过滤器和拦截器有什么区别

134 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

过滤器(Filter)和拦截器(Interceptor)都是基于 AOP(Aspect Oriented Programming,面向切面编程)思想实现。

过滤器

过滤器使用 Servlet 3.0 提供的 @WebFilter 注解,配置过滤的 URL 规则,然后再实现 Filter 接口,重写接口中的 doFilter 方法,具体实现代码

@Component
public class TestInterceptor implements HandlerInterceptor {
    /**
     * @Author: Take-off
     * @Description: //TODO 在请求方法 执行前 被调用,比如验证登录信息
     * @Date: 4:52 PM 2022/10/18
     **/
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器:执行 preHandle 方法。");
        return true;
    }
    /**
     * @Author: Take-off
     * @Description: //TODO 在请求方法之后执行,但会在 DispatcherServlet 进行渲染视图之前被执行
     * @Date: 4:53 PM 2022/10/18
     **/
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器:执行 postHandle 方法。");
    }
    /**
     * @Author: Take-off
     * @Description: //TODO 会在整个请求结束之后再执行
     * @Date: 5:00 PM 2022/10/18
     **/
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器:执行 afterCompletion 方法。");
    }
}

void init(FilterConfig filterConfig):容器启动(初始化 Filter)时会被调用,整个程序运行期只会被调用一次。用于实现 Filter 对象的初始化。

void doFilter(ServletRequest request, ServletResponse response,FilterChain chain):具体的过滤功能实现代码,通过此方法对请求进行过滤处理,其中 FilterChain 参数是用来调用下一个过滤器或执行下一个流程

void destroy():用于 Filter 销毁前完成相关资源的回收工作。

拦截器

1.创建一个普通的拦截器,实现 HandlerInterceptor 接口,并重写接口方法

@Component
public class TestInterceptor implements HandlerInterceptor {
    /**
     * @Author: Take-off
     * @Description: //TODO 在请求方法 执行前 被调用,比如验证登录信息
     * @Date: 4:52 PM 2022/10/18
     **/
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器:执行 preHandle 方法。");
        return true;
    }
    /**
     * @Author: Take-off
     * @Description: //TODO 在请求方法之后执行,但会在 DispatcherServlet 进行渲染视图之前被执行
     * @Date: 4:53 PM 2022/10/18
     **/
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器:执行 postHandle 方法。");
    }
    /**
     * @Author: Take-off
     * @Description: //TODO 会在整个请求结束之后再执行
     * @Date: 5:00 PM 2022/10/18
     **/
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器:执行 afterCompletion 方法。");
    }
}

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle):

在请求方法执行前被调用,也就是调用目标方法之前被调用。比如我们在操作数据之前先要验证用户的登录信息,就可以在此方法中实现,如果验证成功则返回 true,继续执行数据操作业务;否则就返回 false,后续操作数据的业务就不会被执行了。

void postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView):

调用请求方法之后执行,但它会在 DispatcherServlet 进行渲染视图之前被执行。

void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex):

会在整个请求结束之后再执行,也就是在 DispatcherServlet 渲染了对应的视图之后再执行。

2,将上一步创建的拦截器加入到 Spring Boot 的配置文件中

@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Autowired
    private TestInterceptor testInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(testInterceptor)
                .addPathPatterns("/*");
    }
}

两者区别

1.出身不同

过滤器来自于Servlet,而拦截器来自于 Spring 框架。

2.触发时机不同

请求的执行顺序是:请求进入容器 > 进入过滤器 > 进入 Servlet > 进入拦截器 > 执行控制器

3.实现不同

过滤器是基于方法回调实现的。当我们要执行下一个过滤器或下一个流程时,需要调用 FilterChain 对象的 doFilter 方法进行回调执行

拦截器是基于动态代理(底层是反射)实现的。

4.支持的项目类型不同

过滤器是 Servlet 规范中定义的,所以过滤器要依赖 Servlet 容器,它只能用在 Web 项目中;而拦截器是 Spring 中的一个组件,因此拦截器既可以用在 Web 项目中,同时还可以用在 Application 或 Swing 程序中

5.使用的场景不同

因为拦截器更接近业务系统,所以拦截器主要用来实现项目中的业务判断,比如:登陆判断、权限判断、日志记录等业务。而过滤器通常是用来实现通用功能过滤的,比如:敏感词过滤、字符集编码设置。