我们知道Servlet的service方法是被Servlet容器调用的,这个时机是发生的有客户端向servlet请求服务时调用的,而这些都将其委托给DispatcherServlet的doDispatch方法。我们查看其关键代码。

		processedRequest = checkMultipart(request);
				multipartRequestParsed = processedRequest != request;

				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest, false);//1:获得HandlerExecutionChain
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.参数为HandlerExcutionChain中的handler
                                //handlerAdapter在初始化servlet时就已经设置好了
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//2:获得HandlerAdapter

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();//获得请求的方法
                                //判定method....做出相关执行
                                //利用chain中的拦截器,调用拦截器的preHandle方法,对请求进行拦截处理,如果出现异常,则直接返回
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				try {
					// Actually invoke the handler.
                                        //真正的对request进行处理,并返回一个ModelAndView对象
					mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				}
				finally {
					if (asyncManager.isConcurrentHandlingStarted()) {
						return;
					}
				}
                                //如果没有设置viewName,则通过方法设置默认的viewName
				applyDefaultViewName(request, mv);
                                //得到ModelAndView,执行拦截器的postHandle方法
                                mappedHandler.applyPostHandle(processedRequest, response, mv);
                                //将mv或者exception写入response中。。返回给客户端
                                processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

1.1首先获取HandlerExcutionChain

	protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
		return getHandler(request);
	}
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		for (HandlerMapping hm : this.handlerMappings) {//遍历这个handerMappings,那我们就需要知道handlerMappings是怎么设置
			//handlerMappings是在初始化策略中初始化handlerMappings时通过扫描ApplicationContext时获取的
                        //其中HandlerMapping类的Bean,其中就包括RequestMappingHandlerMapping实例
                        if (logger.isTraceEnabled()) {
				logger.trace(
			        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
			}//我们暂时讨论其中的RequestMappingHandlerMapping实例
			HandlerExecutionChain handler = hm.getHandler(request);//所以关键的需要chain的方法在这
			if (handler != null) {
				return handler;
			}
		}
		return null;
	}

1.2:跳到RequestMappingHandlerMapping的getHandler方法中

	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		Object handler = getHandlerInternal(request);//获取内部的handler,如果没有则返回默认的handler,是一个MethodHandler
                //。。。。。。
		// Bean name or resolved handler?判定是bean名字还是实例
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = getApplicationContext().getBean(handlerName);
		}
                //通过获得到的HandlerMethod创建一个HandlerExcutionChain。
		return getHandlerExecutionChain(handler, request);//1.5
	}
	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);//获取request的查找路径
		if (logger.isDebugEnabled()) {
			logger.debug("Looking up handler method for path " + lookupPath);
		}
                //获得存入RequestMappingHandlerMapping中的handlerMethods属性的HandlerMethod
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
                //。。。。。。。。
                
                 return (handlerMethod != null) ? handlerMethod.createWithResolvedBean() : null;
	}

1.3:如何获取HandlerMethod

	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<Match>();

		List<T> directPathMatches = this.urlMap.get(lookupPath);//直接根据path获取存入urlMap中的MappingInfo
		if (directPathMatches != null) {
			addMatchingMappings(directPathMatches, matches, request);//将匹配好的MappingInfo放入matches
		}
		if (!matches.isEmpty()) {
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
			Collections.sort(matches, comparator);//排序
			Match bestMatch = matches.get(0);//只会返回第一个匹配的Match
                        //有多个则比较,相等则抛出异常。。。。
                        //将uri中的模板参数暴露在request的属性上
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.handlerMethod;//返回HandlerMethod
		}
		else {
			return handleNoMatch(handlerMethods.keySet(), lookupPath, request);
		}
	}

1.4:通过传入一个Match的集合引用,将HandlerMethod和MappingInfo封装进Match当中

	private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
		for (T mapping : mappings) {
			T match = getMatchingMapping(mapping, request);//不太懂里面的作用,反正还是返回MappingInfo
			if (match != null) {
                             //通过mappingInfo从handlerMethods那得到HandlerMethod,所以返回的match中有MappingInfo以及HandlerMethod
                             matches.add(new Match(match, handlerMethods.get(mapping)));
			}
		}
	}

1.5创建一个HandlerExcutionChain

	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		HandlerExecutionChain chain =
			(handler instanceof HandlerExecutionChain) ?//传入handler
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);//新建一个chain对象

		chain.addInterceptors(getAdaptedInterceptors());//往chain中添加拦截器,这个以后再讲
                //这两种拦截器是有区别的,一个应该是全局的,一个是根据正则匹配的,只有符合表达式的chain才能添加拦截器。。
		String lookupPath = urlPathHelper.getLookupPathForRequest(request);
		for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
			if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
				chain.addInterceptor(mappedInterceptor.getInterceptor());//往chain中添加拦截器
			}
		}

		return chain;
	}

最后对ModelAndView进行渲染

	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
                //异常暂时不考虑其实现细节
		// Did the handler return a view to render?
		if (mv != null && !mv.wasCleared()) {
			render(mv, request, response);//渲染modelAndView
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
                //省略。。。
		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Concurrent handling started during a forward
			return;
		}

		if (mappedHandler != null) {
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		Locale locale = this.localeResolver.resolveLocale(request);//通过localResolver解析出request中的local
		response.setLocale(locale);//对响应设置local,肯定要一致才行不,。。

		View view;
		if (mv.isReference()) {//mv中的view是不是一个字符串,
			// We need to resolve the view name.//是,则需要通过viewName以及内部数据模型解析得到View
			view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
		}
		else {
			// No need to lookup: the ModelAndView object contains the actual View object.
			view = mv.getView();
		}

		// Delegate to the View object for rendering.将渲染工作交给view,并传入内部数据模型,所以实际的渲染工作是view完成的
		view.render(mv.getModelInternal(), request, response);
	}
	public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (logger.isTraceEnabled()) {
			logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
				" and static attributes " + this.staticAttributes);
		}
                //合并一些静态数据以及requestContext中的数据
		Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
                //预处理request和response
		prepareResponse(request, response);
                //这个方法的实现每个视图引擎都有不同的处理
                renderMergedOutputModel(mergedModel, request, response);//通过合并完的model进行渲染
	}
可以预测,最后通过渲染得到的内容会写入到reponse当中。。。。



Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐