处理spring mvc中的包装异常

时间:2013-03-20 16:33:47

标签: java spring exception spring-mvc exception-handling

我有Spring MVC和jackson。当我开始一个不正确的请求时,杰克逊映射失败并抛出UnrecognizedPropertyException。我想使用

处理此异常
@ExceptionHandler
public String handle(UnrecognizedPropertyException e) {
  ...
}

然而,Spring在HttpMessageConversionException中包含此异常,因此上面的代码不起作用。是否有可能在Spring中处理杰克逊特定的(或一般的库特定的)异常?

3 个答案:

答案 0 :(得分:3)

不幸的是,UnrecognizedPropertyExceptionIOException的子类型。处理RequestResponseBodyMethodProcessor的{​​{1}}(我假设发生异常的地方)对@RequestBody进行了特殊处理(解释为请求输入流的失败),将其包装在{{} 1}}。此外,如果在HttpMessageConverter期间出现转换错误,则指定read接口抛出IOException

无论如何,你将不得不处理这个问题(如果杰克逊提出未经检查的例外情况,事情可能会有所不同)。

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

cause

将用于处理异常。在Spring MVC查找可以处理HttpMessageNotReadableException的处理程序方法,然后用Throwable#getCause解包嵌套异常并再次尝试查找之后,就会发生这种情况。


在4.3之前,或者如果你在@ExceptionHandler public String handle(UnrecognizedPropertyException e) { ... } 的继承层次结构中有一个异常类型的处理程序,你总是可以在自己提取原因之后进行委托。

HttpMessageNotReadableException

答案 1 :(得分:0)

我是这样做的:

/**
 * 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-context中:

   <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按顺序循环遍历异常解析器。你也可以为自己定义这种异常映射,你就可以了!

查看this博文和SimpleMappingExceptionResolver

的javadoc

答案 2 :(得分:0)

我们正在使用org.apache.commons.lang.exception.ExceptionUtils ...

private myMethod (Throwable t) {

    if (ExceptionUtils.getRootCause(t) instanceof MyException) ...
}