[SPRING] Spring MVC의 예외 처리기
SPRINGSpring MVC의 예외 처리기
내 프로젝트의 모든 컨트롤러를 가로채는 예외 처리기를 만들고 싶습니다. 그렇게 할 수 있습니까? 모든 컨트롤러에 처리기 메서드를 넣어야하는 것 같습니다. 당신의 도움을 주셔서 감사합니다. Json 응답을 보내는 스프링 컨트롤러가 있습니다. 따라서 예외가 발생하면 한 곳에서 제어 할 수있는 오류 응답을 보내려고합니다.
해결법
-
==============================
1.(스프링 3.1에서 구현하는 방법을 찾았는데,이 내용은이 답변의 두 번째 부분에서 설명합니다)
(스프링 3.1에서 구현하는 방법을 찾았는데,이 내용은이 답변의 두 번째 부분에서 설명합니다)
Chapter 16.11 Spring 참조의 예외 처리를 보라.
@ExceptionHandler를 사용하는 것보다 더 많은 방법이 있습니다 (gouki의 대답 참조).
Spring 3.2 이상에서는 @ControllerAdvice 클래스에 주석을 달 수 있습니다.이 클래스의 모든 @ExceptionHandler 메소드는 전역 적으로 작동합니다.
Spring 3.1에는 @ControllerAdvice가 없다. 그러나 약간의 해킹으로 비슷한 기능을 가질 수 있습니다.
핵심은 @ExceptionHandler가 작동하는 방식에 대한 이해입니다. Spring 3.1에는 ExceptionHandlerExceptionResolver 클래스가있다. 이 클래스는 슈퍼 클래스의 도움으로 HandlerExceptionResolver 인터페이스를 구현하고 @ExceptionHandler 메소드를 호출합니다.
HandlerExceptionResolver 인터페이스에는 Method가 하나만 있습니다.
ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);`.
요청이 Spring 3.x Controller Method에 의해 처리되면, org.springframework.web.method.HandlerMethod로 대표되는이 메소드는 핸들러 매개 변수이다.
ExceptionHandlerExceptionResolver는 핸들러 (HandlerMethod)를 사용하여 Controller 클래스를 가져 와서 @ExceptionHandler로 주석 된 메소드를 스캔합니다. 이 메소드의 1 개가 예외 (ex)에 일치하는 경우,이 메소드는 예외를 처리하기 위해서 불려갑니다. (이 예외 해결 프로그램이 아무런 책임이 없음을 알리기 위해 null이 반환됩니다).
첫 번째 아이디어는 ExceptionHandlerExceptionResolver처럼 작동하는 자체 HandlerExceptionResolver를 구현하는 것이지만 컨트롤러 클래스에서 @ExceptionHandler를 검색하는 대신 하나의 특수 bean에서이를 검색해야합니다. 단점은, 모든 좋은 메시지 변환기, 인수 확인 자 및 반환 값 처리기를 수동으로 구성해야한다는 것입니다 (실제 구성의 구성은 봄에 자동으로 수행됩니다). 그래서 다른 아이디어를 생각해 냈습니다.
전역 Exception 핸들러를 포함하는 bean을 가리키는 수정 된 핸들러를 사용하여 ExceptionHandlerExceptionResolver에 (이미 구성된) Exception을 "전달"하는 간단한 HandlerExceptionResolver를 구현하십시오. (나는 모든 컨트롤러에 대한 작업 때문에 전역이라고 부른다.).
그리고 이것은 구현입니다 : GlobalMethodHandlerExeptionResolver
import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.Ordered; import org.springframework.util.StringUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; public class GlobalMethodHandlerExeptionResolver implements HandlerExceptionResolver, Ordered { @Override public int getOrder() { return -1; // } private ExceptionHandlerExceptionResolver realExceptionResolver; private List<GlobalMethodExceptionResolverContainer> containers; @Autowired public GlobalMethodHandlerExeptionResolver( ExceptionHandlerExceptionResolver realExceptionResolver, List<GlobalMethodExceptionResolverContainer> containers) { this.realExceptionResolver = realExceptionResolver; this.containers = containers; } @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { for (GlobalMethodExceptionResolverContainer container : this.containers) { ModelAndView result = this.realExceptionResolver.resolveException( request, response, handlerMethodPointingGlobalExceptionContainerBean(container), ex); if (result != null) return result; } // we feel not responsible return null; } protected HandlerMethod handlerMethodPointingGlobalExceptionContainerBean( GlobalMethodExceptionResolverContainer container) { try { return new HandlerMethod(container, GlobalMethodExceptionResolverContainer.class. getMethod("fakeHanderMethod")); } catch (NoSuchMethodException | SecurityException e) { throw new RuntimeException(e); } } }
글로벌 Handler는이 인터페이스를 구현해야한다 (찾기 위해 그리고 핸들러에 사용 된 fakeHanderMethod를 구현하기 위해)
public interface GlobalMethodExceptionResolverContainer { void fakeHanderMethod(); }
그리고 글로벌 핸들러의 예 :
@Component public class JsonGlobalExceptionResolver implements GlobalMethodExceptionResolverContainer { @Override public void fakeHanderMethod() { } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody public ValidationErrorDto handleMethodArgumentNotValidException( MethodArgumentNotValidException validationException, Locale locale) { ... /* map validationException.getBindingResult().getFieldErrors() * to ValidationErrorDto (custom class) */ return validationErrorDto; } }
BTW : Spring은 Exception resolver를 위해 HandlerExceptionResolver를 구현하는 모든 bean을 자동으로 등록하기 때문에 GlobalMethodHandlerExeptionResolver를 등록 할 필요가 없습니다. 그래서 간단한
로 충분하다. -
==============================
2.Spring 3.2부터 @ControllerAdvice 주석을 사용할 수있다. @ControllerAdvice 클래스 내에서 @ExceptionHandler 메서드를 선언 할 수 있습니다. 이 경우 모든 컨트롤러에서 @RequestMapping 메서드의 예외를 처리합니다.
Spring 3.2부터 @ControllerAdvice 주석을 사용할 수있다. @ControllerAdvice 클래스 내에서 @ExceptionHandler 메서드를 선언 할 수 있습니다. 이 경우 모든 컨트롤러에서 @RequestMapping 메서드의 예외를 처리합니다.
@ControllerAdvice public class MyGlobalExceptionHandler { @ExceptionHandler(value=IOException.class) public @ResponseBody String iOExceptionHandler(Exception ex){ // // } // other exception handler methods // ... }
-
==============================
3.예외 처리기를 정의하는 추상 클래스입니다. 그리고 컨트롤러가 그것을 상속하도록하십시오.
예외 처리기를 정의하는 추상 클래스입니다. 그리고 컨트롤러가 그것을 상속하도록하십시오.
from https://stackoverflow.com/questions/6742324/exception-handler-in-spring-mvc by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring bean에서 proxy-target-class = "true"사용하기 (0) | 2019.01.27 |
---|---|
[SPRING] 스프링 MVC 주석 매핑 테스트하기 (0) | 2019.01.27 |
[SPRING] 최대 절전 모드에서 동시 업데이트 처리 (0) | 2019.01.27 |
[SPRING] applicationContext.xml에는 datasource 또는 hibernate.cfg.xml이있다. 차? (0) | 2019.01.27 |
[SPRING] 단위 테스트 Spring @ AOP 방식의 메소드 (0) | 2019.01.27 |