Spring拦截链的原理!
这篇文章,我们帮这个小伙伴扳回一局,从概念到原理,再到核心源码,里里外外把 Spring拦截链的原理讲个透,来,开干!
1. 什么是拦截链?
简单来说,拦截链是一个处理请求的拦截器列表,按照一定的顺序,一个一个地拦截并处理请求。每个拦截器都可以在请求处理前、处理后或完成后执行一些逻辑。
比如,我们可能需要在所有请求处理前进行权限验证,在处理后记录日志,或者在请求完成后释放资源。这些操作可以通过定义不同的拦截器来实现,每个拦截器负责一个特定的任务。
2. Spring中的拦截链
在 Spring MVC中,拦截器链是通过HandlerInterceptor
接口及其实现类来实现的。Spring的DispatcherServlet
作为前端控制器(Front Controller),负责协调请求的各个阶段,包括调用拦截器。
拦截器链的实现允许多个拦截器按照一定的顺序对请求进行处理。每个拦截器都有机会在请求处理前后执行特定的逻辑,这为我们在请求处理流程中插入自定义逻辑提供了极大的灵活性。
3. 拦截链的核心组件
要理解拦截链的实现原理,首先需要了解 Spring MVC 中 4个核心组件的作用和互相之间的关系:
HandlerMapping:HandlerMapping
负责将请求URL映射到具体的处理器(Handler)。处理器通常是一个控制器(Controller)的方法。Spring提供了多种HandlerMapping
实现,如RequestMappingHandlerMapping
,支持基于注解的映射。
HandlerAdapter:HandlerAdapter
是负责执行具体处理器的组件。它知道如何调用特定类型的处理器,并返回一个ModelAndView
对象,用于渲染视图。
DispatcherServlet:DispatcherServlet
是Spring MVC的核心组件,充当前端控制器。它接收所有的HTTP请求,协调HandlerMapping
、HandlerAdapter
和视图解析等组件,最终将请求分发给合适的处理器进行处理。
HandlerInterceptor:HandlerInterceptor
接口定义了拦截器的基本行为。通过实现该接口,可以在请求处理的不同阶段插入自定义逻辑,如请求前、请求后或完成后的处理。
4. 拦截链的工作流程
了解了核心组件后,我们接下来分析拦截链是如何在这些组件之间协作,主要流程可以总结成下面 7个步骤:
-
请求到达 DispatcherServlet:所有的HTTP请求首先由 DispatcherServlet
接收。 -
查找 Handler: DispatcherServlet
使用HandlerMapping
查找与请求URL匹配的处理器(Handler)。 -
应用拦截器前置:在调用处理器之前, DispatcherServlet
会调用已注册的所有拦截器的preHandle
方法。这些拦截器按照定义的顺序依次执行。如果任意一个拦截器的preHandle
返回false
,请求将被终止,后续的拦截器和处理器将不会执行。 -
调用 HandlerAdapter 执行 Handler:所有前置拦截器的 preHandle
方法返回true
后,DispatcherServlet
会调用HandlerAdapter
执行具体的处理器方法(如Controller中的方法)。 -
应用拦截器后置:处理器执行完成后, DispatcherServlet
会调用拦截器的postHandle
方法,这些拦截器按照定义的顺序逆序执行。 -
渲染视图: DispatcherServlet
使用视图解析器(ViewResolver)渲染最终的视图,如返回一个HTML页面。 -
完成拦截器:最后, DispatcherServlet
调用拦截器的afterCompletion
方法,通知拦截器请求已经完成,同样按逆序执行。
这个流程确保了拦截器可以在请求处理的不同阶段插入逻辑,例如验证、日志记录、性能监控等。
5. 源码分析
要深入理解拦截链的实现原理,我们需要查看Spring MVC的源码。下面,我们将逐步分析DispatcherServlet
、HandlerMapping
、HandlerAdapter
和HandlerInterceptor
等组件的源码,实现对拦截链的全面理解。
5.1 DispatcherServlet的角色
DispatcherServlet
是整个Spring MVC请求处理流程的中央枢纽。它承担了接收请求、查找处理器、执行拦截器、调用处理器、渲染视图等任务。
让我们看看DispatcherServlet
中与拦截链相关的关键源码。
public class DispatcherServlet extends FrameworkServlet {
// ...其他代码...
@Override
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// ...初始化上下文...
// 1. 查找处理器
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(request, response);
return;
}
HttpServletRequest webRequest = createWebRequest(request, response);
try {
// 2. 应用拦截器的preHandle方法
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
if (!applyPreHandle(processedRequest, response, mappedHandler, interceptors)) {
return;
}
// 3. 调用处理器
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 4. 应用拦截器的postHandle方法
applyPostHandle(processedRequest, response, mappedHandler, mv, interceptors);
// 5. 渲染视图
render(mv, request, response);
// 6. 应用拦截器的afterCompletion方法
triggerAfterCompletion(processedRequest, response, mappedHandler, null, interceptors);
} catch (Exception ex) {
// 异常处理
// ...
}
}
// ...其他代码...
}
从上面的代码可以看出,DispatcherServlet
在处理请求的过程中,依次执行了查找处理器、应用拦截器的preHandle
、调用处理器、应用拦截器的postHandle
、渲染视图以及应用拦截器的afterCompletion
方法的步骤。
- 点赞
- 收藏
- 关注作者
评论(0)