问题
过滤器中抛出异常,未经过全局异常处理器,前端未接收到异常信息。
问题分析
过滤器Filter和过滤器Interceptor拦截器的使用总是后端开发不可避免的一部分,有时候我们需要在过滤器或拦截器中进行逻辑处理,抛出异常,那么这里抛出的异常可以被@ControllerAdvice注释的异常处理类捕获吗?答案是Filter不会,而Interceptor可以,Filter是基于Servlet框架编写的,Interceptor是基于SpringMVC框架的,SpingMVC不会对Filter中的异常统一处理,所以这里被抛出的异常不能被捕获,那我们如何让不能被捕获的异常被被捕获呢?
解决措施
方法一:HandlerExceptionResolver
我们在要抛出异常的过滤器里面,引入HandlerExceptionResolver,直接抛出一个全局异常。
举例
我是要在JwtAuthorizationTokenFilter这个过滤器中抛出一个对Token异常的判断。
测试
效果
代码
@Autowired
@Qualifier("handlerExceptionResolver")
private HandlerExceptionResolver resolver;
if( true) {
resolver.resolveException(httpServletRequest, httpServletResponse,
null,new BadRequestException(ResultEnum.TOKEN_EXPIRED));
return;//捕获异常后就直接退出了
}
方法二:把异常交给Controller处理
既然Filter中的异常,不能经过我们定义的异常处理类,那我们就把此异常交给controller,让controller经过异常处理类,帮我们处理。
步骤
- 定义过滤器,将异常交给controller处理
- 调整该过滤器的位置,将这个过滤器的位置要放在存在异常处理器的前面(原因看后面图解)
- 定义处理异常的controller
异常过滤器
public class ExceptionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (Exception e) {
request.setAttribute("exception", e);
request.getRequestDispatcher("/error").forward(request, response);
}
}
调整过滤器位置
@Bean
public FilterRegistrationBean<ExceptionFilter> exceptionFilterRegistration() {
FilterRegistrationBean<ExceptionFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new ExceptionFilter());
registration.setName("exceptionFilter");
/* 这个序号要很小,保证 exceptionFilter 是所有过滤器链的入口 */
registration.setOrder(Integer.MIN_VALUE);
return registration;
}
抛出异常的controller
@RestController
public class MyErrorContorller {
@PostMapping("/error")
public Result throwException(HttpServletRequest request) throws Exception {
throw (Exception) request.getAttribute("exception");
}
}
Result 是我自己定义的结果处理类,你们用自己的即可
测试
结果
过滤器位置调整原因
方法三:ErrorController
没有看懂,后续看懂了文章补充
参考文章
参考博客1:Spring 使用 ControllerAdvice 处理 Filter 抛出的异常
参考博客2:Spring中Controller层、Filter层、Interceptor层全局统一异常处理
说明
写这篇文章时,我正处于一个基本的学习阶段,好多知识的原理并不是很清晰,部分解释都是根据自己的想法,如果有错误的地方,欢迎大家批评指正,也欢迎大家在评论区交流。