当前位置: 首页 > news >正文

SpringBoot 拦截器和过滤器的区别

SpringBoot 拦截器和过滤器的区别

SpringBoot 中的拦截器(Interceptor)和过滤器(Filter)都是用于请求处理的增强机制,但它们存在以下核心区别:

对比维度过滤器(Filter)拦截器(Interceptor)
所属规范Servlet 规范( javax.servlet 包)Spring 框架( org.springframework 包)
应用范围所有进入容器的请求(包括静态资源)仅针对 Spring MVC 控制器的请求
触发时机在 Servlet 容器处理请求前/后在 Spring MVC 处理器执行前/后/完成时
实现方式实现 javax.servlet.Filter 接口实现 org.springframework.web.servlet.HandlerInterceptor 接口
依赖注入不支持(Filter 由 Servlet 容器管理)支持(Interceptor 由 Spring 容器管理)
访问上下文仅能访问 ServletRequest 和 ServletResponse可访问 Handler、ModelAndView 等 Spring 组件
执行顺序基于 FilterRegistrationBean 配置的顺序基于 InterceptorRegistry 注册的顺序

设计模式分析

过滤器(Filter)采用的设计模式
  1. 责任链模式(Chain of Responsibility)

    • 多个 Filter 形成链式调用,每个 Filter 可以决定是否继续传递请求到下一个环节
    • 示例代码体现:
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 前置处理chain.doFilter(request, response); // 传递到下一个过滤器或Servlet// 后置处理
      }
      
  2. 装饰器模式(Decorator)

    • 通过 Filter 包装原始请求/响应对象,增强其功能(如字符编码处理)
    • 示例:CharacterEncodingFilter 装饰请求对象以设置字符编码
拦截器(Interceptor)采用的设计模式
  1. AOP(面向切面编程)

    • 拦截器本质是 Spring AOP 的一种实现,通过对 Handler 方法的环绕通知实现增强
    • 示例:
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 前置处理,返回true继续执行后续拦截器和Handlerreturn true;
      }
      
  2. 观察者模式(Observer)

    • 拦截器的 postHandleafterCompletion 方法类似于事件监听机制
    • 当请求处理完成或发生异常时,触发相应的回调方法

典型应用场景对比

场景过滤器(Filter)拦截器(Interceptor)
请求编码处理CharacterEncodingFilter-
跨域请求处理CorsFilter-
权限校验基于 Servlet API 的简单权限检查基于 Spring Security 的复杂权限控制
请求日志记录记录原始请求信息记录完整的处理时间和结果
事务管理-基于 @Transactional 注解的事务拦截
性能监控统计请求总耗时统计 Controller 方法执行耗时

选择建议

  • 使用过滤器:需要对所有请求进行统一处理(如编码、安全头设置)
  • 使用拦截器:需要访问 Spring 容器中的 Bean 或处理 MVC 相关对象(如 ModelAndView)
  • 组合使用:复杂场景下,可结合过滤器和拦截器实现多层级处理(如:过滤器处理基础安全,拦截器处理业务权限)

下面将详细介绍Spring Boot中过滤器(Filter)和拦截器(Interceptor)的使用方法,并提供示例代码:

一、过滤器(Filter)的使用步骤

1. 创建Filter类并实现Filter接口
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;@WebFilter(urlPatterns = "/*", filterName = "requestLogFilter")
public class RequestLogFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;// 前置处理:记录请求信息System.out.println("Filter: 请求URL - " + httpRequest.getRequestURI());// 传递请求到下一个过滤器或Servletchain.doFilter(request, response);// 后置处理:记录响应信息System.out.println("Filter: 请求处理完成");}
}
2. 启用Servlet组件扫描(如果未使用@ServletComponentScan)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication
@ServletComponentScan  // 启用Servlet组件扫描
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
3. 或通过Java配置注册Filter(推荐方式)
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<RequestLogFilter> loggingFilter() {FilterRegistrationBean<RequestLogFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new RequestLogFilter());registrationBean.addUrlPatterns("/*");  // 拦截所有请求registrationBean.setOrder(1);  // 设置过滤器执行顺序return registrationBean;}
}

二、拦截器(Interceptor)的使用步骤

1. 创建Interceptor类并实现HandlerInterceptor接口
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class RequestTimeInterceptor implements HandlerInterceptor {private ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 前置处理:记录请求开始时间long startTime = System.currentTimeMillis();startTimeThreadLocal.set(startTime);System.out.println("Interceptor: 请求开始 - " + request.getRequestURI());return true;  // 返回true继续执行后续拦截器和Handler}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) {// 后置处理:Controller方法执行完成后,但视图渲染前System.out.println("Interceptor: 请求处理中 - " + request.getRequestURI());}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception ex) {// 完成处理:视图渲染完成后,可用于资源清理long startTime = startTimeThreadLocal.get();long endTime = System.currentTimeMillis();System.out.println("Interceptor: 请求完成 - " + request.getRequestURI() + " 耗时: " + (endTime - startTime) + "ms");startTimeThreadLocal.remove();  // 防止内存泄漏}
}
2. 注册拦截器到Spring MVC
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 {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new RequestTimeInterceptor()).addPathPatterns("/**")  // 拦截所有请求.excludePathPatterns("/static/**", "/error");  // 排除静态资源和错误页面}
}

三、过滤器 vs 拦截器执行顺序示例

执行顺序配置
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册第一个拦截器(order=1)registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/**").order(1);// 注册第二个拦截器(order=2)registry.addInterceptor(new SecondInterceptor()).addPathPatterns("/**").order(2);}
}@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<FirstFilter> firstFilter() {FilterRegistrationBean<FirstFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new FirstFilter());registration.addUrlPatterns("/*");registration.setOrder(1);  // 过滤器顺序1return registration;}@Beanpublic FilterRegistrationBean<SecondFilter> secondFilter() {FilterRegistrationBean<SecondFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new SecondFilter());registration.addUrlPatterns("/*");registration.setOrder(2);  // 过滤器顺序2return registration;}
}
执行顺序结果

对于一个HTTP请求,执行顺序为:

FirstFilter.pre -> SecondFilter.pre -> 
FirstInterceptor.pre -> SecondInterceptor.pre -> 
Controller处理请求 -> 
SecondInterceptor.post -> FirstInterceptor.post -> 
视图渲染 -> 
SecondInterceptor.after -> FirstInterceptor.after -> 
SecondFilter.post -> FirstFilter.post

四、常见应用场景代码示例

1. 权限校验拦截器
public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {String token = request.getHeader("Authorization");if (token == null || !validateToken(token)) {response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "未授权");return false;}// 将用户信息存入Request,供后续使用request.setAttribute("user", parseUserFromToken(token));return true;}private boolean validateToken(String token) {// 验证Token逻辑return token.startsWith("Bearer ");}private User parseUserFromToken(String token) {// 解析用户信息return new User("testUser");}
}
2. 字符编码过滤器
@WebFilter(urlPatterns = "/*", filterName = "encodingFilter")
public class EncodingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");chain.doFilter(request, response);}
}

五、关键配置说明

配置项过滤器(Filter)拦截器(Interceptor)
拦截路径配置@WebFilter(urlPatterns = "/*")registry.addPathPatterns("/**")
排除路径配置不直接支持,需在doFilter中手动判断registry.excludePathPatterns("/static/**")
执行顺序控制通过 FilterRegistrationBean.setOrder()通过 addInterceptor().order() 或注册顺序
依赖注入不支持(非Spring管理)支持(可注入Service等Bean)
获取Spring上下文需手动获取ApplicationContext可直接注入所需组件

六、注意事项

  1. 过滤器注意点

    • Filter由Servlet容器管理,生命周期独立于Spring
    • 无法直接注入Spring Bean,需通过ApplicationContext获取
    • 对所有请求生效,包括静态资源和错误请求
  2. 拦截器注意点

    • Interceptor由Spring管理,可使用依赖注入
    • 仅拦截Spring MVC处理的请求,对静态资源无效
    • 可访问HandlerMethod、ModelAndView等Spring MVC特有对象
  3. 性能考虑

    • 过滤器执行更早,性能开销更小
    • 拦截器功能更强大,但依赖Spring MVC上下文

根据实际需求合理选择过滤器或拦截器,复杂场景可组合使用两者。

http://www.dtcms.com/a/273843.html

相关文章:

  • 如何高效验证代理IP的可用性与稳定性
  • 瀚高数据库提交数据后,是否需要COMMIT(APP)
  • oracle
  • 从代码学习深度学习 - 针对序列级和词元级应用微调BERT PyTorch版
  • 线程池拒绝策略执行之后的补偿案例
  • Express + @vladmandic/face-api + mySql 实现人脸识别
  • Oracle 数据库 Dblink
  • 【项目经理】实施项目技术问题
  • 5G标准学习笔记14 - CSI--RS概述
  • Telnet远程连接实验(Cisco)
  • 包稳定的Docker 安装方式(CentOS)
  • 前端实现 MD5 加密
  • 【Linux应用】Ubuntu20.04 aarch64开发板一键安装ROS2(清华源)
  • 登录超时问题的排查方法与预防经验分享
  • 【机器学习】机器学习基础
  • 设计模式笔记_结构型_代理模式
  • GPT3/chatGPT/T5/PaLM/LLaMA/GLM主流大语言模型的原理和差异
  • 触觉反馈手套技术是迈向远程机器人系统灵巧操作的关键一步
  • 【Linux】系统引导修复
  • 【八股消消乐】浅尝Kafka性能优化
  • 服务器机柜与网络机柜各自的优势
  • 微信小程序111~120
  • 十二、k8s工程化管理Helm
  • Docker部署私有仓库
  • Linux_3:进程间通信
  • 全面掌控 Claude Code:命令 + 参数 + 快捷键一文全整理(建议收藏)
  • DVWA靶场通关笔记-反射型XSS(Reflected Medium级别)
  • react打包发到线上报错Minified React error #130
  • 在HP小机上跑了1432天的Oracle RAC,能不能重启?
  • 【ECharts】多个ECharts版本共存解决方案