DispatcherServlet异常处理
由于无法通过filter捕捉并处理DispatcherServlet内部的异常,如项目中文件上传前端通过axios取消请求导致后端的EOF异常(在进入Controller之前接收文件流)。
一般来说会从request底层的方法向上抛出异常,因此我尝试在filter对此异常进行捕获,
但是在DispatcherServlet这里如果没做处理的话默认会一直抛给Tomcat的StandardWrapperValve打印异常,这里我们是想阻止此类异常打印并自行处理。
这里分析下dispatcherServlet处理异常部分的源码
源码部分
@Nullable
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) throws Exception {
//方法里的ex参数就是内部发生的具体异常对象
request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
//这个exMv代表的就是错误视图和模型对象,如果为null则会记录异常日志
ModelAndView exMv = null;
//可以看到DispatcherServlet中的异常处理是由handlerExceptionResolvers这个异常处理解决程序列表来处理的
if (this.handlerExceptionResolvers != null) {
Iterator var6 = this.handlerExceptionResolvers.iterator();
while(var6.hasNext()) {
HandlerExceptionResolver resolver = (HandlerExceptionResolver)var6.next();
exMv = resolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
}
//如果exMV为null就说明之前的异常处理程序并没有解决异常,如果我们自己设置了异常处理程序可以返回一个空视图而不是默认的null
if (exMv != null) {
if (exMv.isEmpty()) {
//如果我们自己设置异常处理后返回空视图,则在这里被被设置异常信息
request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
return null;
} else {
if (!exMv.hasView()) {
String defaultViewName = this.getDefaultViewName(request);
if (defaultViewName != null) {
exMv.setViewName(defaultViewName);
}
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Using resolved error view: " + exMv, ex);
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Using resolved error view: " + exMv);
}
WebUtils.exposeErrorRequestAttributes(request, ex, this.getServletName());
return exMv;
}
} else {
//如果没有任何异常处理程序做处理返回null的话,则这里会抛出异常
throw ex;
}
}
解决方案
WebMvc中添加异常解决程序,不想让某个异常打印日志就返回一个空的ModelAndView
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
resolvers.add(new MyHandlerExceptionResolver());
}
}
class MyHandlerExceptionResolver implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if (ex instanceof MultipartException) {
//这里是要捕获的异常类型,返回一个空视图模型
return new ModelAndView();
}
// handle other exceptions
return null;
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com