9

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

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

但是 Spring 包装了这个异常,HttpMessageConversionException所以上面的代码不起作用。是否可以在 Spring 中处理 Jackson 特定(或一般库特定)异常?

4

3 回答 3

7

不幸的是,UnrecognizedPropertyExceptionIOException. RequestResponseBodyMethodProcessor处理(我假设这@RequestBody是发生异常的地方)对IOException(解释为请求输入流的失败)进行特殊处理,将其包装在HttpMessageNotReadableException. 此外,HttpMessageConverter如果HttpMessageNotReadableExceptionread.

无论如何,你都必须处理这个问题(如果杰克逊抛出未经检查的异常,事情可能会有所不同)。

幸运的是,从 4.3 开始,Spring MVCExceptionHandlerMethodResolver(哪些进程@ExceptionHandler)可以解包cause异常(参见 SPR-14291)。因此,假设您在 的继承层次结构中没有任何异常的HttpMessageNotReadableException处理程序,您的处理程序方法

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

将用于处理异常。这发生在 Spring MVC 查找可以处理 a 的处理程序方法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) {
    ...
}
于 2013-03-20T16:50:46.540 回答
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>

order 字段很重要,因为 Spring 按该顺序循环通过异常解析器。您还可以为自己定义此类异常映射,一切顺利!

检查博客文章和 javadoc 以获取SimpleMappingExceptionResolver

于 2013-03-20T21:16:21.343 回答
0

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

private myMethod (Throwable t) {

    if (ExceptionUtils.getRootCause(t) instanceof MyException) ...
}
于 2019-03-11T15:09:04.517 回答