过滤器和拦截器的区别详解
创作时间:
作者:
@小白创作中心
过滤器和拦截器的区别详解
引用
CSDN
1.
https://m.blog.csdn.net/m0_70871140/article/details/144638166
过滤器(Filter)和拦截器(Interceptor)是 Web 开发中常用的工具,它们可以在请求处理流程中拦截请求或响应,用于完成某些通用功能或业务逻辑控制。尽管它们有很多相似之处,但本质上是两个完全不同的概念。以下是两者的详细区别及使用场景。
一、基本概念
1. 过滤器(Filter)
- 定义:过滤器是基于 Servlet 规范的,运行在 Servlet 容器中,作用于请求和响应的整个生命周期。
- 实现:实现 Java EE 的
javax.servlet.Filter接口,必须在 Web 应用的部署描述文件(如web.xml)中配置,或者通过注解配置。 - 功能:
- 请求预处理(例如请求参数校验、敏感词过滤)。
- 响应后处理(例如统一格式化响应数据、压缩响应内容)。
- 主要用于处理通用的、横切的功能。
2. 拦截器(Interceptor)
- 定义:拦截器是基于框架(如 Spring)的组件,运行在应用层,作用于业务方法的调用前后。
- 实现:实现
HandlerInterceptor接口,并在 Spring 配置中声明。 - 功能:
- 拦截业务层方法调用(如权限校验、日志记录)。
- 更接近业务逻辑,可以操作 Spring 上下文中的 Bean 和其他资源。
二、核心区别
特性 | 过滤器(Filter) | 拦截器(Interceptor) |
|---|---|---|
来源 | 属于 Java EE Servlet 规范的一部分。 | 属于 Spring 框架的一部分。 |
触发时机 | 在请求进入 Servlet 之前和响应离开 Servlet 之后执行。 | 在控制器(Controller)方法调用的前后执行。 |
作用范围 | 针对所有资源(静态资源、动态资源),甚至包括 JSP 和 HTML。 | 仅针对 Spring MVC 的控制器方法(如 @RequestMapping)。 |
实现方式 | 实现 javax.servlet.Filter 接口。 | 实现 HandlerInterceptor 接口。 |
依赖容器 | 依赖于 Servlet 容器(如 Tomcat)。 | 依赖于 Spring 框架。 |
执行顺序 | 比拦截器先执行(更靠近底层)。 | 比过滤器后执行(更靠近业务逻辑)。 |
配置方式 | 配置在 web.xml 文件中或使用 @WebFilter 注解。 | 配置在 Spring 的配置类中,或使用 @Component 和 WebMvcConfigurer。 |
应用场景 | 通用功能(如跨域、编码设置、数据压缩等)。 | 业务逻辑相关(如权限验证、登录校验、日志记录等)。 |
三、执行流程对比
请求从客户端到服务器的执行顺序为:
- 过滤器(Filter):处理所有请求。
- Servlet:核心业务逻辑处理。
- 拦截器(Interceptor):控制器方法调用前后拦截请求。
请求的处理流程通常为:
客户端请求 → 容器 → 过滤器 → Servlet → 拦截器 → 控制器(Controller)方法 → 响应
这种触发顺序使得过滤器更适合处理底层的通用逻辑,而拦截器更贴近业务逻辑。
四、具体实现
1. 过滤器的实现
基于函数回调机制,通过调用 FilterChain.doFilter() 来控制请求的继续执行。
使用 javax.servlet.Filter 接口开发过滤器,需要实现以下三个方法:
示例代码如下:
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class TestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
// 这里可以初始化一些还没被加载的配置等
System.out.println("过滤器初始化:init() 方法执行。");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("过滤器执行前逻辑:请求处理开始。");
chain.doFilter(request, response); // 放行请求,交给下一个过滤器或 Servlet。
System.out.println("过滤器执行后逻辑:响应处理结束。");
}
@Override
public void destroy() {
System.out.println("过滤器销毁:destroy() 方法执行。");
}
}
常用场景:
- 日志记录:记录每个请求的 IP、URL 等信息。
- 安全过滤:屏蔽不合法的请求。
- 设置编码:统一请求和响应的字符集编码。
- 数据压缩:对返回的数据进行 gzip 压缩。
2. 拦截器的实现
基于动态代理实现,通过 HandlerInterceptor 接口定义拦截逻辑。拦截器通常需要注册到 Spring 配置中,执行流程包括:
2.1. preHandle 方法
- 作用:请求方法执行前调用,用于处理请求前的逻辑。通常用于权限验证、日志记录、输入验证等。
- 返回值:必须返回
true或false,true表示请求继续往下处理(进入下一个拦截器或目标方法),false表示请求被拦截,后续的拦截器和目标方法不会被执行。
常见场景:
- 权限检查:检查用户是否已登录、是否有权限访问某个资源。
- 日志记录:记录请求的详细信息,比如请求参数、请求时间等。
2.2. postHandle 方法
- 作用:请求处理后、视图渲染前调用。通常用于对目标方法返回的模型数据进行修改或增强,或者记录请求处理的时间等。
- 返回值:没有返回值,
ModelAndView对象可以在该方法中被修改。
常见场景:
- 在响应返回之前,对视图数据进行修改。例如,向模型中添加额外的属性。
- 记录请求处理的时间,做一些后续的处理,日志记录等。
2.3. afterCompletion 方法
- 作用:请求处理完成后、视图渲染之后调用。通常用于资源的清理工作,比如释放数据库连接、记录请求处理的完成时间等。
- 返回值:没有返回值,可以用来处理异常的情况或做一些日志记录工作。
常见场景:
- 资源清理:例如关闭数据库连接、文件流等。
- 异常处理:可以用于记录异常信息或发送异常报告。
- 性能监控:记录请求的总处理时间,进行性能分析。
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("拦截器 preHandle:请求处理前执行。");
// 检查用户是否已登录
if (request.getSession().getAttribute("user") == null) {
response.sendRedirect("/login"); // 如果未登录,重定向到登录页面
return false; // 拦截请求,不继续执行
}
return true; // 请求继续处理
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
System.out.println("拦截器 postHandle:请求处理后,但未渲染视图时执行。");
// 可以修改 ModelAndView,比如添加公共的属性到模型
if (modelAndView != null) {
modelAndView.addObject("footer", "Footer content");
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("afterCompletion:请求完全处理后,视图渲染后");
// 记录请求处理的时间
long startTime = (long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
System.out.println("请求处理时间:" + (endTime - startTime) + "ms");
// 如果有异常,可以记录或做进一步处理
if (ex != null) {
System.out.println("发生了异常:" + ex.getMessage());
}
}
}
配置拦截器:
将拦截器加入到 Spring 配置中:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor())
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/login", "/static/**"); // 排除特定路径
}
}
五、应用场景总结
过滤器适合场景
- 跨域处理(CORS)。
- URL 访问限制。
- 字符集设置。
- 日志记录。
- 数据压缩。
拦截器适合场景
- 用户身份验证。
- 权限控制。
- 请求统计。
- 业务逻辑预处理或后置操作。
- 系统日志记录(业务级别)。
六、总结
- 过滤器面向底层,关注请求和响应的整体生命周期,适合处理通用功能。
- 拦截器面向业务层,关注控制器方法的调用,适合处理业务逻辑相关功能。
- 两者各有侧重点,开发时需根据具体需求选择合适的工具来实现功能。
热门推荐
夏日必备:黄瓜&菠菜凉拌菜大揭秘!
NBA地震级交易:东契奇与戴维斯互换东家
NBA惊天交易:东契奇戴维斯互换,湖人独行侠爵士三方大交易震撼联盟
塞尔蒂克大手笔引援,新赛季能否夺冠?
老年人如何保护牙齿健康?这些口腔健康知识一定要看!
健康养生:食物中的重金属污染与健康风险!
基于生物传感器的土壤重金属检测系列新方法介绍
小岛阳菜:从偶像到坚韧女性的心路历程
涡轮增压技术详解:原理、类型及应用
都说汽车功率大提速快,为何 2.5 自吸比 2.0T 功率高,提速却更慢?
如何在日常生活中绽放欢喜心
数字时代,中老年人的生活新方式
双十一社交购物大揭秘:Instagram vs 小红书
赓续世博精神 世博滨江打造可持续低碳城区发展典范
涩谷 10 个必去景点
除湿机湿度多少度合适?除湿机最佳湿度设置及使用技巧
新加坡文化遗产节即将开启!探索地标建筑鲜为人知的秘密
日本动漫巡礼:7个必去的日漫打卡地
新加坡:乌节路节日亮灯仪式拉开序幕
三伏天养生:生姜、羊肉和绿豆,三种食物助你补阳养胃
每日中药本草:砂仁,调理脾胃必备:砂仁的健脾开胃功效与食疗方
车厘子这样洗才安全!
车厘子清洗大揭秘:小苏打+盐+白醋,农药虫卵全跑光!
汉堡包是垃圾食品?营养师教你这样吃更健康!
汉堡真的会伤害你的心脏吗?
厨房里食物垃圾的创意再利用方法
盐酸洛贝林注射液:急救必备神器?
打造理想家居:2025年家居色彩设计指南
纪念馆设计的历史背景与未来展望
9.20全国爱牙日|如何从小养成正确刷牙习惯?华西口腔专家来支招