概述
HandlerExecutionChain
可以被想象成一个"容器",不过为了避免和我们常说的Spring
容器中的"容器"混淆,使用"持有者"更合适。这个"持有者"的设计目的就是持有一些东西,这些东西是什么呢?是一个Handler
,和一组特定顺序的HandlerInterceptor
。
所持有的Handler
可以被理解成被正经设计为处理目标请求,输出响应数据的处理逻辑,可能是某个开发人员实现的控制器方法逻辑,也可能是Spring MVC
容器根据配置提供的某个方法逻辑。
而一个HandlerInterceptor
则是类似于AOP
中切面的一种概念逻辑。这些HandlerInterceptor
可能由框架自身提供,也可能由开发人员提供,然后在Spring MVC
初始化过程中,符合某种特征的HandlerInterceptor
会按特定顺序包裹到某些Handler
外面,形成一个个HandlerExecutionChain
,待DispatcherServlet
用于请求处理。
DispatcherServlet
处理一个请求的主要逻辑中,第一个重要的步骤就是根据请求中所携带的信息(主要是URL
信息)找到合适的Handler
,这里找到的Handler
其实就是HandlerExecutionChain
的形式。
在DispatcherServlet
执行目标Handler
(也就是所找到的HandlerExecutionChain
中的Handler
对象)之前,首先是执行HandlerExecutionChain#applyPreHandle
,也就是执行HandlerExecutionChain
中HandlerInterceptor
数组里各个HandlerInterceptor
对象方法applyPreHandle
。这些HandlerInterceptor#applyPreHandle
执行的顺序是所属HandlerInterceptor
在数组中索引的正序(从索引为0到索引最大)。如果这些HandlerInterceptor#applyPreHandle
的执行没有任何一个返回false
,则随后DispatcherServlet
会继续执行Handler
处理请求。如果这些HandlerInterceptor#applyPreHandle
的执行有任何一个返回false
,则可以认为它对请求已经进行了处理,此时会调用当前HandlerExecutionChain
的triggerAfterCompletion
(语义稍后介绍),不再继续其他HandlerInterceptor#applyPreHandle
/HandlerInterceptor#applyPostHandle
的执行,并且DispatcherServlet
也不会再继续执行Handler
。
DispatcherServlet
对目标Handler
的执行,其实是对所找到的HandlerExecutionChain
中的Handler
对象的执行(具体的执行逻辑另行介绍)。
DispatcherServlet
执行完目标Handler
之后,会执行HandlerExecutionChain#applyPostHandle
,也就是执行HandlerExecutionChain
里每个HandlerInterceptor
方法applyPostHandle
。这些HandlerInterceptor#applyPostHandle
执行的顺序是所属HandlerInterceptor
在数组中索引的逆序(从索引最大到索引为0)。注意方法HandlerExecutionChain#applyPostHandle
不返回任何值。
DispatcherServlet
调用完Handler
,HandlerExecutionChain#applyPostHandle
,以及处理完Handler
结果(包括视图解析和渲染)之后,无论是否有异常,都会调用方法HandlerExecutionChain#triggerAfterCompletion
应用到请求/响应对象,该方法的参数ex
用于表示以上过程中发生异常时的异常对象,如果以上过程没有遇到异常,则ex
会是null
。
总结
HandlerExecutionChain
所持有的对象Handler
– 处理请求的目标Handler
HandlerInterceptor
– 0或多个Handler
处理请求的前置/后置/完成时拦截处理器
HandlerExecutionChain
所提供的中重要方法applyPreHandle
– 前置拦截处理器applyPostHandle
– 后置拦截处理器triggerAfterCompletion
– 完成时拦截处理器这里"完成时"覆盖正常完成时和异常完成时两种情况。
源代码
源代码版本 : spring-webmvc-5.1.5.RELEASE
package org.springframework.web.servlet;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
/**
* Handler execution chain, consisting of handler object and any handler interceptors.
* Returned by HandlerMapping's HandlerMapping#getHandler method.
*
* @author Juergen Hoeller
* @since 20.06.2003
* @see HandlerInterceptor
*/
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
// 所持有的 Handler,当前 Handler
private final Object handler;
// 保存当前 Handler 的拦截器,一个数组,说明拦截器可以有多个
@Nullable
private HandlerInterceptor[] interceptors;
// 辅助数组 interceptors 工作的 拦截器 list,以 interceptors 为主,具体使用方法可以参考 :
// 1. HandlerExecutionChain(handler,interceptors)
// 2. getInterceptors
@Nullable
private List<HandlerInterceptor> interceptorList;
// 记录 preHandle 方法应用返回 true 的最后一个 HandlerInterceptor 的索引,
// 用于方法 applyPreHandle 和 triggerAfterCompletion 之间的运行协调
private int interceptorIndex = -1;
/**
* Create a new HandlerExecutionChain.
* @param handler the handler object to execute
*/
public HandlerExecutionChain(Object handler) {
this(handler, (HandlerInterceptor[]) null);
}
/**
* Create a new HandlerExecutionChain.
* @param handler the handler object to execute
* @param interceptors the array of interceptors to apply
* (in the given order) before the handler itself executes
*/
public HandlerExecutionChain(Object handler, @Nullable HandlerInterceptor... interceptors) {
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
this.handler = originalChain.getHandler();
this.interceptorList = new ArrayList<>();
CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
}
else {
this.handler = handler;
this.interceptors = interceptors;
}
}
/**
* Return the handler object to execute.
*/
public Object getHandler() {
return this.handler;
}
public void addInterceptor(HandlerInterceptor interceptor) {
initInterceptorList().add(interceptor);
}
public void addInterceptors(HandlerInterceptor... interceptors) {
if (!ObjectUtils.isEmpty(interceptors)) {
CollectionUtils.mergeArrayIntoCollection(interceptors, initInterceptorList());
}
}
private List<HandlerInterceptor> initInterceptorList() {
if (this.interceptorList == null) {
this.interceptorList = new ArrayList<>();
if (this.interceptors != null) {
// An interceptor array specified through the constructor
CollectionUtils.mergeArrayIntoCollection(this.interceptors, this.interceptorList);
}
}
this.interceptors = null;
return this.interceptorList;
}
/**
* Return the array of interceptors to apply (in the given order).
* @return the array of HandlerInterceptors instances (may be null)
*/
@Nullable
public HandlerInterceptor[] getInterceptors() {
if (this.interceptors == null && this.interceptorList != null) {
this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[0]);
}
return this.interceptors;
}
/**
* 调用者调用 Handler 之前,会调用当前 HandlerExecutionChain 的此方法应用所有的
* HandlerInterceptor#preHandle 到请求/响应对象,注意 HandlerInterceptor#preHandle 执行的顺序
* 是它们在数组中的索引正序
* Apply preHandle methods of registered interceptors.
* @return true if the execution chain should proceed with the
* next interceptor or the handler itself. Else, DispatcherServlet assumes
* that this interceptor has already dealt with the response itself.
* 返回值语义 :
* true -- 调用者 DispatcherServlet 继续执行 Handler
* false -- 某个拦截器已经对请求/响应作出处理,调用者 DispatcherServlet 不需要再继续执行 Handler
*/
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 遍历执行每个 HandlerInterceptor#preHandle :
// 如果返回 true,继续执行下一个 HandlerInterceptor#preHandle,
// 如果返回 false, 则不再继续调用其它的 HandlerInterceptor#preHandle,而是调用 triggerAfterCompletion,
// 然后整个函数结束,返回 false
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
// 记录 preHandle 方法应用返回 true 的最后一个 HandlerInterceptor 的索引
this.interceptorIndex = i;
}
}
// 如果没有任何一个 HandlerInterceptor#preHandle 返回 false, 则整个函数返回 true
return true;
}
/**
* Apply postHandle methods of registered interceptors.
* 调用者,其实也就是 DispatcherServlet,在调用完 Handler 之后,会调用当前 HandlerExecutionChain 的此方法应用
* 所有的 HandlerInterceptor#postHandle 到请求/响应对象,注意 HandlerInterceptor#postHandle 执行的顺序
* 是它们在数组中的索引逆序
*/
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
/**
* Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
* Will just invoke afterCompletion for all interceptors whose preHandle invocation
* has successfully completed and returned true.
* 调用者,也就是 DispatcherServlet , 调用完 Handler,HandlerExecutionChain#applyPostHandle,
* 以及处理完Handler结果(包括视图解析和渲染)之后,无论是否有异常,都会调用该方法
* HandlerExecutionChain#triggerAfterCompletion。
* 该方法的参数 ex 用于表示以上过程中发生异常时的异常对象,如果以上过程没有遇到异常,则ex会是null。
*/
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 逆序遍历每个应用 applyPreHandle 成功的 HandlerInterceptor 的方法 afterCompletion 到请求/响应,
// 注意:并不是遍历每个 HandlerInterceptor,而是只遍历应用 applyPreHandle 成功的那些 HandlerInterceptor
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
/**
* Apply afterConcurrentHandlerStarted callback on mapped AsyncHandlerInterceptors.
*/
void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
if (interceptors[i] instanceof AsyncHandlerInterceptor) {
try {
AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptors[i];
asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
}
catch (Throwable ex) {
logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);
}
}
}
}
}
/**
* Delegates to the handler and interceptors' toString().
*/
@Override
public String toString() {
Object handler = getHandler();
StringBuilder sb = new StringBuilder();
sb.append("HandlerExecutionChain with [").append(handler).append("] and ");
if (this.interceptorList != null) {
sb.append(this.interceptorList.size());
}
else if (this.interceptors != null) {
sb.append(this.interceptors.length);
}
else {
sb.append(0);
}
return sb.append(" interceptors").toString();
}
}