原文链接:过滤器和拦截器的区别 – 编程屋
目录
可能有些小伙伴们在接手公司的项目时,经常看到公司的项目中既有过滤器又有拦截器,那么它们既然都拦截的作用,那么各自扮演着什么样的角色呢?要想搞懂它们所扮演的角色,就需要搞懂它们各自有什么作用了。
1. 拦截器是基于java的反射机制,而过滤器是基于函数回调的。
2. 拦截器只能对action请求请作用,而过滤器对所有的请求都起作用
3. 拦截器可以访问action的上下文,而过滤器不能
4 在action的生命周期中,拦截器可以多次被调用,而过滤器只能调用一次
以下附有拦截器和过滤器的详细介绍:
java过滤器(Filter)_IT盛夏的果实的博客-CSDN博客
一篇搞懂拦截器(HandlerInterceptor)的用法_IT盛夏的果实的博客-CSDN博客

可见Filter过滤器是javax.servlet包下的,是在Servlet规范中定义的,也就是说过滤器Filter的使用依赖于Tomcat等容器,导致它只能在web程序中使用。

拦截器是一个Sping组件,由Spring管理,不依赖于Tomcat容器,是可以单独使用的。也可以应用于Application、Swing容器中。
在有的项目中,既有过滤器又有拦截器,那么它们两者之间的执行顺序是谁先谁后呢?先过滤器->再拦截器

在上面说过,Filter是依赖于Tomcat容器的,所以请求是在进入Tomcat之后、进入Servet之前对请求进行一个预处理,然后进入Servlet,再经过拦截器进行处理、最后进入我们的Controller。
为了证实上述所说:我们可以在一个项目中同时配置过滤器和拦截器(其余配置不在展示,可以参考上述两篇文章),
过滤器:
- @WebFilter("/*")
- public class MyFilterOne implements Filter {
-
- /**
- * web应用启动时,web服务器将创建Filter的实例对象,并调用init方法,读取web.xml的配置,完成对象的初始化功能,
- * 从而为后续的用户请求做好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次,开发人员通过init的参数,
- * 可或得代表当前filter配置信息的FilterConfig对象)
- * @param filterConfig
- * @throws ServletException
- */
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
- }
-
- /**
- * 这个方法完成实际的过滤操作,当客户请求访问与过滤器相关联的URL的时候,Servlet过滤器将先执行doFilter方法,FilterChain参数用于访问后续过滤器
- * @param servletRequest
- * @param servletResponse
- * @param filterChain
- * @throws IOException
- * @throws ServletException
- */
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- System.out.println("我是过滤器,我进来了");
- filterChain.doFilter(servletRequest, servletResponse);
- }
-
- /**
- * filter创建后会保存在内存中,当web应用移除或者服务器停止时才销毁,该方法在Filter的生命周期中仅执行一次,在这个方法中,可以释放过滤器使用的资源
- */
- @Override
- public void destroy() {
-
- }
- }
拦截器:
-
- @Component
- public class HeaderInterceptor implements HandlerInterceptor {
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("进入拦截器=======执行前========");
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("进入拦截器=======执行中========");
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("进入拦截器=======执行后========");
- }
- }
Controller层:
- @RestController
- public class LoginController {
-
-
- @GetMapping("/test/filterAndInterceptor")
- public String testFilter(){
- System.out.println("我是controller");
- return "请看控制台谁先输出";
- }
- }
访问:

控制台输出:

可见:上述结论是正确的,请求先经过过滤器再经过拦截器。
在有的业务场景中,会在过滤器或者拦器引入sevice,看看情况分别是怎么样
- @GetMapping("/test/filterAndInterceptor")
- public String testFilter(){
- System.out.println("我是controller");
- return "请看控制台谁先输出";
- }
- @Service
- public class LoginServiceImpl implements LoginService{
- @Override
- public void login() {
- System.out.println("我是service中登录方法");
- }
- }
在过滤器中引入service:
- package com.liubujun.springbootinterceptor.filter;
-
-
-
-
- import com.liubujun.springbootinterceptor.service.LoginService;
-
- import javax.annotation.Resource;
- import javax.servlet.*;
- import javax.servlet.annotation.WebFilter;
- import java.io.IOException;
-
- /**
- * @Author: liubujun
- * @Date: 2022/10/16 19:26
- */
-
- @WebFilter("/*")
- public class MyFilterOne implements Filter {
-
- @Resource
- private LoginService loginService;
-
- /**
- * web应用启动时,web服务器将创建Filter的实例对象,并调用init方法,读取web.xml的配置,完成对象的初始化功能,
- * 从而为后续的用户请求做好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次,开发人员通过init的参数,
- * 可或得代表当前filter配置信息的FilterConfig对象)
- * @param filterConfig
- * @throws ServletException
- */
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
- }
-
- /**
- * 这个方法完成实际的过滤操作,当客户请求访问与过滤器相关联的URL的时候,Servlet过滤器将先执行doFilter方法,FilterChain参数用于访问后续过滤器
- * @param servletRequest
- * @param servletResponse
- * @param filterChain
- * @throws IOException
- * @throws ServletException
- */
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- System.out.println("我是过滤器,我进来了");
- loginService.login();
- filterChain.doFilter(servletRequest, servletResponse);
- }
-
- /**
- * filter创建后会保存在内存中,当web应用移除或者服务器停止时才销毁,该方法在Filter的生命周期中仅执行一次,在这个方法中,可以释放过滤器使用的资源
- */
- @Override
- public void destroy() {
-
- }
- }
访问之后控制台输出:一切正常

在拦截器中引入service :
- @Component
- public class HeaderInterceptor implements HandlerInterceptor {
-
- @Resource
- private LoginService loginService;
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("进入拦截器=======执行前========");
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- loginService.login();
- System.out.println("进入拦截器=======执行中========");
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("进入拦截器=======执行后========");
- }
- }
以上只是部分内容,为了维护方便,本文已迁移到新地址:过滤器和拦截器的区别 – 编程屋