spring HandlerMapping、HandlerExecutionChain 、HandlerAdapter的作用

HandlerMapping

HandlerMapping是request与handler object之间的映射,它能根据request找到对应的handler。handler object总会被包装成HandlerExecutionChain ,HandlerExecutionChain 里含有handler object、interceptor等。
HandlerMapping接口仅有一个方法getHandler,从方法注释中得知,handler object可以是任意类型,甚至都不需要实现标签接口,这样的好处是允许使用其他框架的handler object。
注意,在getHandler时,会进行content-type、参数、url、method等要素匹配,如果找不到对应的handler object(通常是@controller、@requestmapping注解的方法,也就是HandlerMethod),则会出抛出异常,返回404、405之类的状态码。

/**
	 * 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
	 */
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

看一个HandlerMapping实例,<mvc:annotation-driven>标签注册RequestMappingHandlerMapping,它实现了HandlerMapping接口,此类中的lookupHandlerMethod方法负责寻找request对应的HandlerMethod。

/**
	 * Look up the best-matching handler method for the current request.
	 * If multiple matches are found, the best match is selected.
	 * @param lookupPath mapping lookup path within the current servlet mapping
	 * @param request the current request
	 * @return the best-matching handler method, or {@code null} if no match
	 * @see #handleMatch(Object, String, HttpServletRequest)
	 * @see #handleNoMatch(Set, String, HttpServletRequest)
	 */
	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<Match>();
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
		if (directPathMatches != null) {
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
			// No choice but to go through all mappings...
			addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
		}

		if (!matches.isEmpty()) {
			// 省略
		}
		else {
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}

HandlerExecutionChain

HandlerExecutionChain 是Handler执行链,包含handler Object、interceptor。所以HandlerExecutionChain 提供了getHandler、getInterceptors方法,配置文件中配置的interceptor都会加入到HandlerExecutionChain
在这里插入图片描述

实例

接下来看一下HandlerMapping、HandlerExecutionChain的实际应用,DispatcherServlet的doDispatch方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
				HandlerExecutionChain mappedHandler = null;
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
				
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
	}

大体流程是,根据request获取到HandlerExecutionChain ,根据HandlerExecutionChain 获取到handler,根据handler获取HandlerAdapter ,HandlerAdapter 判断文件是否被修改过,如果没修改过,直接返回。否则,HandlerExecutionChain 执行拦截器的prehandle方法,然后HandlerAdapter 执行实际处理。

HandlerAdapter

HandlerAdapter 是Handler适配器,负责具体的request处理,比如参数解析、返回值处理。

/**
	 * Use the given handler to handle this request.
	 * The workflow that is required may vary widely.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @param handler handler to use. This object must have previously been passed
	 * to the {@code supports} method of this interface, which must have
	 * returned {@code true}.
	 * @throws Exception in case of errors
	 * @return ModelAndView object with the name of the view and the required
	 * model data, or {@code null} if the request has been handled directly
	 */
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

总结

个人感觉,HandlerMapping、HandlerExecutionChain 、HandlerAdapter是spring mvc最重要的三个组件了

  • HandlerMapping
    • 是request与handler object的映射,负责url、参数、content-type、method等匹配
  • HandlerExecutionChain
    • 是handler执行链,它包装了handler obejct、interceptor,很典型的包装对象
  • HandlerAdapter
    • 顾名思义,是handler的适配器,它能处理参数转换为handler能接受的数据类型,解析参数、处理返回值等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值