03-HandlerMapping

HandlerMapping

  • HandlerMapping定义了请求和请求处理器之间的映射关系,框架的实现类有:BeanNameUrlHandlerMapping和RequestMappingHandlerMapping等
  • 请求处理器handler总是被HandlerExecutionChain包装的,DispatcherServlet按照顺序调用每个拦截器的preHandle方法,如果所有的preHandle返回true,再最后调用处理器,最后倒序调用postHandle。

一、HandlerMapping接口

  • HandlerMapping接口定义了部分常量和一个getHandler方法,该方法根据HttpServletRequest请求对象返回HandlerExecutionChain
public interface HandlerMapping {
 
	/**
	 * Return a handler and any interceptors for this request. The choice may be made
	 * on request URL, session state, or any factor the implementing class chooses.
	 * <p>The returned HandlerExecutionChain contains a handler Object, rather than
	 * even a tag interface, so that handlers are not constrained in any way.
	 * For example, a HandlerAdapter could be written to allow another framework's
	 * handler objects to be used.
	 * <p>Returns {@code null} if no match was found. This is not an error.
	 * The DispatcherServlet will query all registered HandlerMapping beans to find
	 * a match, and only decide there is an error if none can find a handler.
	 * 
	 * @param request current HTTP request
	 * @return a HandlerExecutionChain instance containing handler object and
	 * any interceptors, or {@code null} if no mapping found
	 * @throws Exception if there is an internal error
	 */
	@Nullable
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

二、HandlerExecutionChain

  • HandlerExecutionChain代表请求处理器链(Handler execution chain),由请求处理器和请求拦截器组成。它封装了全部的HandlerInterceptor拦截器并且包含处理器handler,提供了调用拦截器和handler的方法
  • 下面是部分源码和注释,一些简单的get属性的方法和简单代码已经省略
public class HandlerExecutionChain {

    //handler处理器对象
	private final Object handler;

    //拦截器数组和拦截器链
	@Nullable
	private HandlerInterceptor[] interceptors;

	@Nullable
	private List<HandlerInterceptor> interceptorList;

    //处理拦截器时,preHandle返回true的拦截器对应的下标
	private int interceptorIndex = -1;

	//构造方法
	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;
		}
	}

    //添加拦截器
	public void addInterceptor(HandlerInterceptor interceptor) {
		initInterceptorList().add(interceptor);
	}

    //获取拦截器
	public HandlerInterceptor[] getInterceptors() {
		if (this.interceptors == null && this.interceptorList != null) {
			this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
		}
		return this.interceptors;
	}


    //调用全部拦截器的preHandle方法,并且会记录返回true的下标,triggerAfterCompletion只会执行哪些返回true的拦截器,
    //比如下标从0-10,0-4返回true,下标5返回false,那么triggerAfterCompletion只会从下标4的拦截器开始倒序执行到0
	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;
	}

    //调用拦截器的postHandle方法,只会调用preHandle返回true的拦截器对应的postHandle方法,调用顺序和preHandle相反
	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);
			}
		}
	}

    //调用拦截器的afterCompletion,只会调用preHandle返回true的拦截器对应的afterCompletion方法,调用顺序和preHandle相反
	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);
				}
			}
		}
	}

    //这个方法会在Controller方法异步执行时开始执行
	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);
					}
				}
			}
		}
	}
}

三、HandlerInterceptor

  • HandlerInterceptor是SpringMvc的处理器拦截器,它定义了三个方法
public interface HandlerInterceptor {

    //预处理回调方法
    //拦截handler处理器的执行,执行时机是在HandlerMapping找到合适的处理器之后,在HandlerAdapter调用处理器之
    //前(简单说就算找到处理器之后,先执行拦截器,再执行真正的处理器)
    //DispatcherServlet在一个链里面执行处理器,因此链里面的任何一个拦截器都可以中断这个链的执行,该方法返回false,
    //后面的拦截器就不会执行了,返回false的话就可以直接通过response来响应了
    //通常用于执行前的校验,检查,日志记录,性能监控逻辑
	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
	                throws Exception {
		return true;
	}

	//后处理回调方法
	//调用时机是在HandlerAdapter真正调用了处理器之后,但是在DispatcherServlet渲染示图之前
	//可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理
	//执行顺序是倒序执行,和preHandle相反
	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
	                @Nullable ModelAndView modelAndView) throws Exception {
	}

    //整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还
    //可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
	//注意只有对应的拦截器的preHandle返回true,afterCompletion才会被执行,
	//执行顺序是倒序执行,和preHandle相反
	//关于异步请求处理,查看:AsyncHandlerInterceptor
	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
	                @Nullable Exception ex) throws Exception {
	}
}

四、RequestMappingHandlerMapping

  • RequestMappingHandlerMapping是HandlerMapping的一个核心实现类,关于请求处理器的加载,拦截器的加载以及请求处理器的获取都和RequestMappingHandlerMapping密切相关,在后文中会分析这些流程。

五、小结

  • HandlerMapping是映射器的顶层接口,根据请求来查询处理对应请求的处理器,查询到返回的是一个处理器执行链
  • 处理器执行链封装了处理器方法和写拦截器,拦截器会有对应的方法在处理器方法的前后调用执行
  • 拦截器的前置方法如果有一个返回false,那么请求就会返回,拦截器的前置后置方法执行顺序是倒序的,比如前置方法是1->2->3,那么后置方法执行就是3->2->1
  • 关于拦截器的扫描加载,Handler处理器的扫描加载,Handler处理器的获取细节在后面的文章中开展
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值