在使用Spring MVC时会遇到需要自己捕获异常并处理的情况。一般可以使用HandlerExceptionResolver去处理。
但是默认情况下,Spring MVC或自己注入3个HandlerExceptionResolver如下:

org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

这时会按顺序调用HandlerExceptionResolver处理能够处理的异常,如果没有处理就返回null,这时会继续调用下一个,如果其中一个返回了ModelAndView则后面的将不会再调用:

// Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
  exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
  if (exMv != null) {
    break;
  }
}

这样就会出现一个问题,我们通过bean配置的HandlerExceptionResolver将会在最后一个执行,如果前面某个HandlerExceptionResolver已经返回ModelAndView了,就调用不到了。

比如参数格式不正确时的400的错误就被DefaultHandlerExceptionResolver处理了。

<!--异常处理-->
<bean id="defaultHandlerExceptionResolver" class="com.***.***.DefaultHandlerExceptionResolver"/>

解决办法,调整HandlerExceptionResolver执行顺序,可以通过实现接口org.springframework.core.Ordered 来解决。
默认的三个OrderInteger.MAX_VALUE,所以我们只有比它小就可以了如Integer.MIN_VALUE
如下:

/**
 * 默认异常处理
 */
public class DefaultHandlerExceptionResolver implements HandlerExceptionResolver,Ordered {
    private static Logger logger = Logger.getLogger(DefaultHandlerExceptionResolver.class);

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        logger.error(e.getMessage(), e); //记录日志
    }

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }
}