Spring——Spring开发实战经验(4)
- 创业
- 2025-09-07 03:57:02

摘要
本文深入探讨了 Spring 应用中 Interceptor(拦截器)、Filter(过滤器)和 Aspect(切面)的执行顺序、职责及典型使用场景。Filter 是 Servlet 级别的机制,主要用于日志记录、权限验证等,它在请求到达 Spring MVC 的 DispatcherServlet 前执行,响应返回时按配置顺序反向执行。Interceptor 是 Spring 提供的机制,用于拦截 Spring MVC 请求,它在请求进入 Spring MVC 处理之前、Controller 方法执行之前和之后执行。Aspect(AOP)则用于处理横切关注点,如事务管理、日志记录等,它通过代理机制在目标方法执行前后插入额外逻辑。文中还提供了 WebMvcConfig 配置示例、拦截器与其他组件的对比以及拦截器与 AOP 的区别和联系等内容,帮助读者更好地理解和使用这些机制。
1. Interceptor/Filter/Aspect 的执行顺序在 Spring 应用中,Interceptor、Filter 和 Aspect 都是用来处理请求的不同机制。它们各自有不同的职责和执行顺序。理解它们的执行顺序对于调试和优化应用非常重要。
1.1. Filter(过滤器)职责:Filter是一种 Servlet 级别的机制,主要用于请求和响应的预处理和后处理。它通常用于日志记录、权限验证、请求修改等操作。
执行顺序:Filter 在 Servlet 容器中非常早地被调用,并且它在请求到达 Spring MVC 的处理器之前执行。
执行顺序:
请求到达:Filter 在请求到达 Spring MVC 的 DispatcherServlet 前执行。Filter 执行:所有配置的 Filter 按照配置顺序依次执行。请求交给 DispatcherServlet:Filter 在请求到达 DispatcherServlet 时,会允许请求继续向下传递。响应返回:响应从 DispatcherServlet 返回时,Filter 会按配置顺序反向执行(从最后一个 Filter 到第一个 Filter)。典型使用场景:
日志记录权限校验请求数据修改响应数据修改 1.2. Interceptor(拦截器) 职责:Interceptor 是 Spring 提供的机制,它用于拦截 Spring MVC 请求。与 Filter 不同的是,Interceptor 是基于 Spring 的控制器和 HandlerMapping 的,并且它只与 Spring MVC 控制器交互。执行顺序:Interceptor 在请求进入 Spring MVC 处理之前、Controller 方法执行之前和之后执行。执行顺序:
请求到达 DispatcherServlet:当请求到达 DispatcherServlet 时,Interceptor 会按配置顺序依次执行。执行 Controller 方法:Interceptor 执行完成后,DispatcherServlet 会调用 Controller 层的处理方法。响应返回:当 Controller 方法返回结果后,Interceptor 会按配置顺序反向执行,直到最后一个 Interceptor。典型使用场景:
权限验证请求计时处理请求日志 3. Aspect (AOP)(切面) 职责:Aspect 是基于切面编程(AOP)机制的,用于在方法执行前后增加额外的行为(如日志记录、事务处理等)。它是通过 @Aspect 注解和切点(@Before、@After、@Around 等)来定义的。执行顺序:Aspect 是 Spring AOP 的一部分,AOP 执行顺序通常是基于方法执行的前后,而不是请求/响应的生命周期。它通常是在 Controller 方法执行前后,或者 Service/DAO 层方法执行前后 进行拦截。执行顺序:
请求到达 DispatcherServlet:在这个阶段,Interceptor 和 Filter 会先执行。Controller 方法执行:Aspect 会在方法执行前后执行,具体的顺序取决于通知的类型(例如 @Before、@After、@Around 等)。 @Before:在目标方法执行前执行。@After:在目标方法执行后执行。@Around:可以在方法执行前后都执行。 响应返回:响应返回时,Aspect 会根据 @After 或 @AfterReturning 等通知继续执行。典型使用场景:
日志记录事务管理安全校验 执行顺序总结:阶段
Filter
Interceptor
Aspect
请求到达 DispatcherServlet
首先执行(Filter Chain)
最后执行(Spring 容器配置的顺序)
不影响请求进入 DispatcherServlet
Controller 方法执行前
不参与
执行前通知 (preHandle
)
执行前通知 (@Before
或 @Around
)
Controller 方法执行后
不参与
执行后通知 (postHandle
)
执行后通知 (@After
或 @Around
)
响应返回
反向执行(Filter Chain)
反向执行(Spring 容器配置的顺序)
执行后通知 (@AfterReturning
或 @After
)
执行顺序图解: Filter → Interceptor → Controller 方法 → Interceptor → Filter (请求方向)Filter ← Interceptor ← Controller 方法 ← Interceptor ← Filter (响应方向) 实用场景示例:假设有如下情形:
你需要在每个请求的最前面进行身份验证,可以使用 Filter 来实现。你需要在控制器方法执行之前和之后记录日志或进行权限校验,可以使用 Interceptor 来实现。你需要在特定方法执行前后做日志记录、事务管理等操作,可以使用 Aspect 来实现。 补充说明: Filter 是 Java EE 标准的机制,直接作用于 Servlet 容器,独立于 Spring。Interceptor 是 Spring 特有的功能,作用于 Spring MVC 处理的请求。Aspect 是 Spring AOP 提供的功能,可以用来处理横切关注点,适用于方法级别的增强。通过合理的使用 Filter、Interceptor 和 Aspect,你可以实现非常灵活的请求处理、日志记录、安全校验等功能。
2. WebMvcConfig配置示例 @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Resource private PermissionInterceptor permissionInterceptor; @Resource private CookieInterceptor cookieInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(permissionInterceptor).addPathPatterns("/**"); registry.addInterceptor(cookieInterceptor).addPathPatterns("/**"); } }这是一个 Spring MVC 的配置类,WebMvcConfig 实现了 WebMvcConfigurer 接口,主要用于配置和定制 Spring MVC 的行为。以下是代码中的关键点:
@Configuration:标注该类为一个配置类,Spring 容器会将其识别为 Bean 定义的来源。WebMvcConfigurer:这是一个 Spring 提供的接口,允许我们通过实现其方法来自定义 Spring MVC 的配置。@Resource:用于注入 Spring 容器中的 Bean。这里注入了两个拦截器:permissionInterceptor:权限拦截器,用于处理与用户权限相关的逻辑。cookieInterceptor:Cookie 拦截器,用于处理与 Cookie 验证或操作相关的逻辑。addInterceptors 方法:这个的是实现WebMvcConfigurer的方法。用来向 Spring MVC 的拦截器链中添加拦截器。InterceptorRegistry:拦截器注册器,用于配置拦截器及其作用路径。addInterceptor(permissionInterceptor).addPathPatterns("/**"):将 permissionInterceptor 注册到拦截器链。addPathPatterns("/**") 表示拦截所有请求路径。addInterceptor(cookieInterceptor).addPathPatterns("/**"):同样注册 cookieInterceptor 拦截所有请求路径。拦截器执行顺序:拦截器会按照注册顺序依次执行(即先执行 permissionInterceptor,再执行 cookieInterceptor)。
package org.springframework.web.servlet.config.annotation; import java.util.List; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.lang.Nullable; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.HandlerExceptionResolver; public interface WebMvcConfigurer { default void configurePathMatch(PathMatchConfigurer configurer) { } default void configureContentNegotiation(ContentNegotiationConfigurer configurer) { } default void configureAsyncSupport(AsyncSupportConfigurer configurer) { } default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { } default void addFormatters(FormatterRegistry registry) { } default void addInterceptors(InterceptorRegistry registry) { } default void addResourceHandlers(ResourceHandlerRegistry registry) { } default void addCorsMappings(CorsRegistry registry) { } default void addViewControllers(ViewControllerRegistry registry) { } default void configureViewResolvers(ViewResolverRegistry registry) { } default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { } default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) { } default void configureMessageConverters(List<HttpMessageConverter<?>> converters) { } default void extendMessageConverters(List<HttpMessageConverter<?>> converters) { } default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { } default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { } @Nullable default Validator getValidator() { return null; } @Nullable default MessageCodesResolver getMessageCodesResolver() { return null; } }这段代码定义了 WebMvcConfigurer 接口,它是 Spring MVC 配置的核心接口之一。通过实现这个接口,开发者可以自定义 Spring MVC 的各种行为,包括路径匹配、内容协商、异步支持、默认 Servlet 处理、格式化器、拦截器、资源处理器、跨域映射、视图控制器、视图解析器、参数解析器、返回值处理器、消息转换器、异常处理器以及验证器和消息代码解析器。
3. Spring 中拦截器Spring MVC的拦截器 (HandlerInterceptor) 是一种 AOP(面向切面编程) 的实现机制,允许在请求处理的不同阶段拦截 HTTP 请求并执行特定逻辑。以下是拦截器的主要作用:
3.1. 拦截器工作流程 触发时机: 拦截器在请求到达控制器(@Controller 或 @RestController)之前执行。响应生成后,在发送给客户端之前再次执行。 主要方法: preHandle(HttpServletRequest request, HttpServletResponse response, Object handler): 在请求到达控制器之前执行。返回 true 表示继续处理请求;返回 false 表示中止请求。 postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView): 在控制器处理完请求后,但尚未生成响应之前执行。 afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex): 在视图渲染完成后执行,用于资源清理或记录日志。 3.2. 拦截器常见应用场景 权限校验(如 PermissionInterceptor): 判断用户是否有权限访问某些接口。如果没有权限,直接返回错误响应(如 403 Forbidden)。 认证与登录验证: 验证用户是否已登录,检查 Session 或 Token。如果未登录,跳转到登录页面或返回 401 Unauthorized。 请求日志记录: 记录请求的参数、响应结果、执行时间等信息,用于监控和分析。 参数校验与数据预处理: 检查请求中的参数是否合法。为请求添加必要的上下文数据(如用户信息、请求头补充)。 跨站请求伪造(CSRF)防护: 检查请求头中的 CSRF Token 是否有效。 请求追踪与调试: 生成唯一的请求 ID,用于追踪请求链路。 3.3. 拦截器与其他组件的对比特性
拦截器 (Interceptor)
过滤器 (Filter)
切面 (AOP Aspect)
触发阶段
Spring MVC 的处理流程内
Servlet 请求的早期阶段
方法级别(如 @Controller
方法调用)
关注点
与请求处理相关(权限、认证等)
全局请求过滤(编码、跨域等)
与业务逻辑相关(如日志、事务管理)
实现接口
HandlerInterceptor
javax.servlet.Filter
@Aspect
(基于 Spring AOP)
应用场景
请求认证、权限校验、日志记录等
请求过滤、跨域、编码设置等
日志、事务处理、通用逻辑
4. 拦截器与AOP区别拦截器(Interceptor)虽然与 AOP(面向切面编程) 有相似之处,但严格来说,拦截器并不是 AOP 的直接实现,而是一个独立的机制。二者有不同的设计目的和实现方式,但在某些场景下确实可以通过拦截器实现类似于 AOP 的功能。下面详细分析它们的区别和联系。
4.1. 拦截器与 AOP 的区别 4.1.1. 核心概念不同 AOP(Aspect-Oriented Programming): 是一种面向切面编程的设计思想,用于在不改变核心业务逻辑的情况下,动态地为方法添加额外行为。通过 切面(Aspect) 和 切入点(Pointcut) 的定义,精准定位到某些方法调用,并在方法执行的 前后或异常时 添加逻辑。主要基于 Spring AOP(代理模式) 或 AspectJ(字节码增强)。 拦截器(Interceptor): 是 Spring MVC 或其他框架提供的一种机制,用于对 HTTP 请求和响应 进行拦截和处理。通常应用在 Web 请求的处理链路 中,比如在请求到达控制器之前,或响应生成之后添加逻辑。 4.1.2. 工作范围不同 AOP: 应用于方法级别,主要是对业务方法(如 @Service、@Controller)进行增强。可以在任何类的方法上进行增强,甚至独立于 Spring MVC。 拦截器: 专注于处理 HTTP 请求和响应,属于 Spring MVC 流程 的一部分。作用范围是 Controller(控制器)方法之前和之后。 4.1.3. 触发机制不同 AOP: 基于代理模式(JDK 动态代理或 CGLIB 动态代理)或字节码操作(如 AspectJ)。使用切面定义,依赖切入点表达式(如 execution())。仅对特定的方法调用生效,与 HTTP 请求无关。 拦截器: 工作在 Spring MVC 的处理链中,由 DispatcherServlet 调度执行。对 HTTP 请求进行预处理(如认证、日志、跨域检查等)。 4.2. 拦截器是否可以实现 AOP 的功能?在某些场景下,拦截器确实可以实现类似 AOP 的功能,例如:
记录日志: 在拦截器的 preHandle 方法中记录请求的参数。权限校验: 在拦截器中判断是否有访问权限,阻止不合法请求。但拦截器的能力有限:
它只能拦截基于 HTTP 的请求,无法对方法调用(非 HTTP 场景)进行增强。它无法精准到某个类或方法,而是基于请求路径。AOP 更灵活和强大,适合以下场景:
精准增强特定方法(通过切入点)。跨服务的通用逻辑(如事务管理、性能监控)。 4.3. 拦截器与 AOP 的联系 二者的功能在某些场景下重叠。例如,拦截器可以在请求进入 Controller 前后,记录日志或进行校验,这与 AOP 的切面功能相似。在 Spring 应用中,AOP 和拦截器经常配合使用: 拦截器处理全局的 HTTP 请求级别逻辑。AOP 处理业务方法级别的切面逻辑。 4.4. 拦截器和 AOP 的对比表特性
AOP
拦截器(Interceptor)
作用范围
方法级别(类、方法的调用)
请求级别(HTTP 请求前后)
依赖机制
动态代理(JDK Proxy 或 CGLIB)
Spring MVC 的 HandlerInterceptor
主要应用场景
日志、事务管理、性能监控、方法增强等
请求认证、权限校验、跨域、统一日志等
触发点
方法调用(如 @Service
方法)
HTTP 请求的处理过程
实现方式
@Aspect
(Spring AOP 或 AspectJ)
实现 HandlerInterceptor
接口
局限性
无法直接作用于 HTTP 请求
无法精确到特定方法,强依赖 Spring MVC
4.5. 示例对比 4.5.1. AOP 切面示例 @Aspect @Component public class LoggingAspect { @Pointcut("execution(* com.example.service.*.*(..))") public void serviceMethods() {} @Before("serviceMethods()") public void logBefore(JoinPoint joinPoint) { System.out.println("Before method: " + joinPoint.getSignature().getName()); } } 作用: 在 com.example.service 包中的所有方法执行之前记录日志。 4.5.2. 拦截器示例 public class LoggingInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { System.out.println("Before handling request: " + request.getRequestURI()); return true; } } 作用: 在每次 HTTP 请求到达 Controller 之前记录请求路径。 4.6. 总结 拦截器不是 AOP 的实现,但它们的功能在某些场景下有重叠。拦截器 更偏向于 HTTP 请求级别的拦截,而 AOP 更灵活,适合方法级增强。在复杂项目中,拦截器和 AOP 通常配合使用,实现从请求级别到方法级别的逻辑分离。 博文参考Spring——Spring开发实战经验(4)由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Spring——Spring开发实战经验(4)”