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)));
			}
		}
	}

在这里插入图片描述

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