복붙노트

[SPRING] 봄 mvc에서 래핑 된 예외 처리

SPRING

봄 mvc에서 래핑 된 예외 처리

Spring MVC와 jackson이 있습니다. 잘못된 요청을 시작하면 Jackson 매핑이 실패하고 UnrecognizedPropertyException이 발생합니다. 이 예외를 처리하려면

@ExceptionHandler
public String handle(UnrecognizedPropertyException e) {
  ...
}

그러나 Spring은 HttpMessageConversionException에서이 예외를 감싸기 때문에 위의 코드는 작동하지 않습니다. Spring에서 Jackson 특정 (또는 일반적으로 라이브러리 관련) 예외를 처리 할 수 ​​있습니까?

해결법

  1. ==============================

    1.불행히도 UnrecognizedPropertyException은 IOException의 부속 유형입니다. @RequestBody를 처리하는 RequestResponseBodyMethodProcessor (예외가 발생하는 곳이라고 가정)는 IOException (요청 입력 스트림의 실패로 해석)을 처리하여 HttpMessageNotReadableException에 래핑합니다. 또한 HttpMessageConverter 인터페이스는 읽기 중에 변환 오류가있는 경우 HttpMessageNotReadableException을 throw하도록 지정됩니다.

    불행히도 UnrecognizedPropertyException은 IOException의 부속 유형입니다. @RequestBody를 처리하는 RequestResponseBodyMethodProcessor (예외가 발생하는 곳이라고 가정)는 IOException (요청 입력 스트림의 실패로 해석)을 처리하여 HttpMessageNotReadableException에 래핑합니다. 또한 HttpMessageConverter 인터페이스는 읽기 중에 변환 오류가있는 경우 HttpMessageNotReadableException을 throw하도록 지정됩니다.

    (잭슨이 체크되지 않은 예외를 던지면 상황이 달라졌을 수도 있습니다.) 상관없이 처리해야합니다.

    다행히 4.3 이후, Spring MVC의 ExceptionHandlerMethodResolver (@ExceptionHandler를 처리 함)는 예외의 원인을 풀 수 있습니다 (SPR-14291 참조). 따라서 HttpMessageNotReadableException의 상속 계층에서 예외에 대한 처리기가 없다고 가정하면 처리기 메서드

    @ExceptionHandler
    public String handle(UnrecognizedPropertyException e) {
        ...
    }
    

    예외를 처리하는 데 사용됩니다. 이것은 Spring MVC가 HttpMessageNotReadableException을 처리 할 수있는 핸들러 메소드를 찾은 다음에 Throwable # getCause를 사용하여 중첩 예외를 unwrap하고 다시 조회를 시도한 후에 발생합니다.

    4.3 이전 버전에서 또는 HttpMessageNotReadableException의 상속 계층 구조에서 예외 유형에 대한 핸들러가있는 경우 원인을 직접 추출한 후 언제든지 위임 할 수 있습니다.

    @ExceptionHandler
    public String handle(HttpMessageConversionException e) throws Throwable {
        Throwable cause = e.getCause();
        if (cause instanceof UnrecognizedPropertyException) {
            handle((UnrecognizedPropertyException) cause);
        }
        ...
    }
    
    public String handle(UnrecognizedPropertyException e) {
        ...
    }
    
  2. ==============================

    2.나는 이렇게 해.

    나는 이렇게 해.

    /**
     * Global exception handler for unhandled errors.
     * @author Varun Achar
     * @since 2.0
     * @version 1.0
     *
     */
    public class Http500ExceptionResolver extends SimpleMappingExceptionResolver
    {
        @Inject
        private ViewResolver resolver;
    
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
        {
            ModelAndView mv = new ModelAndView();
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            if(CommonUtil.isAjax(request))
            {
                MappingJackson2JsonView view = new MappingJackson2JsonView();
                view.setObjectMapper(JsonUtil.getObjectMapper());
                mv.addObject("responseMessage", "We had some problems while serving your request. We are looking into it");
                mv.addObject("responseCode", GenericResponse.ERROR.code());
                mv.addObject("success", false);
                mv.setView(view);
            }
            else
            {
                mv.setViewName(resolver.getView(ViewConstants.ERROR_PAGE));
            }
            return mv;
        }
    }
    

    그리고 내 서블릿 컨텍스트에서 :

       <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
            <property name="order" value="0" />
        </bean>
        <bean id="securityExceptionResolver"
            class="com.trelta.commons.utils.security.SecurityExceptionResolver">
            <property name="order" value="1"></property>
            <property name="exceptionMappings">
                <map>
                    <entry key="org.springframework.security.access.AccessDeniedException"
                        value="/common/accessDenied"></entry>
                    <entry key="org.springframework.security.core.AuthenticationException"
                        value="/common/authenticationFailure"></entry>
                </map>
            </property>
        </bean>
        <bean id="http500ExceptionResolver"
                class="com.trelta.commons.utils.security.Http500ExceptionResolver">
                <property name="order" value="3" />
        </bean>
    

    순서 필드는 Spring이 예외 확인자를 순서대로 순환하므로 중요합니다. 이 유형의 예외 매핑을 직접 정의 할 수도 있습니다.

    이 블로그 게시물과 javadoc에서 SimpleMappingExceptionResolver를 확인하십시오.

  3. ==============================

    3.우리는 org.apache.commons.lang.exception.ExceptionUtils를 사용하고 있습니다 ...

    우리는 org.apache.commons.lang.exception.ExceptionUtils를 사용하고 있습니다 ...

    private myMethod (Throwable t) {
    
        if (ExceptionUtils.getRootCause(t) instanceof MyException) ...
    }
    
  4. from https://stackoverflow.com/questions/41681309/how-to-handle-wrapped-exceptions-in-a-spring-exception-handler by cc-by-sa and MIT license