在使用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
来解决。
默认的三个Order
为Integer.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;
}
}