SpringBoot过滤器中异常处理无效解决方案

问题

过滤器中抛出异常,未经过全局异常处理器,前端未接收到异常信息。

问题分析

过滤器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经过异常处理类,帮我们处理。

步骤

  1. 定义过滤器,将异常交给controller处理
  2. 调整该过滤器的位置,将这个过滤器的位置要放在存在异常处理器的前面(原因看后面图解)
  3. 定义处理异常的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:

参考博客2:

说明

经验分享 程序员 微信小程序 职场和发展