728x90
예외 3유형
1. Validation Exception : 클라이언트요청 데이터에 대한 유효성 검증에서 발생하는 예외
2. Custom Exception : 서비스 계층의 비즈니스 로직에서 던져지는 의도된 예외
3. Runtime Exception : 웹 어플리케이션 실행 중에 발생하는 예외
Keyword
@ExceptionHandler
@RestControllerAdvice
@ExceptionHandler
: controller Level에서의 예외처리
: controller클래스 내의 handleException메서드 level에 적용
사용법
1. Controller 클래스에 @ExceptionHandler 애너테이션 적용
: 메서드 레벨에 @ExceptionHandler을 적용한다. => 현재 모든 ResponseBody가 전송되는 상태
@RestController
@RequestMapping("/v6/members")
@Validated
@Slf4j
public class MemberController {
...
@PostMapping
public ResponseEntity postMember(@Valid @RequestBody MemberPostDto memberDto) {
Member member = mapper.memberPostDtoToMember(memberDto);
Member response = memberService.createMember(member);
return new ResponseEntity<>(mapper.memberToMemberResponseDto(response),
HttpStatus.CREATED);
}
...
// 이 부분 작성
@ExceptionHandler
public ResponseEntity handleException(MethodArgumentNotValidException e) {
final List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
return new ResponseEntity<>(fieldErrors, HttpStatus.BAD_REQUEST);
}
}
* 예시 응답
더보기
[
{
"codes": [
"Email.memberPostDto.email",
"Email.email",
"Email.java.lang.String",
"Email"
],
"arguments": [
{
"codes": [
"memberPostDto.email",
"email"
],
"arguments": null,
"defaultMessage": "email",
"code": "email"
},
[],
{
"arguments": null,
"defaultMessage": ".*",
"codes": [
".*"
]
}
],
"defaultMessage": "올바른 형식의 이메일 주소여야 합니다",
"objectName": "memberPostDto",
"field": "email",
"rejectedValue": "hgd@",
"bindingFailure": false,
"code": "Email"
}
]
2. ErrorResponse 클래스 적용
: ErrorResponse클래스를 만들어서 원하는 Error정보만 담아 전송하기위한 메서드를 작성한다
: 즉, DTO클래스의 유효성 검사 후, 실패한 피르(멤버변수)에 대한 Error정보만 전달
package com.codestates.member.error;
import lombok.Getter;
import lombok.AllArgsConstructor;
import java.util.List;
// DTO클래스의 유효성 검증 실패시, 실패한 필드(멤버변수)에 대한 Error 정보만 담아서 응답으로 전송하기 위한 ErrorResponse클래스
// DTO클래스에서 검증해야 되는 멤버변수에서 유효성 검증에 실패하는 멤버 변수들이 하나 이상이 될 수 있기 때문에, 유효성 검증 실패에러 또한 하나 이상이 될 수 있다
// => ResponseBody의 JSON 응답 객체가 배열로 되어있는 이유
@Getter
@AllArgsConstructor
public class ErrorResponse {
// 한 개 이상의 유효성 검증에 실패한 필드의 에러정보를 담기 위해서 List객체를 이용
private List<FieldError> fieldErrors;
// 각각의 별도의 에러 정보를 나타내는 멤버 클래스
// static 멤버 클래스 = ErrorResponse의 멤버 (이너 클래스라는 말이아닌 이렇게 부름)
@Getter
@AllArgsConstructor
public static class FieldError {
private String field;
private Object rejectedValue; // 야는 오브젝트 타입이다
private String reason;
}
}
3. ErrorResponse클래스를 사용하도록, Controller의 handleException() 메서드 수정
@ExceptionHandler
public ResponseEntity handleException(MethodArgumentNotValidException e) {
// List<FieldError>를 통째로 ResponseEntity클래스에 담아서 전달
final List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
// 여기서 부터 바뀐 부분
// 필요한 정보들만 선택적으로 골라서 ErrorResponse.FieldError클래스에 담아서 List로 변환 후 ResponseEntity클래스에 전달
List<ErrorResponse.FieldError> errors =
fieldErrors.stream().map(error -> new ErrorResponse.FieldError(
error.getField(),error.getRejectedValue(),error.getDefaultMessage()))
.collect(Collectors.toList());
// 리턴 파라미터가 바뀌었다
return new ResponseEntity<>(new ErrorResponse(errors), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler 단점
: 모든 예외를 다 커스터마이징하기엔, Controller마다 중복이 많이 발생함.
: 즉, 다양한 유형의 예외를 다 처리하기에 비효율적임
학습 링크
1. @ExceptionHandler 애너테이션 공식문서
728x90
'Codestates [Back-end] > 데일리 로그 [TIL]' 카테고리의 다른 글
22.08.25 Spring MVC - 예외처리(3) 비즈니스 로직 (2) | 2022.08.25 |
---|---|
22.08.24 Spring MVC - 예외처리(2) (0) | 2022.08.24 |
22.08.23 SpringMVC - 서비스계층 (2) (0) | 2022.08.23 |
22.08.23 SpringMVC - 서비스계층 (1) (0) | 2022.08.23 |
22.08.22 SpringMVC - API계층 (DTO) [진행중] (0) | 2022.08.22 |