处理spring mvc中的包装exception

我有Spring MVC和jackson。 当我开始一个不正确的请求时,Jackson映射失败并抛出UnrecognizedPropertyException 。 我想使用处理此exception

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

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

不幸的是, UnrecognizedPropertyExceptionIOException的子类型。 处理@RequestBodyRequestResponseBodyMethodProcessor (我假设发生exception的地方)具有对IOException特殊处理(解释为请求输入流的失败),将其包装在HttpMessageNotReadableException 。 此外,如果在read期间发生转换错误,则指定HttpMessageConverter接口抛出HttpMessageNotReadableException

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

幸运的是, 自4.3以来,Spring MVC的ExceptionHandlerMethodResolver (处理@ExceptionHandler )可以解开exception的cause ( 参见SPR-14291 )。 因此,假设您没有HttpMessageNotReadableException的inheritance层次结构中的任何exception处理程序,那么您的处理程序方法

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

将用于处理exception。 这发生在Spring MVC查找可处理HttpMessageNotReadableException的处理程序方法HttpMessageNotReadableException ,然后使用Throwable#getCause解包嵌套exception并再次尝试查找。


在4.3之前的版本中,或者如果你在HttpMessageNotReadableException的inheritance层次结构中有一个exception类型的处理程序,你总是可以在自己提取原因后委托。

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

我是这样做的:

 /** * 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上下文中:

                 

订单字段很重要,因为Spring按顺序循环遍历exception解析器。 你也可以为自己定义这种exception映射,你很高兴!

查看此博客文章和javadoc for SimpleMappingExceptionResolver