SpringBoot获取处理器流程

目录

一、获取处理器流程

1、获取处理器流程流程图

2、DispatcherServlet组件

2.1、doService()

2.2、doDispatch()逻辑

2.3、getHandler()逻辑

3、AbstractHandlerMapping组件

4、RequestMappingInfoHandlerMapping组件

5、AbstractHandlerMethodMapping组件

5.1、getHandlerInternal()逻辑

5.2、lookupHandlerMethod()逻辑


一、获取处理器流程

1、获取处理器流程流程图

SpringBoot获取处理器流程_第1张图片

客户端请求过来,经过一系列的servlet,进来到DispatcherServlet控制器,经过上图的方法调用链路,经过映射器处理,交由注册机处理获取映射的处理器。当然在系统初始化的时候已经做了一些工作,才能获取处理器。

2、DispatcherServlet组件

2.1、doService()

	/**
	 * 公开特定于 DispatcherServlet 的请求属性,并为实际分派委托 # doDispatch。
	 */
	@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 请求日志
		logRequest(request);

		//在包含的情况下保留请求属性的快照,以便能够在包含后恢复原始属性。
		Map attributesSnapshot = null;
		// WebUtils.isIncludeRequest(request)
		if (true) {
			attributesSnapshot = new HashMap<>();
			// 获取属性名称并遍历
			Enumeration attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		// 使框架对象对处理程序和视图对象可用。
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

		if (this.flashMapManager != null) {
			// this.flashMapManager.retrieveAndUpdate(request, response);
			FlashMap inputFlashMap = null;
			if (inputFlashMap != null) {
				request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
			}
			request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
			request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
		}

		RequestPath previousRequestPath = null;
		if (this.parseRequestPath) {
			previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
			ServletRequestPathUtils.parseAndCache(request);
		}

		try {
			doDispatch(request, response);
		}
		finally {
			if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
				// 还原原始属性快照,以防包含。
				if (attributesSnapshot != null) {
					restoreAttributesAfterInclude(request, attributesSnapshot);
				}
			}
			ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
		}
	}

对请求request参数设置一些属性,重点是调用doDispatch(request, response);处理

2.2、doDispatch()逻辑


	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		// 异步管理器
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

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

				// 确定当前请求的处理程序
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// 确定当前请求的处理程序适配器
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// 如果处理程序支持,则处理上次修改的标头。
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// 实际上调用处理程序
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
			// 处理调度结果,视图解析
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// 而不是 postHandle 和 after Completion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// 清理由多部分请求使用的所有资源。
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

处理到处理程序的实际分派该处理程序将通过按顺序应用 servlet 的 HandlerMaps 来获得。HandlerAdapter 将通过查询 servlet安装的 HandlerAdapter 来获得,以找到第一个支持处理程序类的 HandlerAdapter。所有 HTTP 方法都由此方法处理。这取决于 HandlerAdapter 或者 Handler 本身来决定哪些方法是可以接受的。这个是整个DispatcherServlet的核心处理逻辑,获取处理器、适配器等处理逻辑,调用getHandler()进入下一个处理逻辑。

2.3、getHandler()逻辑

	/**
	 * 为此请求返回 HandlerExectionChain。
	 */
	@Nullable
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			// 遍历DispatcherServlet的handlerMappings字段,取出处理器
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

调用HandlerMapping接口getHandler()方法,交给它的实现类AbstractHandlerMapping组件的getHandler()方法处理。

3、AbstractHandlerMapping组件


	@Override
	@Nullable
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		// 999520
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean名称还是已解析处理程序?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}

		//确保为拦截器和其他人提供缓存的 lookupPath
		if (!ServletRequestPathUtils.hasCachedPath(request)) {
			initLookupPath(request);
		}

		// 根据处理器以及请求获取处理链
		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 (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
			CorsConfiguration config = getCorsConfiguration(handler, request);
			if (getCorsConfigurationSource() != null) {
				CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
				config = (globalConfig != null ? globalConfig.combine(config) : config);
			}
			if (config != null) {
				config.validateAllowCredentials();
			}
			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}

		return executionChain;
	}

查找给定请求的处理程序,如果没有找到特定的处理程序,则返回到默认处理程序。

4、RequestMappingInfoHandlerMapping组件

	@Override
	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
		try {
			// 调用父类方法处理
			return super.getHandlerInternal(request);
		}
		finally {
			// 清理
			ProducesRequestCondition.clearMediaTypesAttribute(request);
		}
	}

5、AbstractHandlerMethodMapping组件

5.1、getHandlerInternal()逻辑

	/**
	 * 查找给定请求的处理程序方法。
	 */
	@Override
	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		// 初始化用于请求映射的路径。
		String lookupPath = initLookupPath(request);
		// 加锁
		this.mappingRegistry.acquireReadLock();
		try {
			// 查找处理器方法
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			// 释放锁
			this.mappingRegistry.releaseReadLock();
		}
	}

查找给定请求的处理程序方法。

5.2、lookupHandlerMethod()逻辑

	/**
	 * 查找当前请求的最佳匹配处理程序方法。如果找到多个匹配,则选择最佳匹配。
	 */
	@Nullable
	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List matches = new ArrayList<>();
		// 返回给定 URL 路径的匹配项。不是线程安全的。
		List directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
		if (directPathMatches != null) {
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
			// 退回所有登记。
			addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
		}
		if (!matches.isEmpty()) {
			Match bestMatch = matches.get(0);
			if (matches.size() > 1) {
				Comparator comparator = new MatchComparator(getMappingComparator(request));
				// 排序
				matches.sort(comparator);
				bestMatch = matches.get(0);
				if (logger.isTraceEnabled()) {
					logger.trace(matches.size() + " matching mappings: " + matches);
				}
				if (CorsUtils.isPreFlightRequest(request)) {
					for (Match match : matches) {
						if (match.hasCorsConfig()) {
							return PREFLIGHT_AMBIGUOUS_MATCH;
						}
					}
				}
				else {
					Match secondBestMatch = matches.get(1);
					if (comparator.compare(bestMatch, secondBestMatch) == 0) {
						Method m1 = bestMatch.getHandlerMethod().getMethod();
						Method m2 = secondBestMatch.getHandlerMethod().getMethod();
						String uri = request.getRequestURI();
						throw new IllegalStateException(
								"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
					}
				}
			}
			request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
			// 当找到匹配的映射时调用。
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.getHandlerMethod();
		}
		else {
			// 当没有找到匹配的映射时调用。
			return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
		}
	}

查找当前请求的最佳匹配处理程序方法。如果找到多个匹配,则选择最佳匹配。

到此处理完毕

你可能感兴趣的:(Spring家族,spring,java)