文章目录
- 2020.12.29修改
- 问题:拦截器里面抛出异常,全局异常处理能捕获吗?
- 测试
- 结论
- 源码分析
- 2022-03-14
- 先说这篇文章的讨论点,拦截器里面抛出异常走不走异常解析器
- 请求走/error
2020.12.29修改
发现这篇文章很多新手哥们看,当时我也是刚写博客,格式比较差,而且也没有将代码贴出来,很多人都说以偏概全~我想的是,这个这么简单的代码,自己随便找个代码试一下不就好了,想了想,还是重新编辑一下好了:
问题:拦截器里面抛出异常,全局异常处理能捕获吗?
很多朋友私信问我拦截器里面抛出异常,全局异常处理能捕获吗?
然后我认问是可以的,但是需要用代码说话:
先随便写个拦截器:拦截器的几个方法就不多说了我demo试的是preHandle方法,在一开始请求就会进来:
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
log.info("request uri : {}", requestURI);
throw new RuntimeException("aaa");
// return true;
}
}
然后我的全局异常处理是这样的异常处理简单了解:
@ControllerAdvice
public class GlobalHandlerExceptionResolver {
private final Logger log = LoggerFactory.getLogger(getClass());
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult allExceptionHandler(Exception e) {
log.info("================进入异常处理================");
ResponseResult result = new ResponseResult(e.getMessage(), 500);
throw new NullPointerException("bbb");
// return result;
}
}
测试
请求/ 的时候发现跳转到/error 页面报错;请求不存在的url的时候就会跳转到/error然后报错;
请求/aaa(/aaa在controller里面配置了,存在RequestMapping为"/aaa")的时候发现抛异常就直接进入到异常解析器;
结论
在controller里面配置了,存在RequestMapping为"/aaa")的时候发现抛异常就直接进入到异常解析器;
否则就不会进入异常解析器;
源码分析
最近在看spring源码,看完再来分析
2022-03-14
发现好多兄弟还在看这篇文章,现在有一点springmvc的源码基础,对原先的问题进行一个简单回顾.项目中有存在RequestMapping为"/aaa"),没有对应的/ccc的处理方法.
- 请求/ccc没有对应的处理器的时候,会直接请求到/error,没有执行到异常解析器.
- 请求到/error的时候,拦截器抛出异常,进入异常解析器.
- 请求/aaa的时候,拦截器抛出异常,进入异常解析器.
我先总结一下,
当有对应的处理器的时候,拦截器里面抛出异常会走到异常解析器.
当没有对应处理器的时候,拦截器里面抛出异常不会走到异常解析器.
我测试使用的是springboot项目,当找不到的对应的controller地址映射,handler映射也不到就走/error结束。
springboot项目有个默认的/error解析器,BasicErrorController,这时候/error相当于有了处理器.就会执行到异常解析器.
请求/aaa的时候同/error,在拦截器里面抛出异常会走到异常解析器.
先说这篇文章的讨论点,拦截器里面抛出异常走不走异常解析器
在DispatcherServlet的方法doDispatch里面,有个异常处理的方法,processDispatchResult;
接下来就执行到了AbstractHandlerExceptionResolver解析器,我们写的异常解析器都会被转成这个的子类
@Override
@Nullable
public ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
if (shouldApplyTo(request, handler)) {
prepareResponse(ex, response);
ModelAndView result = doResolveException(request, response, handler, ex);
if (result != null) {
// Print debug message when warn logger is not enabled.
if (logger.isDebugEnabled() && (this.warnLogger == null || !this.warnLogger.isWarnEnabled())) {
logger.debug("Resolved [" + ex + "]" + (result.isEmpty() ? "" : " to " + result));
}
// Explicitly configured warn logger in logException method.
logException(ex, request);
}
return result;
}
else {
return null;
}
}
shouldApplyTo方法就会去判断执不执行对应的异常处理器,AbstractHandlerExceptionResolver的shouldApplyTo方法就是判断对应的handler处理器是不是HandlerMethod,如果是的话就会会执行对应的异常处理器,如果不是就返回false就不会执行对应的异常处理器了.而/ccc请求没有对应的handler处理器,所以返回false了…
protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) {
if (handler != null) {
if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
return true;
}
if (this.mappedHandlerClasses != null) {
for (Class<?> handlerClass : this.mappedHandlerClasses) {
if (handlerClass.isInstance(handler)) {
return true;
}
}
}
}
// Else only apply if there are no explicit handler mappings.
return (this.mappedHandlers == null && this.mappedHandlerClasses == null);
}
请求走/error
springmvc没有对应的处理器的时候,会直接请求到/error,