在春天处理包装异常mvc

问题描述:

我有春天mvc和杰克逊。当我得到不正确的请求时,jackson映射失败并引发UnrecognizedPropertyException。我想处理使用在春天处理包装异常mvc

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

但是春天包装此异常HttpMessageConversionException所以上面的代码不起作用此异常。是否有可能在春季处理杰克逊特定(或一般图书馆特定)的例外?

不幸的是,UnrecognizedPropertyExceptionIOException的亚型。处理@RequestBody(我假设这是发生异常的位置)的RequestResponseBodyMethodProcessorIOException(解释为请求输入流的故障)有特殊处理,将其包装在HttpMessageNotReadableException中。此外,如果在read期间存在转换错误,则指定HttpMessageConverter接口将抛出HttpMessageNotReadableException。不管怎样(如果杰克逊抛出未经检查的异常,事情可能会有所不同),你将不得不处理这个问题。

幸运的是,since 4.3, Spring MVC's ExceptionHandlerMethodResolver(其中进程@ExceptionHandler)可以打开cause的例外(see SPR-14291)。因此,假设你没有为在HttpMessageNotReadableException继承层次结构的任何异常处理程序,你的处理方法

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

将被用来处理异常。这发生在Spring MVC查找可以处理HttpMessageNotReadableException的处理程序方法后,然后用Throwable#getCause解开嵌套的异常并再次尝试查找。


在前期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) { 
    ... 
} 
+0

难看,但作品和我有什么好 – piotrek 2013-04-03 12:44:13

+0

@piotrek你确定这个工程?我们已经在Spring 4.2中尝试了这一点,但它没有。 Spring只记录了一条调试消息并抛弃了异常('ExceptionHandlerExceptionResolver'中的'logger.debug(“无法调用@ExceptionHandler方法:”+ exceptionHandlerMethod,invocationEx)') – 2017-01-16 10:45:36

+0

我再也无法访问该代码,对不起: ( – piotrek 2017-01-16 15:39:26

我做这种方式:

/** 
* 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; 
    } 
} 

而且在我的servlet上下文:

<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> 

顺序字段是因为通过上按顺序异常解析器春周期很重要。你也可以为自己定义一个这样的异常映射,你很好走!

检查this博客文章和javadoc为SimpleMappingExceptionResolver

+0

我想我们有误会。问题是我不能这样做' piotrek 2013-03-21 11:15:45

+0

哦..明白了.. Spring包装了异常,我检查了spring的源代码,除非你重写类的方法,否则你不能这么做。@ Sotirios的方法似乎是最好的 – 2013-03-21 12:07:40