过滤器和拦截器的执行顺序

<think>好的,我需要解释Java中过滤器拦截器执行时机。首先,我需要回顾一下它们的基本概念,然后比较它们在请求处理流程中的不同阶段。 用户可能已经了解过滤器拦截器的基本区别,但需要更详细的时间顺序说明。我应该先明确它们在整个请求处理中的位置,比如在Servlet容器Spring MVC中的位置。 过滤器是Servlet规范的一部分,作用于更底层,拦截所有进入容器的请求。而拦截器是Spring MVC的组件,作用于DispatcherServlet之后,处理控制器级别的请求。所以它们的执行时机肯定不同。 接下来,我应该详细描述一个HTTP请求从客户端到服务器的处理流程,指出过滤器拦截器分别在哪个步骤执行。例如,请求先经过过滤器链,然后到达DispatcherServlet,之后才由拦截器处理。 同时,需要注意多个过滤器拦截器执行顺序,比如过滤器顺序由web.xml中的配置顺序决定,而拦截器顺序由Spring配置中的添加顺序决定。在响应阶段,它们的执行顺序相反,类似于栈的结构。 还要提到一些特定的方法,比如过滤器的doFilter(),拦截器的preHandle()、postHandle()afterCompletion(),以及它们分别在处理流程的哪个阶段被调用。 可能用户会混淆它们的执行顺序,所以需要用清晰的步骤或流程图来说明。例如,请求先经过所有过滤器的doFilter(),然后进入DispatcherServlet,接着是拦截器的preHandle(),控制器方法处理,拦截器的postHandle(),视图渲染,最后是拦截器的afterCompletion(),响应再经过过滤器的逆序处理。 需要确保内容准确,避免错误。比如,过滤器执行在Spring上下文之外,而拦截器在Spring MVC的上下文中,所以拦截器可以访问Spring的bean,而过滤器默认不能,除非使用特殊的配置如DelegatingFilterProxy。 最后,总结它们的执行时机差异,强调过滤器更早介入,拦截器在Spring MVC处理阶段介入,帮助用户形成清晰的时序图。</think>--- ### **执行时机全景图** 想象一次网购流程: `浏览器 → 快递分拣中心(过滤器) → 本地配送站(拦截器) → 你家` --- ### **详细执行流程** 1. **请求进入服务器** - 💼 **过滤器先工作**(所有请求必须经过) ```java // 过滤器执行顺序Filter1 → Filter2 → Filter3 public void doFilter(request, response, chain) { System.out.println("进入过滤器"); // 处理请求前 chain.doFilter(request, response); // 放行 System.out.println("离开过滤器"); // 处理响应后 } ``` 2. **到达Spring大门** - 🚪 请求进入`DispatcherServlet`(Spring MVC入口) 3. **拦截器层层把关** ```java // 拦截器执行顺序Interceptor1.pre → Interceptor2.pre → 控制器方法 public boolean preHandle(...) { /* 控制器方法执行前 */ } // 控制器处理完成后倒序执行 public void postHandle(...) { /* 控制器执行后,视图渲染前 */ } // 最终一定会执行(类似finally) public void afterCompletion(...) { /* 整个请求完成后 */ } ``` 4. **响应返回浏览器** - 🔙 **过滤器再次处理响应**(逆序执行) ```java // 过滤器响应处理顺序Filter3 → Filter2 → Filter1 ``` --- ### **最形象的对比表** | **阶段** | 过滤器执行位置 | 拦截器执行位置 | |----------------------|---------------------------------|---------------------------------| | **请求进入时** | Tomcat收到请求后立即处理 | Spring MVC接收到请求后处理 | | **业务处理前** | 在所有过滤器中先执行 | 按配置顺序执行preHandle() | | **业务处理后** | 在所有过滤器中最后处理响应 | postHandle()倒序执行 | | **整个流程结束后** | 无 | afterCompletion()倒序执行 | --- ### **经典执行顺序示例** 1. 用户发起`/api/login`请求 2. **FilterChain**:编码过滤器 → 安全过滤器 → 日志过滤器 3. 进入`DispatcherServlet` 4. **Interceptor**:登录校验 → 权限检查 → 参数验证 5. 执行Controller方法 6. **Interceptor逆向**:参数验证 → 权限检查 → 登录校验(postHandle) 7. 返回响应时**Filter逆向**:日志过滤器 → 安全过滤器 → 编码过滤器 --- ### **记忆技巧** 把服务器想象成**网红奶茶店**: - **过滤器** = 店门口叫号的保安(先检查健康码,最后递奶茶) - **拦截器** = 制作区的店员(先加珍珠,最后封口) **关键规律**: - 过滤器的`doFilter()`像三明治🥪:前代码 → 放行 → 后代码 - 拦截器执行像电梯🛗: - 上楼:preHandle()按1→2→3层按按钮顺序 - 下楼:postHandle()按3→2→1层自动反向 --- ### **常见坑点提醒** 1. 在过滤器的`chain.doFilter()`**之后**写的代码,会在控制器处理**完成后**执行 ```java // 错误示例:以为这里能获取响应内容 chain.doFilter(request, response); String respData = response.getContent(); // 此时可能还没写入数据! ``` 2. 拦截器的`postHandle()`中修改ModelAndView**有效**,但`afterCompletion()`中修改**无效** ```java // postHandle()适合添加统一数据 modelAndView.addObject("version", "1.0"); // afterCompletion()适合资源清理 ``` 3. 过滤器中读取请求参数时,如果其他过滤器已经调用过`request.getInputStream()`,会导致后续读取失败(类似奶茶店吸管被提前戳开)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值