SpringMVC源碼解析二:請求處理過程2

第2步處理方法:

//遍歷所有的映射器,直到找到能夠配對該請求的一個映射器,
	// 在映射器內部配對到對應的Handler,最終生成HandlerExecutionChain對象並返回
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping hm : this.handlerMappings) {
				if (logger.isTraceEnabled()) {
					logger.trace(
							"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
				}
				HandlerExecutionChain handler = hm.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}	


//this.handlerMappings在容器初始化時已經生成
//主要看下:HandlerExecutionChain handler = hm.getHandler(request);

getHandler在HandlerMapping接口中
	public interface HandlerMapping{
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
	}

HandlerMapping接口中getHandler實現類如下:

 

AbstractHandlerMapping類中實現getHandler方法:	
	
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		//抽象類的抽象方法,匹配對象請求的Handler對象,具體實現邏輯看子類
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		if (handler instanceof String) {
			//如果匹配的Handler對象只是字符串,則以字符串爲id。例如容器中得到對象的bean
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}

		//將匹配的攔截器和Handler對象全部都包裝到HandlerExecutionChain對象中
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
		
		if (CorsUtils.isCorsRequest(request)) {
			CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
			CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
			CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}
		return executionChain;
	}


protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;

getHandler裏面有兩個方法:

2.1.//抽象類的抽象方法,匹配對象請求的Handler對象,具體實現邏輯看子類

Object handler = getHandlerInternal(request);

2.2//將匹配的攔截器和Handler對象全部都包裝到HandlerExecutionChain對象中
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

先看2.1:

   Object handler = getHandlerInternal(request);
   AbstractHandlerMapping中有接口:
   protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;
   getHandlerInternal接口實現類分爲兩個類:
        AbstractUrlHandlerMapping               //實現url匹配controller
        AbstractHandlerMethodMapping       //實現Method匹配方法

      首先看AbstractUrlHandlerMapping實現方法:

    protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
		//根據請求獲取路徑
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		//根據路徑獲取Handler
		Object handler = lookupHandler(lookupPath, request);
		if (handler == null) {
			// We need to care for the default handler directly, since we need to
			// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
			Object rawHandler = null;
			if ("/".equals(lookupPath)) {
				rawHandler = getRootHandler();
			}
			if (rawHandler == null) {
				rawHandler = getDefaultHandler();
			}
			if (rawHandler != null) {
				// Bean name or resolved handler?
				if (rawHandler instanceof String) {
					String handlerName = (String) rawHandler;
					rawHandler = obtainApplicationContext().getBean(handlerName);
				}
				validateHandler(rawHandler, request);
				handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
			}
		}
		if (handler != null && logger.isDebugEnabled()) {
			logger.debug("Mapping [" + lookupPath + "] to " + handler);
		}
		else if (handler == null && logger.isTraceEnabled()) {
			logger.trace("No handler mapping found for [" + lookupPath + "]");
		}
		return handler;
	}

	
	protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
		// Direct match?
		//直接嘗試匹配
		Object handler = this.handlerMap.get(urlPath);
		if (handler != null) {
			// Bean name or resolved handler?
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			validateHandler(handler, request);
			return buildPathExposingHandler(handler, urlPath, urlPath, null);
		}

		// Pattern match?
		//再次嘗試模式匹配
		List<String> matchingPatterns = new ArrayList<>();
		for (String registeredPattern : this.handlerMap.keySet()) {
			if (getPathMatcher().match(registeredPattern, urlPath)) {
				matchingPatterns.add(registeredPattern);
			}
			else if (useTrailingSlashMatch()) {
				if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {
					matchingPatterns.add(registeredPattern +"/");
				}
			}
		}

		String bestMatch = null;
		Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
		if (!matchingPatterns.isEmpty()) {
			Collections.sort(matchingPatterns, patternComparator);
			if (logger.isDebugEnabled()) {
				logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
			}
			bestMatch = matchingPatterns.get(0);
		}
		if (bestMatch != null) {
			handler = this.handlerMap.get(bestMatch);
			if (handler == null) {
				if (bestMatch.endsWith("/")) {
					handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
				}
				if (handler == null) {
					throw new IllegalStateException(
							"Could not find handler for best pattern match [" + bestMatch + "]");
				}
			}
			// Bean name or resolved handler?
			if (handler instanceof String) {
				String handlerName = (String) handler;
				handler = obtainApplicationContext().getBean(handlerName);
			}
			validateHandler(handler, request);
			String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);

			// There might be multiple 'best patterns', let's make sure we have the correct URI template variables
			// for all of them
			Map<String, String> uriTemplateVariables = new LinkedHashMap<>();
			for (String matchingPattern : matchingPatterns) {
				if (patternComparator.compare(bestMatch, matchingPattern) == 0) {
					Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
					Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
					uriTemplateVariables.putAll(decodedVars);
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
			}
			return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
		}

		// No handler found...
		return null;
	}

現在看第二種實現方式:AbstractHandlerMethodMapping

在容器初始化過程中創建映射器(RequestMappingHandlerMapping)對象時,
	會尋找所有被@Controller 註解類中被 @RequestMapping 註解的方法,
	然後解析方法上的 @RequestMapping 註解,把解析結果封裝成 RequestMappingInfo 對象,
	也就是說RequestMappingInfo 對象是用來裝載方法的匹配相關信息,
	每個匹配的方法都會對應一個 RequestMappingInfo 對象。

	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		if (logger.isDebugEnabled()) {
			logger.debug("Looking up handler method for path " + lookupPath);
		}
		this.mappingRegistry.acquireReadLock();
		try {
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			if (logger.isDebugEnabled()) {
				if (handlerMethod != null) {
					logger.debug("Returning handler method [" + handlerMethod + "]");
				}
				else {
					logger.debug("Did not find handler method for [" + lookupPath + "]");
				}
			}
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}

	
	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<>();
		//根據請求的lookupPath,找到對應的記錄映射方法信息的對象的數組,也就是List<T>
		//當實現類是RequestMappingHandlerMapping時,T就是RequestMappingInfo
		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...
			//有時候根據lookupPath匹配不了對應的方法記錄信息,例如restful風格/test/{username}
			//但是實際lookupPath=/test/tom,這樣就需要遍歷所有的Mappings
			addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
		}

		if (!matches.isEmpty()) {
			//getMappingComparator(request) 該抽象類的抽象方法,如果最終一個request匹配出多個
			//RequestMappingInfo,那麼最終由實現類自己實現排序邏輯
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
			Collections.sort(matches, comparator);
			if (logger.isTraceEnabled()) {
				logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
						lookupPath + "] : " + matches);
			}
			Match bestMatch = matches.get(0);
			if (matches.size() > 1) {
				if (CorsUtils.isPreFlightRequest(request)) {
					return PREFLIGHT_AMBIGUOUS_MATCH;
				}
				Match secondBestMatch = matches.get(1);
				if (comparator.compare(bestMatch, secondBestMatch) == 0) {
					Method m1 = bestMatch.handlerMethod.getMethod();
					Method m2 = secondBestMatch.handlerMethod.getMethod();
					throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
							request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
				}
			}
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.handlerMethod;
		}
		else {
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}

	//遍歷所有的mapping,也就會上面的List<RequestMappingInfo>
	private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
		for (T mapping : mappings) {
			//該抽象類的抽象方法,由實現類自己實現檢測邏輯,
			// 匹配request對象和RequestMappingInfo上面對應的信息是否匹配,匹配規則自己寫
			T match = getMatchingMapping(mapping, request);
			if (match != null) {
				//將匹配的RequestMappingInfo對象和其對應的HandlerMethod 對象裝進Match對象,放進matches集合裏面
				matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
			}
		}
	}

	

2.2//將匹配的攔截器和Handler對象全部都包裝到HandlerExecutionChain對象中

HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

以上就是第二步的源碼,主要是取得處理當前請求的controller,這裏也稱爲hanlder處理器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章