쿠릉쿠릉 쾅쾅
쿠릉쿠릉 쾅쾅
쿠릉쿠릉 쾅쾅
250x250
전체 방문자
오늘
어제
  • 분류 전체보기
    • HTML CSS
    • 잡담
    • 프로그래밍 꿀팁 사이트
    • 코딩 도서
    • [자바]
      • 디자인 패턴
      • 자바의 정석 - 3판
      • 자바
      • 자바 문법
    • git
    • [TDD]
    • 개발 서적 독후감
      • 클린 코더
      • 토비 스프링3
      • 객체지향의 사실과 오해
      • 모던 자바 인 액션
      • 엘레강트 오브젝트
    • CS
      • 운영체제
      • HTTP
    • [SQL]
      • SQL 기초
      • 혼자공부하는SQL
    • [ Spring ]
      • REST API
      • Spring Toy
      • Spring 에러
      • Spring
      • Spring 입문
      • Spring 핵심 원리
      • SpringMVC 1편
      • SpringMVC 2편
      • Spring Boot를 이용한 RESTful We..
      • Batch
    • [JPA]
      • JPA
      • JPA 에러
      • JPA 프로그래밍 - 기본편
      • 스프링 부트와 JPA 활용 1 - 웹 애플리케이..
      • 실전! 스프링 부트와 JPA 활용2 - API 개..
      • 실전! 스프링 데이터 JPA
      • 실전! Querydsl
    • 인텔리제이
    • [DB]
      • DB
      • H2
    • Gradle
    • 면접
    • [알고리즘]
      • 알고리즘
      • 자료구조
      • 자바 알고리즘 공부
    • [프로젝트]
    • 쿠릉식 객체지향 사고
    • 리눅스

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 스프링
  • Git
  • Spring
  • GitHub
  • REST API
  • 깃허브
  • 함수형인터페이스
  • 스프링부트
  • 백준
  • JPA
  • querydsl
  • java
  • springboot
  • SQL
  • http
  • MVC
  • 알고리즘
  • 자료구조
  • 재귀
  • 자바

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
쿠릉쿠릉 쾅쾅

쿠릉쿠릉 쾅쾅

[ Spring ]/REST API

[Spring] AOP를 이용한 Exception Handing

2022. 5. 8. 04:31
728x90

 

 

@ControllerAdvice 애노테이션과 ResponseEntityExceptionHandler 추상 클래스 상속을 통해 예외처리를 할 수 있다.
@ControllerAdvice 애노테이션을 사용하여 Exception 처리를 한 곳으로 모으는 경우, ResponseEntityExceptionHandler를 상속 받도록 하여 Spring MVC에서 기본으로 제공되는 Exception들의 처리를 간단하게 등록할 수 있다.
ResponseEntityExceptionHandler 추상 클래스에는 각 Exception 처리를 위한 메서드들을 모두 protected로 선언되어 있어서 필요에 따라 Override를 해야한다.

📌 ExceptionResponse

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExceptionResponse {

    private LocalDateTime timestamp;
    private String message;
    private String details;

}

오류를 담을 객체다.

📌 UserNotFoundException

public class UserNotFoundException extends RuntimeException {

    public UserNotFoundException(String message) {
        super(message);
    }

}

사용자 정의 예외 클래스다.

📌 CustomizedResponseEntityExceptionHandler

@RestControllerAdvice
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    // 오류 정보를 담을 객체를 만드는 메서드
    private ExceptionResponse createExceptionResponse(Exception ex, WebRequest request) {
        return new ExceptionResponse(LocalDateTime.now(), ex.getMessage(), request.getDescription(false));
    }


    @ExceptionHandler(Exception.class)
    public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
        ExceptionResponse exceptionsResponse = createExceptionResponse(ex, request);
        return new ResponseEntity<>(exceptionsResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }


    @ExceptionHandler(UserNotFoundException.class)
    public final ResponseEntity<Object> handleUserNotFoundException(Exception ex, WebRequest request) {
        ExceptionResponse exceptionsResponse = createExceptionResponse(ex, request);
        return new ResponseEntity<>(exceptionsResponse, HttpStatus.NOT_FOUND);
    }

}

 

스프링 MVC Excpetion Handler 기능을 한다. 
@ControllerAdivce를 사용하면 Global Controller Exception Handling을 할 수 있다.
ResponseEntityExceptionHandler 추상 클래스를 상속 받고 있다. ResponseEntityExceptionHandler 추상 클래스는 Spring MVC에서 발생할 수 있는 예외에 대해 미리 Handling 해놓은 클래스다. 
즉, @ControllerAdvice 애노테이션으로 모든 컨트롤러에서 발생하는 Exception을 캐지하고 캐치한 Exception들(사용자 정의 Exception 클래스 제외)을 기본적으로 ResponseEntityExceptionHandler에서 정의된 메서드로 처리할 수 있다.
WebRequest는 HttpServletRequest 클래스와 비슷하지만 HttpServletRequest와 달리 서블릿에 종속되지 않는다. HttpServletRequest보다 WebRequest를 사용할 것을 권장한다. WebRequest를 통해 예외가 어느 URI에서 발생했는지 알 수 있다. WebReqeust#getDescription(boolean includeClientInfo) 를 통해 예외가 발생한 URI 주소를 가져올 수 있다. 파라미터를 true로 할 경우 클라이언트에 대한 정보도 가져온다. 

 

🧷 오류 메시지 캐싱

더보기

📌 ExampleException

public class ExampleException extends RuntimeException{

    public ExampleException() {
        super();
    }

    public ExampleException(String message) {
        super(message);
    }

    public ExampleException(String message, Throwable cause) {
        super(message, cause);
    }

    public ExampleException(Throwable cause) {
        super(cause);
    }

    protected ExampleException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

 사용자 정의 오류 클래스

📌 ExceptionResponse

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExceptionResponse {

    private LocalDateTime timestamp;
    private String message;
    private String details;

}

 오류를 담을 객체

 📌 CustomizedResponseEntityExceptionHandler

@RestControllerAdvice
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    // 오류 정보를 담을 객체를 만드는 메서드
    private ExceptionResponse createExampleException(Exception ex, WebRequest request) {
        return new ExceptionResponse(LocalDateTime.now(), resolveMessage(ex, ex.getMessage()), request.getDescription(false));
    }

    /**
     * 오류 메시지 캐싱
     */
    private final Map<Class<? extends Exception>, String> messageMappings 
            = Collections.unmodifiableMap(new LinkedHashMap<>(){
                
        {
            put(ExampleException.class, "심플예제 입니다.");
        }
        
    });


    private String resolveMessage(Exception ex, final String defaultMessage) {
        return messageMappings.entrySet()
                .stream()
                .filter(entry -> entry.getKey().isAssignableFrom(ex.getClass()))
                .findFirst()
                .map(Map.Entry::getValue)
                .orElse(defaultMessage);
    }
    
    @ExceptionHandler(ExampleException.class)
    public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
        ExceptionResponse exceptionsResponse = createExceptionResponse(ex, request);
        return new ResponseEntity<>(exceptionsResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

 messageMappings : key를 Exception Class로 하고, value를 String 타입인 에러 메시지로 했다. 순서가 있는 순서가 있는 LinkedHashMap을 만들고 이 map을 unmodifiableMap으로 불변 객체로 만들어 캐싱한다.
 resovleMeessage : 파라미터로 Exception과 defaulMessage를 받는다. messageMappings에서 일치하는 Exception이 있는지 확인하고 존재하면 value 값을 가져와서 사용하고 없다면 인자로 받은 defaultMessage를 사용한다.

 

 

 

 

 

👀 참고 자료

https://velog.io/@modsiw/Spring-Controller%EC%97%90%EC%84%9C-%EB%8B%A4%EC%96%91%ED%95%9C-%ED%83%80%EC%9E%85%EC%9C%BC%EB%A1%9C-Request-%EC%9A%94%EC%B2%AD%EB%B0%9B%EA%B8%B0-PathVariable-RequestParam-ModelAttribute-RequestBody

 

[Spring] Controller에서 다양한 타입으로 Request 요청( PathVariable, RequestParam, ModelAttribute, RequestBody)

Spring에서 Client로 받은 요청을 객체로 바인딩하기 위해 사용하는 방법 ServletRequest, ServletResponseHttpServletRequest, HttpServletResponse : 위에꺼를 상속받음HttpServletRequest.getI

velog.io

 

https://programmingrecoding.tistory.com/20

 

parameter 추출하기(HttpServletRequest, WebRequest ,@RequestParam, @PathVariable)

Contorller에서 Request를 받는방식에는 @RequesetMapping, @PostMapping, @GetMapping이 있다. @RequestMapping의 사용형태 ex) value는 Request해주는 요청값이고(form태그의 action="test1"이렇게 받았다면 위..

programmingrecoding.tistory.com

 

https://blog.naver.com/PostView.naver?blogId=writer0713&logNo=221605253778&parentCategoryNo=&categoryNo=83&viewDate=&isShowPopularPosts=true&from=search 

 

[Spring] Rest API Exception Handling

Spring MVC (+ Spring Boot)를 사용하여 Rest API를 만들때마다 Exception Handling을 하면서...

blog.naver.com

 

 

728x90

'[ Spring ] > REST API' 카테고리의 다른 글

[Spring] Rest API Documentation을 위한 Swagger 사용  (0) 2022.05.10
[Spring] API 구현을 위한 Hateoas 적용  (0) 2022.05.10
[Spring] Rest Api Version 관리  (0) 2022.05.10
[Spring] Response 데이터 제어를 위한 Filtering  (0) 2022.05.09
[Spring] URI 조립을 위한 ServletUriComponentsBuilder  (0) 2022.05.08
    '[ Spring ]/REST API' 카테고리의 다른 글
    • [Spring] API 구현을 위한 Hateoas 적용
    • [Spring] Rest Api Version 관리
    • [Spring] Response 데이터 제어를 위한 Filtering
    • [Spring] URI 조립을 위한 ServletUriComponentsBuilder
    쿠릉쿠릉 쾅쾅
    쿠릉쿠릉 쾅쾅
    깃허브 주소 : https://github.com/kureung

    티스토리툴바