Spring MVC : 概念模型 HandlerExecutionChain

深入探讨SpringMVC框架中HandlerExecutionChain的作用与工作原理,解析其如何组织Handler与HandlerInterceptor,以及在请求处理流程中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

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,也就是执行HandlerExecutionChainHandlerInterceptor数组里各个HandlerInterceptor对象方法applyPreHandle。这些HandlerInterceptor#applyPreHandle执行的顺序是所属HandlerInterceptor在数组中索引的正序(从索引为0到索引最大)。如果这些HandlerInterceptor#applyPreHandle的执行没有任何一个返回false,则随后DispatcherServlet会继续执行Handler处理请求。如果这些HandlerInterceptor#applyPreHandle的执行有任何一个返回false,则可以认为它对请求已经进行了处理,此时会调用当前HandlerExecutionChaintriggerAfterCompletion(语义稍后介绍),不再继续其他HandlerInterceptor#applyPreHandle/HandlerInterceptor#applyPostHandle的执行,并且DispatcherServlet也不会再继续执行Handler

DispatcherServlet对目标Handler的执行,其实是对所找到的HandlerExecutionChain中的Handler对象的执行(具体的执行逻辑另行介绍)。

DispatcherServlet执行完目标Handler之后,会执行HandlerExecutionChain#applyPostHandle,也就是执行HandlerExecutionChain里每个HandlerInterceptor方法applyPostHandle。这些HandlerInterceptor#applyPostHandle执行的顺序是所属HandlerInterceptor在数组中索引的逆序(从索引最大到索引为0)。注意方法HandlerExecutionChain#applyPostHandle不返回任何值。

DispatcherServlet 调用完HandlerHandlerExecutionChain#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();
	}

}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值