请简述单个拦截器和多个拦截器的执行流程
时间: 2024-12-31 15:44:37 浏览: 7
### 单个拦截器的工作原理
在Spring MVC中,单个拦截器主要通过实现`HandlerInterceptor`接口来定义。当请求到达控制器之前,会依次调用预处理方法`preHandle()`;如果返回true,则继续执行下一个阶段,在视图渲染完成后调用后置处理器`postHandle()`,最后在整个请求结束后触发完成回调`afterCompletion()`[^4]。
对于单个拦截器而言:
- 请求进入时先经过`preHandle()`
- 如果此函数返回false则中断后续操作并直接响应客户端
- 若返回true则正常流转至Controller层处理业务逻辑
- 处理完毕后再按相反顺序依次调用`postHandle()` 和 `afterCompletion()`
```java
public class SingleInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Single Interceptor Pre Handle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Single Interceptor Post Handle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Single Interceptor After Completion");
}
}
```
### 多个拦截器的执行流程
当存在多个拦截器时,它们按照声明顺序被加入到拦截链中形成一条线性的责任链条。每个拦截器都遵循相同的生命周期管理规则,即先后经历各自的三个阶段:`preHandle()` -> Controller 执行 -> `postHandle()` -> `afterCompletion()`。值得注意的是,这些方法是以先进先出(FIFO)原则排列执行,而`postHandle()`和`afterCompletion()`则是以后进先出(LIFO)的方式逆序回溯执行[^2]。
具体来说就是:
- 对于所有的`preHandle()`方法,是从第一个到最后一个依次调用;
- 接着才是目标资源(如Controller中的Action)的具体动作;
- 随后的`postHandle()`环节又反过来由最后一个向前逐级传递控制权给前一环;
- 最终整个过程结束时再从尾部向头部遍历一遍`afterCompletion()`。
```java
public class FirstMultiInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("First Multi Interceptor Pre Handle");
return super.preHandle(request, response, handler);
}
// ... other methods ...
}
public class SecondMultiInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Second Multi Interceptor Pre Handle");
return super.preHandle(request, response, handler);
}
// ... other methods ...
}
```
假设上述两个拦截器都被配置到了同一个路径下,那么访问该路径时的实际运行日志将会显示如下序列:“First Multi Interceptor Pre Handle”,紧接着是“Second Multi Interceptor Pre Handle”。之后才会进入到对应的Controller内部去真正处理HTTP请求的内容。而在离开这个特定URL映射范围的时候,“Second Multi Interceptor”的相应钩子会被最先激活,随后才是“First Multi Interceptor”。
阅读全文