spring DispatcherServlet doDispatch 阅读笔记

首先列举下几个基础知识也就是spring 文档里面的重要的一个 Special Bean Types哈。

HandlerMapping,顾名思义用于对handler的映射。主要方法

@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

接受一个基础的request对象,返回一个HandlerExecutionChain。返回的是一个处理链哈,把拦截器和handler一起装载进去了。HandlerExecutionChain代码比较长自己看源码去。

再回到doDispatch 方法。直接上代码

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;//整个方法的核心对象
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);//检查是否包含文件流
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
                //决定当前request使用哪一个handler
				mappedHandler = getHandler(processedRequest);
                 //为空就使用默认的handler.
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
                //确定当前request的dandler的handler adapter
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = HttpMethod.GET.matches(method);
				if (isGet || HttpMethod.HEAD.matches(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

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

				// Actually invoke the handler.
                //实际调用hander方法的地方。                
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

整个代码其实目的很明确,就是通过为request找到对应的handler 然后调用hander方法处理请求.

1,通过request对象获取handler,代码如下

// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);

getHandler方法为直接遍历所有的handlermapping.返回获取的第一个handler.handlermapping本身是有一个排序的哈。注意这里返回的是HandlerExecutionChain。handler和interceptor一起被打包进去了。有兴趣可以看看getHandler的实现是怎么组装interceptor。

@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   if (this.handlerMappings != null) {
      for (HandlerMapping mapping : this.handlerMappings) {
         HandlerExecutionChain handler = mapping.getHandler(request);
         if (handler != null) {
            return handler;
         }
      }
   }
   return null;
}

2.1事实上在我们获取到handler之后直接往下执行就好了。不同类型的handler直接加一个类型判断。再来个类型转换就好了。spring的做法更优雅。

持有一个handlerAdapter集合,这部分是初始化时候获取的,注册到ioc容器就行。spring通过类型加载。获取到handler后遍历handlerAdapter。通过handler的真实类型来判断是否支持处理。在handle的时候。强转handler的类型就ok。因为handlerAdapter是针对固定类型编码的。往下看选择HandlerAdapter的代码。

// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   if (this.handlerAdapters != null) {
      for (HandlerAdapter adapter : this.handlerAdapters) {
         if (adapter.supports(handler)) {
            return adapter;
         }
      }
   }
   throw new ServletException("No adapter for handler [" + handler +
         "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

持有一个HandlerAdapter的集合,遍历这个集合找到合适的HandlerAdapter。看一下adapter的support方法,这里就是进行判断。等于说以这种方式获取了handler的类型。因为adapter就是根据handler编写的。可以说是一对一关系。

@Override
public boolean supports(Object handler) {
   return (handler instanceof Controller);
}

adapter的handle方法很直接直接转型。adapter这部分代码使用SimpleControllerHandlerAdapter的,其它得实现大同小异哈。

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {

   return ((Controller) handler).handleRequest(request, response);
}

总结

总的来说就是持有一个HandlerMapping集合。一个handlerAdapter集合,HandlerMapping遍历调用getHandler获取handler(其实是一个HandlerExecutionChain 除了handler还有其他私货拦截器),handlerAdapter集合再去通过handler遍历调用supports来判断类型。找到确定的handlerAdapter,再去执行hander方法。到这里就结束了。

引入handlerAdapter就是为了可扩展,里面就是一些类型判断和转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值