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处理器。

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