过滤器和拦截器的区别详解
创作时间:
作者:
@小白创作中心
过滤器和拦截器的区别详解
引用
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 访问限制。
- 字符集设置。
- 日志记录。
- 数据压缩。
拦截器适合场景
- 用户身份验证。
- 权限控制。
- 请求统计。
- 业务逻辑预处理或后置操作。
- 系统日志记录(业务级别)。
六、总结
- 过滤器面向底层,关注请求和响应的整体生命周期,适合处理通用功能。
- 拦截器面向业务层,关注控制器方法的调用,适合处理业务逻辑相关功能。
- 两者各有侧重点,开发时需根据具体需求选择合适的工具来实现功能。
热门推荐
五个随时随地都能修行的方法,收藏!
PersonalLLM——探索LLM是否能根据五大人格特质重新塑造一个新的角色?
高考真题怎么获取?
如何判断猪是否被寄生虫感染?猪如何驱虫?
沈阳十大名吃:从马烧麦到西塔大冷面,地道东北风味等你来尝
来东北就是要吃呀!盘点沈阳必打卡美食清单,这些老店不容错过!
跑步机好还是动感单车好:选择哪个更适合你的减肥计划
这间只收1元钱的“抗癌厨房”,何以坚持22年不打烊
高原弥散制氧机使用注意事项
你不知道的冷知识——陕西篇
栀子花的花语与象征(探索栀子花的15种寓意)
AR和VR游戏发展的必然趋势
第一次参加无领导小组面试,怎样快速融入
一个孩子顺利度过甲流的7天,家长都做对了什么?
脸谱绘出黑神话 古老非遗潮起来
AI+电力:未来十年的黄金赛道
DeepSeek推荐:5天玩转沈阳,从景点到美食全攻略
海角社区的互动方式探讨:促进交流与合作的新策略
华为笔记本电脑清洁方法是什么?
高校学术不端行为频频曝光,背后存在哪些问题?
事关5家上市公司!“C类”卫生巾被疑不卫生 产品检验报告道出实情
打消伤疤比较好的方法是什么
电脑录音设备管理软件推荐:从入门到专业
家庭教育不等于压力教育:如何让孩子快乐学习
如何办理私企人员退休手续?这类手续的办理要求有哪些?
4060显卡属于什么档次的显卡 4060显卡参数配置介绍
《不能承受的生命之轻》:真正的成熟是实现这三种内在和解
安全礼仪红绿灯
朱元璋出生地之争:“明光说”把史学之争引向歧途
雍正杀年羹尧的原因探析