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

Spring Boot 中 Filter、Interceptor 和 AOP 的全面对比与应用场景

Spring Boot 中 Filter、Interceptor 和 AOP 的全面对比与应用场景

Spring Boot 中Filter(过滤器)、Interceptor(拦截器)、AOP的区别、执行顺序、适用场景。


1. 三者一句话定位

  • Filter(过滤器)

Servlet 规范,在 Tomcat 容器层工作,最早执行,能拦截所有请求(静态资源、Servlet、Controller)。

  • HandlerInterceptor(拦截器)

Spring MVC 组件,在 Spring 容器内工作,只拦截进入 Controller 的请求

  • AOP(面向切面)

Spring 核心功能,不局限于 Web,可拦截任意方法(Service、Dao、Controller 等)。


2. 执行顺序(最重要)

请求进来时顺序:

  1. Filter → 2. Interceptor → 3. AOP → Controller

返回时顺序:

Controller → AOP → Interceptor → Filter

简单记:Filter 最外,AOP 最里


3. 详细对比表

对比项Filter(过滤器)Interceptor(拦截器)AOP
所属规范Servlet 规范Spring MVCSpring 核心
作用范围所有 Web 请求只拦截 Controller 请求任意 Spring Bean 方法
能否获取 Bean不能直接注入 Spring Bean可以可以
能否获取请求可以(request/response)可以不能直接获取,需依赖 RequestContextHolder
能否获取方法不能可以(HandlerMethod)可以(切点、方法签名)
适用场景编码、跨域、限流、请求头过滤登录校验、日志、权限日志、事务、缓存、通用增强
触发时机最早中间最晚(靠近方法)

4. 各自核心用法(极简)

① Filter(过滤器)

实现javax.servlet.Filter

@Component public class MyFilter implements Filter { @Override public void doFilter(...) { // 请求前 chain.doFilter(request, response); // 响应后 } }

② Interceptor(拦截器)

实现HandlerInterceptor

@Component public class MyInterceptor implements HandlerInterceptor { // 进入Controller前 @Override public boolean preHandle(...) throws Exception { return true; } // Controller执行后 @Override public void postHandle(...) {} // 视图渲染后 @Override public void afterCompletion(...) {} }

③ AOP

使用@Aspect+ 切点表达式

@Aspect @Component public class MyAop { @Before("execution(* com.xxx.controller.*.*(..))") public void before() { // 方法执行前 } }

5. 怎么选择?(最实用)

  • 过滤所有请求(静态资源、跨域、编码)→Filter

  • 拦截Controller、做登录/权限Interceptor

  • 通用方法增强(日志、事务、缓存)→AOP


6. 一句话总结

  • Filter:容器层守门员,拦所有请求

  • Interceptor:MVC守门员,拦Controller

  • AOP:方法级增强,拦任意方法


以下是可直接运行的 Spring Boot 完整示例代码,涵盖 Filter、Interceptor、AOP 三种组件的完整实现、配置及测试场景:

7. 完整可运行示例代码

7.1 项目依赖(pom.xml)

核心依赖为 Spring Boot Web,无需额外引入其他依赖(AOP 已包含在 Spring 核心依赖中):

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.15</version><!-- 稳定版本,可根据需求调整 --><relativePath/></parent><dependencies><!-- Spring Boot Web 核心依赖(包含 Servlet、Spring MVC) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

7.2 核心组件实现

7.2.1 Filter 实现与配置

功能:记录请求进入时间,拦截所有 Web 请求(包括静态资源)

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Date; // 注解方式配置:拦截所有路径(/*),过滤器名称为 MyFilter @WebFilter(urlPatterns = "/*", filterName = "MyFilter") public class MyFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(MyFilter.class); // 过滤器初始化(项目启动时执行) @Override public void init(FilterConfig filterConfig) throws ServletException { logger.info("MyFilter 初始化"); } // 核心过滤逻辑(每次请求都会执行) @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 1. 请求前处理 HttpServletRequest request = (HttpServletRequest) servletRequest; String requestUrl = request.getRequestURL().toString(); long startTime = new Date().getTime(); logger.info("MyFilter 拦截请求:{},进入时间:{}", requestUrl, startTime); // 2. 放行请求(继续向下执行,进入 Interceptor) filterChain.doFilter(servletRequest, servletResponse); // 3. 响应后处理 long endTime = new Date().getTime(); logger.info("MyFilter 完成响应:{},耗时:{}ms", requestUrl, (endTime - startTime)); } // 过滤器销毁(项目停止时执行) @Override public void destroy() { logger.info("MyFilter 销毁"); } }

Filter 启用配置(主启动类添加注解):

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; // 扫描 Servlet 组件(@WebFilter、@WebServlet 等) @ServletComponentScan @SpringBootApplication public class FilterInterceptorAopApplication { public static void main(String[] args) { SpringApplication.run(FilterInterceptorAopApplication.class, args); } }

7.2.2 Interceptor 实现与配置

功能:登录校验(模拟),只拦截 Controller 请求

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class MyInterceptor implements HandlerInterceptor { private static final Logger logger = LoggerFactory.getLogger(MyInterceptor.class); // 1. 进入 Controller 前执行(核心校验逻辑) @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { logger.info("MyInterceptor preHandle:进入 Controller 前校验"); // 模拟登录校验:从 Session 中获取用户信息,无则拦截 HttpSession session = request.getSession(); Object user = session.getAttribute("loginUser"); if (user == null) { logger.warn("用户未登录,拦截请求:{}", request.getRequestURL()); // 未登录则重定向到登录页(或返回 401) response.sendRedirect("/login"); return false; // 拦截请求,不进入 Controller } return true; // 放行请求,进入 Controller } // 2. Controller 执行后、视图渲染前执行 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { logger.info("MyInterceptor postHandle:Controller 执行完成,准备渲染视图"); } // 3. 视图渲染后执行(整个请求完成) @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { logger.info("MyInterceptor afterCompletion:请求完全完成"); } }

Interceptor 注册配置(需手动注册到 Spring 容器):

import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; // 配置类:注册 Interceptor @Configuration public class WebMvcConfig implements WebMvcConfigurer { // 注册自定义拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()) .addPathPatterns("/api/**") // 拦截 /api 下所有请求(只拦截 Controller 相关请求) .excludePathPatterns("/login"); // 排除登录接口,不拦截 } }

7.2.3 AOP 实现

功能:记录 Service 层方法执行日志(通用方法增强)

import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.aspectj.lang.annotation.Aspect; import java.lang.reflect.Method; // 标识为切面类 @Aspect // 交给 Spring 管理 @Component public class MyAop { private static final Logger logger = LoggerFactory.getLogger(MyAop.class); private long startTime; // 切入点:拦截 com.example.service 包下所有类的所有方法 @Pointcut("execution(* com.example.service.*.*(..))") public void servicePointCut() {} // 方法执行前增强 @Before("servicePointCut()") public void beforeMethod(JoinPoint joinPoint) { startTime = System.currentTimeMillis(); // 获取方法信息 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); String className = joinPoint.getTarget().getClass().getName(); logger.info("MyAop 方法执行前:类名={},方法名={}", className, method.getName()); } // 方法执行后增强 @After("servicePointCut()") public void afterMethod(JoinPoint joinPoint) { long endTime = System.currentTimeMillis(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); logger.info("MyAop 方法执行后:方法名={},耗时={}ms", method.getName(), (endTime - startTime)); } }

7.3 测试场景(Controller + Service)

7.3.1 测试 Service

import org.springframework.stereotype.Service; @Service public class TestService { // 测试方法,会被 AOP 拦截 public String testMethod(String param) { return "Service 处理完成,参数:" + param; } }

7.3.2 测试 Controller

import com.example.service.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @RestController public class TestController { @Autowired private TestService testService; // 登录接口(不被 Interceptor 拦截) @GetMapping("/login") public String login(HttpSession session) { // 模拟登录:向 Session 存入用户信息 session.setAttribute("loginUser", "testUser"); return "登录成功"; } // 测试接口(被 Interceptor 拦截,调用 Service 被 AOP 拦截) @GetMapping("/api/test") public String test(@RequestParam String param) { return testService.testMethod(param); } }

7.4 运行测试与预期结果

7.4.1 测试步骤

  1. 启动 Spring Boot 项目,观察日志:MyFilter 初始化

  2. 访问登录接口:http://localhost:8080/login,返回「登录成功」

  3. 访问测试接口:http://localhost:8080/api/test?param=hello,观察日志输出顺序

7.4.2 预期日志顺序(对应执行顺序)

// 1. Filter 拦截请求 MyFilter 拦截请求:http://localhost:8080/api/test,进入时间:xxx // 2. Interceptor 进入 Controller 前校验 MyInterceptor preHandle:进入 Controller 前校验 // 3. AOP 拦截 Service 方法执行前 MyAop 方法执行前:类名=com.example.service.TestService,方法名=testMethod // 4. Service 方法执行(业务逻辑) // 5. AOP 拦截 Service 方法执行后 MyAop 方法执行后:方法名=testMethod,耗时=xxms // 6. Interceptor Controller 执行完成 MyInterceptor postHandle:Controller 执行完成,准备渲染视图 // 7. Interceptor 请求完全完成 MyInterceptor afterCompletion:请求完全完成 // 8. Filter 响应完成 MyFilter 完成响应:http://localhost:8080/api/test,耗时=xxms

7.5 关键说明

  • 包路径说明:示例中包路径为com.example,实际开发中需替换为自己的项目包路径

  • 依赖版本:示例使用 Spring Boot 2.7.15(稳定版),若使用 3.x 版本,需注意 Servlet API 从 javax 迁移为 jakarta,代码需对应调整(如javax.servlet.Filterjakarta.servlet.Filter

  • 扩展场景:可根据需求修改 Filter 拦截路径、Interceptor 校验逻辑、AOP 切入点(如拦截 Controller 或 Dao 层方法)

http://www.jsqmd.com/news/457172/

相关文章:

  • 微动开关采购避坑指南:2026年厂家选择建议,大电流微动开关/微动开关/新能源微动开关,微动开关供应厂家排名 - 品牌推荐师
  • 基于Spring Boot的汽车租赁系统的设计与实现(源码+文档)
  • 德国新帕泰克:粒度分析仪领域的实力标杆企业 - 品牌推荐大师1
  • CVE-2025-14898漏洞复现
  • OpenClaw 与微信(企业微信)集成完整步骤
  • 技术日报|openclaw单日暴增9164星总量破28.9万,agency-agents代理体系强势登榜第二
  • 为什么 123.toString() 不会报错?揭秘 JavaScript Number 的隐藏魔法
  • QModMaster:工业级ModBus通信的开源解决方案
  • 计算机毕业设计java基于vue的健身房信息管理系统基于SpringBoot+Vue的健身房智慧运营综合管理平台设计健身俱乐部会员课程与场地预约一体化管理系统的研发
  • linux 服务器支持的 TCP 连接数上限及配置优化
  • 零门槛打造全场景智能助手:QQBot个性化自动化实践指南
  • 突破音乐枷锁:qmcdump让QQ音乐加密文件重获自由
  • 有没有适合初学者使用的低代码/无代码Agent开发工具?新手入门全指南
  • 一文说清:AI认证一级 vs 二级,难度、侧重点、适用人群全对比
  • 2026上海宠物皮肤科医院怎么挑?看这篇指南就够了,异宠医院/母猫绝育/狗狗绝育/母狗绝育,宠物皮肤科医生找哪家 - 品牌推荐师
  • QMC音频解密工具:3步解锁加密音乐文件
  • 全面解析:面向职场效率提升的AI等级认证,考试题型与考查重点揭秘
  • 2026安防防护门优质厂家推荐指南:后方洞库大门、复合式枪弹库门、室内现金岛、室外现金岛、文物库房金库门选择指南 - 优质品牌商家
  • 【优化求解】基于扰动调制光感实现智能光分配的占位分布估算Matlab代码
  • EdgeRemover:系统化清除Windows Edge浏览器的安全解决方案
  • 2026年如家礼品卡回收价格深度解析:你的闲置酒店卡还值多少钱? - 京回收小程序
  • 低温粉碎机怎么选?三大国产实力制造商深度测评 - 品牌推荐大师
  • 选购DIY挂饰卡圈书圈,哪个厂家口碑好 - 工业品牌热点
  • 【图像加密】基于混沌和秩交织的有效图像加密算法 质数因子 + 时间种子 + 异或运算附matlab代码
  • 【实时Linux工业PLC解决方案系列】第二十五篇 - 实时Linux PLC电源管理优化
  • “箭头函数的设计初衷是简化回调、绑定词法 this”的补充说明
  • 捷运达加拿大清关行专业不,在浙江口碑好不好 - myqiye
  • geekez指纹生成脚本
  • 5大核心功能节省80%重复操作:BetterGI智能辅助工具全解析
  • 2026年高薪赛道盘点:这10类岗位年薪百万起步,小白程序员如何精准收藏抢占先机?