filter、servlet、interceptor的执行顺序

本文详细解析了Servlet Filter的基本概念及其在Struts2框架中的执行顺序。阐述了Filter如何作为请求处理链的一部分,在用户请求到达Servlet之前对其进行预处理,并在Servlet生成响应后进行后处理。此外,还介绍了如何通过配置决定多个Filter的执行顺序。

1. Filter可认为是Servlet的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。它与Servlet的区别在于:它不能直接向用户生成响应。完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

struts2

 

通过上图可以看到,顺序应该是我们配的filter在前,之后是struts2的FilterDispatcher,然后是各个拦截器,最后原路返回。

 

2. Servlet  Filter  Struts2的DispatcherFilter的执行顺序。

在Servlet JSR中说明了Servlet和Filter执行的顺序:

如果一个请求匹配了一个Serlvet,并且该Servlet配置了一个或者多个Filter,毫无疑问,先执行Filter,再执行Servlet。

对与多个匹配的Filter,哪个先执行呢?

JSR中说明的是,按照多个匹配的Filter,是按照其在web.xml中配置的顺序来执行的。

所以这也就是,把自己的Filter或者其他的Filter(比如UrlRewrite的Filter)放在Struts的DispatcherFilter的前面的原因。因为,它们需要在请求被Struts2框架处理之前,做一些前置的工作。

当Filter被调用,并且进入了Struts2的DispatcherFilter中后,Struts2会按照在Action中配置的Interceptor Stack中的Interceptor的顺序,来调用Interceptor。

 

 

 

参考文章:http://www.iteye.com/problems/41978 

 

 

<think> 首先,用户的问题是:“我想了解Spring Boot拦截器Interceptor执行顺序 请问Spring Boot拦截器Interceptor执行顺序” 参考了几个引用: - 引用[1]:提到拦截器在请求处理前后执行逻辑,如日志、权限校验等。 - 引用[2]:解释了拦截器的执行流程,过滤器和拦截器的区别,包括拦截范围不同。 - 引用[3]:提到拦截器用于AOP,执行如日志、权限检查等任务。 用户明确询问拦截器的执行顺序。我需要基于这些引用和我的知识来回答。 回想拦截器在Spring Boot中的执行顺序: - 拦截器实现`HandlerInterceptor`接口。 - 接口有三个关键方法: 1. `preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)`:在控制器方法执行前调用。返回true继续执行后续拦截器和控制器,返回false则中断。 2. `postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)`:在控制器方法执行后、视图渲染前调用。 3. `afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)`:在请求完成后调用,无论是否有异常。 执行顺序: 1. 所有拦截器的`preHandle`方法按注册顺序执行。 2. 如果所有`preHandle`返回true,控制器方法执行。 3. 控制器方法执行后,所有拦截器的`postHandle`方法按注册顺序的逆序执行。 4. 最后,所有拦截器的`afterCompletion`方法按注册顺序的逆序执行。 注册顺序:在配置类中通过`addInterceptor()`添加拦截器时的顺序决定了它们的执行顺序。 从引用中提取有用信息: - 引用[2]提到:“拦截器的执行流程”,但没有详细说明顺序。它说:“通过执行流程分析,大家应该已经清楚了过滤器和拦截器之间的区别”,但焦点在区别上。 - 我需要补充知识,确保回答真实可靠。 回答结构: 1. 解释拦截器的作用,基于引用。 2. 详细描述执行顺序。 3. 给出示例或伪代码。 4. 根据系统指令: - 使用中文回答。 - 行内数学表达式用$...$,但这里可能没有数学表达式。 - 独立公式用$$...$$,但同样可能不适用。 - 生成相关问题。 - 引用的段落末尾添加引用标识,如[^1]。 引用标识:我需要标明引用来源。用户提供了引用[1]、[2]、[3],所以我应该引用它们。 例如,在描述时,可以说:“根据引用[1],拦截器用于在请求处理前后执行特定逻辑如日志记录[^1]。” 回答结构清晰: - 先介绍拦截器。 - 然后解释执行顺序。 - 最后生成相关问题。 生成相关问题:在最后添加“§§相关问题§§”部分,列出3-5个相关问题。 完整回答大纲: 1. 介绍拦截器:简述是什么和用途。 2. 执行顺序详细说明:分步解释preHandle, postHandle, afterCompletion的顺序。 3. 注册顺序的影响:如何控制顺序。 4. 示例:简单代码或伪代码展示。 5. 相关问题。 确保语言自然,使用中文。 最终回答格式: - 内容分段。 - 必要时添加代码块。 - 结尾添加相关问题。 </think> ### Spring Boot拦截器Interceptor执行顺序 在Spring Boot中,拦截器(Interceptor)是实现`HandlerInterceptor`接口的组件,用于在Web请求处理的不同阶段插入自定义逻辑,如日志记录、权限验证或性能监控[^1][^3]。拦截器的执行顺序由其在配置类中的注册顺序决定,主要包括三个阶段:`preHandle`、`postHandle`和`afterCompletion`。以下是详细的执行流程说明,基于核心概念和实际实现原理。 #### 拦截器的执行顺序详解 拦截器的执行顺序分为以下步骤,每个步骤对应`HandlerInterceptor`接口的方法: 1. **`preHandle`方法(在控制器方法执行前调用)**: - 所有拦截器的`preHandle`方法按照注册顺序依次执行。 - 每个拦截器的`preHandle`方法返回一个布尔值:如果返回`true`,则继续执行后续拦截器或控制器;如果返回`false`,则中断整个请求处理链。 - 例如,如果有两个拦截器`InterceptorA`和`InterceptorB`注册在顺序中(先A后B),执行顺序为:`InterceptorA.preHandle()` → `InterceptorB.preHandle()`。 2. **控制器方法执行**: - 如果所有`preHandle`方法都返回`true`,Spring Boot会调用目标控制器(Controller)的请求处理方法。 - 这一阶段不涉及拦截器逻辑,但属于整体请求处理流程的一部分。 3. **`postHandle`方法(在控制器方法执行后、视图渲染前调用)**: - 控制器方法执行完成后,所有拦截器的`postHandle`方法按照注册顺序的**逆序**执行。 - 例如,对于注册顺序为`InterceptorA` → `InterceptorB`,执行顺序为:`InterceptorB.postHandle()` → `InterceptorA.postHandle()`。 - 此方法常用于处理模型数据或添加额外日志[^1][^3]。 4. **`afterCompletion`方法(在请求完成后调用,无论是否有异常)**: - 在请求处理结束(包括视图渲染完成或发生异常)后,所有拦截器的`afterCompletion`方法按照注册顺序的**逆序**执行。 - 同样,以`InterceptorA`和`InterceptorB`为例,执行顺序为:`InterceptorB.afterCompletion()` → `InterceptorA.afterCompletion()`。 - 此阶段适合执行资源清理或最终日志记录[^1][^2]。 #### 注册顺序如何影响执行 在Spring Boot配置类中,你需要通过`WebMvcConfigurer`的`addInterceptor()`方法注册拦截器。拦截器的注册顺序直接决定了`preHandle`的顺序和`postHandle`/`afterCompletion`的逆序。以下是一个简单的代码示例: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 注册拦截器,顺序决定了执行优先级 registry.addInterceptor(new LoggingInterceptor()).order(1); // 先注册,preHandle先执行 registry.addInterceptor(new AuthInterceptor()).order(2); // 后注册,preHandle后执行 } } // 自定义拦截器示例 public class LoggingInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { System.out.println("LoggingInterceptor: preHandle"); return true; // 继续执行 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { System.out.println("LoggingInterceptor: postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("LoggingInterceptor: afterCompletion"); } } // 另一个拦截器 public class AuthInterceptor implements HandlerInterceptor { // 类似实现... } ``` 执行输出示例: - `preHandle`顺序:LoggingInterceptor → AuthInterceptor - `postHandle`和`afterCompletion`逆序:AuthInterceptor → LoggingInterceptor #### 关键区别与注意事项 - **与过滤器的区别**:拦截器只拦截Spring环境中的资源(如Controller请求),而过滤器(Filter)会拦截所有Servlet请求,包括静态资源[^2]。拦截器的执行顺序更精细,更适合Spring Boot的上下文管理。 - **中断逻辑**:如果某拦截器的`preHandle`返回`false`,后续拦截器和控制器不会执行,但已执行的拦截器的`afterCompletion`方法仍会调用以清理资源[^1]。 - **性能影响**:多个拦截器可能增加请求延迟,建议逻辑简单以避免瓶颈[^3]。 通过合理配置注册顺序,你可以灵活控制拦截器链,实现如先验证权限后记录日志的流水线处理[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值