@ExceptionHandler(xx.class)
- 이렇게 쓰고 인자로 캐치해서 핸들링하고 싶은 예외 클래스를 등록해주면 끝
- {a.class,b.class}이런식으로 여러개를 처리 할 수도 있음
- 단, Controller(rest포함)에서만 사용이 가능 함
- parameter로 받으려한 오류 클래스를 받거나 간단하게는 Exception클래스로 받으면 됨
CustomException
- 자신이 처리하고 싶은 예외들을 (직접 만든 예외 포함)처리하기 위해 직접 만드는 클래스
- 보통 RuntimeException을 extends해서 구현하나, 더 많은 예외를 처리하고 싶으면 Exception을 확장하면 된다
- 서비스단에서 그냥 뭘 리턴하는데 안되면 그냥 만든 오류 throw하고 @ExceptionHandler로 처리
- 근데 이렇게 일일이 다 예외를 만드는 것 보단 BaseException을 만들고 예외 코드,메세지를 설정해서 처리하는게 더 깔끔하고 효율적 이다.
public class NotFoundMemberException extends RuntimeException {
public NotFoundMemberException() {
super();
}
public NotFoundMemberException(String message, Throwable cause) {
super(message, cause);
}
public NotFoundMemberException(String message) {
super(message);
}
public NotFoundMemberException(Throwable cause) {
super(cause);
}
}
----------------------------------------------------------------
@Transactional(readOnly = true)
public UserDto getUserWithAuthorities(String username) {
return UserDto.from(userRepository.findOneWithAuthoritiesByUsername(username)
.orElseThrow(() -> new NotFoundMemberException("Member not found1")));
}
@Transactional(readOnly = true)
public UserDto getMyUserWithAuthorities() {
System.out.println("called getMyUserWithAuthorities");
return UserDto.from(
SecurityUtil.getCurrentUsername()
.flatMap(userRepository::findOneWithAuthoritiesByUsername)
.orElseThrow(() -> new NotFoundMemberException("Member not found2"))
);
}
@ControllerAdvice
- ExceptionHandling은 명시된 클래스의 오류에 대해서 작동한다면, ControllerAdvice는 모든 컨트롤러에서 발생할 수 있는 예외를 catch하는 어노테이션
- @RestControllerAdvice는 똑같지만 ResponseBody로 객체를 리턴할 수도 있다
- 만약, 전역의 예외를 캐치하지만, 특정 패키지 내에서만 캐치하고 싶다면
- @RestControllerAdvice("com.example.demo.login.controller")
- 이런식으로 특정할 수도 있음
@ControllerAdvice
public class RestResponseExceptionHandler extends ResponseEntityExceptionHandler {
@ResponseStatus(CONFLICT)
@ExceptionHandler(value = { DuplicateMemberException.class })
@ResponseBody
protected ErrorDto conflict(RuntimeException ex, WebRequest request) {
return new ErrorDto(CONFLICT.value(), ex.getMessage());
}
@ResponseStatus(FORBIDDEN)
@ExceptionHandler(value = { NotFoundMemberException.class, AccessDeniedException.class })
@ResponseBody
protected ErrorDto forbidden(RuntimeException ex, WebRequest request) {
return new ErrorDto(FORBIDDEN.value(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
//do something to return error
return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
}
- 이렇게 ResponseEntityExceptionHandler를 확장하기도 하는데 이는, 기존에 spring이 정의해놓은 에러를 오버라이딩을 통해 쉽게 핸들링하기 위해 확장함
- 무엇보다 중요한건 오류 핸들링을 하고 리턴을 보내주는 행위를 획일화?일체화 해주는 것!
- a오류 b오류 마다 다 다른 형식으로 오류를 처리하는 것 보단, errorDTO만들어서 보내는게 훨씬 생산적이다.
@ResponseStatus(CODE)
- response를 할 때, status값을 설정하는 것
@Valid
Not valid한 경우 발생하는 오류를 BindException, 이나 MethodArgumentNotValidException으로 잡을 수 있음전자는 @ModelAttribute로 받은 파라미터에 대해, 후자는 @RequestBody로 받은 파라미터에 대해 처리한다?DTO의 Valid를 설정한 필드마다 FiledError가 발생하는데, 이는 MethodArgumentNotValidException에서 getBindingResult를 호출해서 BindingResult를 얻고 얘한테서 getFieldErrors하면 발생한 FieldError목록을 얻을 수 있다.
이때는 잘 몰랐지만 .. 지금 다시 정리해보면
- 검증하고 싶은 파라미터 (주로 DTO)에 검증 조건을 정의하고 (NotEmpty ..) 해당 파라미터를 받는 컨트롤러 앞에 @Valid나 @Validated 를 붙여주고 바로 뒤에 BindingResult를 같이 받아주면 오류가 있는 경우 bindingResult에 발생한 오류가 들어있다.
- 메세지 설정 파일로 오류 메세지를 직접 설정할 수 도 있고, 그냥 기본 메세지를 사용할 수 도 있다.
- 이렇게 어노테이션으로 필드에러를 검증하는 것을 bean Validation이라 함
- 해당 검증은 @ModelAttribute도 가능하고 @RequestBody에도 적용이 가능하다.
'Spring' 카테고리의 다른 글
[Spring Boot] SMTP를 이용해 이메일 인증을 구현해보자 (0) | 2023.04.17 |
---|---|
Spring Batch (0) | 2023.04.05 |
Spring Security - Cors. setAllowCredentials (0) | 2023.04.05 |
What is JWT?? (2) (With OAuth2.0) (0) | 2023.04.05 |
What is JWT??(1) (0) | 2023.04.05 |