org.springframework.web.servlet.DispatcherServlet-doDispatch-getHandler方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		/**
		 * 聲明變量 HttpServletRequest HandlerExecutionChain Handler執行鏈包含和最扣執行的Handler
		 */
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		//是不是一個多組件請求
		boolean multipartRequestParsed = false;
		//異步管理器
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			//視圖
			ModelAndView mv = null;
			//異常
			Exception dispatchException = null;

			try {
				/**
				 * 1.檢查是否上傳請求
				 */
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
				/**
				 * 2.根據processedRequest獲取映射的Handler執行鏈 HandlerExecutionChain
				 * 有當前請求的Handler和Inteceptor
				 */
				mappedHandler = getHandler(processedRequest);

getHandler方法

	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			/**
			 * 遍歷handlerMappings 映射器
			 */
			for (HandlerMapping mapping : this.handlerMappings) {
				//根據請求獲取HandlerExecutionChain
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

request中有請求的url
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

org.springframework.web.servlet.handler.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) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}
		/**
		 * 獲取HandlerExecutionChain
		 */
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

		if (logger.isTraceEnabled()) {
			logger.trace("Mapped to " + handler);
		}
		else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
			logger.debug("Mapped to " + executionChain.getHandler());
		}
		/**
		 * 跨域配置
		 */
		if (CorsUtils.isCorsRequest(request)) {
			CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
			CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
			CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}

		return executionChain;
	}

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal方法


	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		/**
		 * 獲取請求的url如 /demo/handler01
		 */
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		this.mappingRegistry.acquireReadLock();
		try {
			/**
			 * 查詢和url reqeust匹配的HandlerMthod
			 */
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			//返回
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod方法


protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<>();
		/**
		 * 根據URL獲取匹配 ,可以匹配到多個
		 * 通過uri直接在註冊的RequestMapping中獲取對應的RequestMappingInfo列表,需要注意的是,
		 * 這裏進行查找的方式只是通過url進行查找,但是具體哪些RequestMappingInfo是匹配的,還需要進一步過濾
		 */
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
		if (directPathMatches != null) {
			/**
			 * 如果匹配的就添到上面的集合中
			 */
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
			// 如果無法通過uri進行直接匹配,則對所有的註冊的RequestMapping進行匹配,這裏無法通過uri
			// 匹配的情況主要有三種:
			// ①在RequestMapping中定義的是PathVariable,如/user/detail/{id};
			// ②在RequestMapping中定義了問號表達式,如/user/?etail;
			// ③在RequestMapping中定義了*或**匹配,如/user/detail/**
			// No choice but to go through all mappings...
			addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
		}

		if (!matches.isEmpty()) {
			/**
			 * 使用生成一個比較器
			 * 對匹配的結果進行排序,獲取相似度最高的一個作爲結果返回,這裏對相似度的判斷時,
			 *
			 */
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
			//使用比較器排序
			matches.sort(comparator);
			//排序後第一個是最好的,獲取匹配程度最高的一個匹配結果
			Match bestMatch = matches.get(0);
			if (matches.size() > 1) {
				if (logger.isTraceEnabled()) {
					logger.trace(matches.size() + " matching mappings: " + matches);
				}
				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();
					String uri = request.getRequestURI();
					throw new IllegalStateException(
							"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
				}
			}
			request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
			//這裏主要是對匹配結果的一個處理,主要包含對傳入參數和返回的MediaType的處理
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.handlerMethod;
		}
		else {
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}

這裏對於結果的匹配,首先會通過uri進行直接匹配,如果能匹配到,則在匹配結果中嘗試進行RequestMethod,Consumes和Produces等配置的匹配;如果通過uri不能匹配到,則直接對所有定義的RequestMapping進行匹配,這裏主要是進行正則匹配,如果能匹配到。如果能夠匹配到,則對匹配結果按照相似度進行排序,並且對前兩個結果相似度進行比較,如果相似度一樣,則拋出異常,如果不一樣,則返回相似度最高的一個匹配結果。如果無法獲取到匹配結果,則對所有的匹配結果進行遍歷,判斷當前request具體是哪一部分參數無法匹配到結果。對於匹配結果的獲取,主要在addMatchingMappings()方法中

addMatchingMappings方法

	private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
		for (T mapping : mappings) {
			T match = getMatchingMapping(mapping, request);
			if (match != null) {
				matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
			}
		}
	}

在這裏插入圖片描述

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