Spring mvc之HandlerExecutionChain
处理程序执行链,由处理程序对象和任何处理程序拦截器组成。由HandlerMapping的HandlerMapping.getHandler方法返回。
其属性有:
- Object类型的handler;
- HandlerInterceptor[]类型的interceptors;
- List<HandlerInterceptor>类型的interceptorList;
- int类型的interceptorIndex;
其构造方法有两个,如下所示:
public HandlerExecutionChain(Object handler);
public HandlerExecutionChain(Object handler, @Nullable HandlerInterceptor... interceptors);
构造方法具体实现代码:
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;
}
}
从构造方法可以发现,实例化入参有2个,分别是handler和interceptors数组。首先,判断handler是否为HandlerExecutionChain的实例,如果是则进行强制类型转换,获取handler并存入当前对象的handler中,然后把handler入参的interceptors对象存入当前实例化的interceptorList中,以及入参中的interceptors存入当前对象的interceptorList中;如果handler不是HandlerExecutionChain的实例,则直接把handler存入当前实例的handler字段中,interceptors数组对象存入当前实例的interceptors属性字段中。
1. applyPreHandle方法
返回值:如果执行链应继续处理下一个拦截器或处理程序本身,则为true。否则,DispatcherServlet假设这个拦截器已经处理了响应本身。
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
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;
}
this.interceptorIndex = i;
}
}
return true;
}
2. applyPostHandle方法
应用已注册拦截器的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);
}
}
}
3. triggerAfterCompletion方法
在映射的HandlerInterceptors上触发完成后回调。将只为其预处理调用已成功完成并返回true的所有拦截器调用afterCompletion。
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
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);
}
}
}
}
4. applyAfterConcurrentHandlingStarted方法
在映射的AsyncHandlerInterceptors上应用afterConcurrentHandlerStarted回调。
void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
if (interceptor instanceof AsyncHandlerInterceptor) {
try {
AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptor;
asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
}
catch (Throwable ex) {
if (logger.isErrorEnabled()) {
logger.error("Interceptor [" + interceptor + "] failed in afterConcurrentHandlingStarted", ex);
}
}
}
}
}
}
5. 装载拦截器
AbstractHandlerMapping类中,获取到HandlerMethod对象后,如果不为空就会给其包装成一个HandlerExecutionChain对象,该对象将被加入拦截器信息。
为给定的处理程序构建HandlerExecutionChain,包括适用的拦截器。
默认实现使用给定的处理程序、处理程序映射的公共拦截器以及与当前请求URL匹配的任何MappedInterceptors构建标准HandlerExecutionChain。拦截器按注册顺序添加。子类可以重写它以扩展/重新排列拦截器列表。
如下代码所示:
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}