过滤器和拦截器的区别
创始人
2024-03-30 21:27:17
0

目录

1 前言

2 区别

2.1  实现原理不同

2.2 使用范围不同

2.3 执行顺序不同

4 注入Bean的情况不同

1 前言

        可能有些小伙伴们在接手公司的项目时,经常看到公司的项目中既有过滤器又有拦截器,那么它们既然都拦截的作用,那么各自扮演着什么样的角色呢?要想搞懂它们所扮演的角色,就需要搞懂它们各自有什么作用了。

2 区别

2.1  实现原理不同

1. 拦截器是基于java的反射机制,而过滤器是基于函数回调的。

2. 拦截器只能对action请求请作用,而过滤器对所有的请求都起作用

3. 拦截器可以访问action的上下文,而过滤器不能

4 在action的生命周期中,拦截器可以多次被调用,而过滤器只能调用一次

以下附有拦截器和过滤器的详细介绍:

java过滤器(Filter)_IT盛夏的果实的博客-CSDN博客

一篇搞懂拦截器(HandlerInterceptor)的用法_IT盛夏的果实的博客-CSDN博客

2.2 使用范围不同

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

 拦截器是一个Sping组件,由Spring管理,不依赖于Tomcat容器,是可以单独使用的。也可以应用于Application、Swing容器中。

2.3 执行顺序不同

在有的项目中,既有过滤器又有拦截器,那么它们两者之间的执行顺序是谁先谁后呢?先过滤器->再拦截器

 在上面说过,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*/@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}/*** 这个方法完成实际的过滤操作,当客户请求访问与过滤器相关联的URL的时候,Servlet过滤器将先执行doFilter方法,FilterChain参数用于访问后续过滤器* @param servletRequest* @param servletResponse* @param filterChain* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("我是过滤器,我进来了");filterChain.doFilter(servletRequest, servletResponse);}/*** filter创建后会保存在内存中,当web应用移除或者服务器停止时才销毁,该方法在Filter的生命周期中仅执行一次,在这个方法中,可以释放过滤器使用的资源*/@Overridepublic void destroy() {}
}

拦截器:


@Component
public class HeaderInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("进入拦截器=======执行前========");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("进入拦截器=======执行中========");}@Overridepublic 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 "请看控制台谁先输出";}
}

访问: 

控制台输出:

 可见:上述结论是正确的,请求先经过过滤器再经过拦截器。

4 注入Bean的情况不同

在有的业务场景中,会在过滤器或者拦器引入sevice,看看情况分别是怎么样

    @GetMapping("/test/filterAndInterceptor")public String testFilter(){System.out.println("我是controller");return "请看控制台谁先输出";}
@Service
public class LoginServiceImpl implements LoginService{@Overridepublic 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 {@Resourceprivate LoginService loginService;/*** web应用启动时,web服务器将创建Filter的实例对象,并调用init方法,读取web.xml的配置,完成对象的初始化功能,* 从而为后续的用户请求做好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次,开发人员通过init的参数,* 可或得代表当前filter配置信息的FilterConfig对象)* @param filterConfig* @throws ServletException*/@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}/*** 这个方法完成实际的过滤操作,当客户请求访问与过滤器相关联的URL的时候,Servlet过滤器将先执行doFilter方法,FilterChain参数用于访问后续过滤器* @param servletRequest* @param servletResponse* @param filterChain* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("我是过滤器,我进来了");loginService.login();filterChain.doFilter(servletRequest, servletResponse);}/*** filter创建后会保存在内存中,当web应用移除或者服务器停止时才销毁,该方法在Filter的生命周期中仅执行一次,在这个方法中,可以释放过滤器使用的资源*/@Overridepublic void destroy() {}
}

访问之后控制台输出:一切正常

 在拦截器中引入service :

@Component
public class HeaderInterceptor implements HandlerInterceptor {@Resourceprivate LoginService loginService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("进入拦截器=======执行前========");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {loginService.login();System.out.println("进入拦截器=======执行中========");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("进入拦截器=======执行后========");}
}

发起请求:发现竟然报错了。

打断点之后发现:拦截器中注入的service为null。

 那么为什么会出现这种情况呢?这是因为加载顺序导致的问题,拦截器的加载时间点在springcontext之前,而bean是由Spring管理。所以为null。

那么如何修改呢?

@Configuration
public class WebAppConfig implements WebMvcConfigurer {@Resourceprivate HeaderInterceptor headerInterceptor;/*** 添加拦截规则* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {List patterns = new ArrayList<>();patterns.add("/login/login");registry.addInterceptor(headerInterceptor).addPathPatterns("/**") //所有的请求都要拦截。.excludePathPatterns(patterns); //将不需要拦截的接口请求排除在外}
}

之前是这样的: 

@Configuration
public class WebAppConfig implements WebMvcConfigurer {/*** 添加拦截规则* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new HeaderInterceptor());}
}

再次测试发现就不会报错了。

参考文章:拦截器(Interceptor)和过滤器(Filter)的执行顺序和区别_熊與猫v的博客-CSDN博客_filter和interceptor执行顺序

相关内容

热门资讯

货币政策工具加力支持 □ 本报记者 詹 超 【场景】 昆山开发区,苏州清陶动力科技有限公司车间的固态电池生产线嗡嗡作响,金...
我国继续实施更加积极的财政政策 经济日报北京12月28日讯(记者曾金华)记者从全国财政工作会议获悉,今年财政工作取得新成效,为推动完...
吴中区“三强化”促进法律服务业... 苏州市吴中区锚定“升级服务产业、优化营商环境、赋能高质量发展”核心目标,以政策为引领、平台为支撑、人...
央行:稳妥有序完善房地产信贷基... |2025年12月29日 星期一| NO.1 央行:稳妥有序完善房地产信贷基础性制度 12月26日,...
大金重工[002487]关于诉... 本版导读 2025-12-29 2025-12-29 2025-12-29 2025...
国务院国资委:完善国有资产管理... 国务院国资委党委书记、主任张玉卓在学习时报刊发文章《坚定不移做强做优做大国有企业和国有资本》。其中提...
“惠民政策落不到村”,紧抓!(... 本报记者 郑洋洋 “重点研究周武村党组织软弱涣散的问题,大家直奔主题,谈谈看法。”山西长治市潞城区店...
财政政策如何继续“更加积极” 记者从27日至28日举行的全国财政工作会议获悉:2026年要继续实施更加积极的财政政策,扩大财政支出...
落户政策居然考虑放开! 怎么,我能落户北京了? 大家好,我是孙少睡,这是我的第467篇楼市评论。 很多人的第一反应肯定是有没...
股市必读:ST泉为股东因涉嫌违... 截至2025年12月26日收盘,ST泉为(300716)报收于9.96元,下跌0.8%,换手率0.9...