SpringMvc源碼記錄之請求執行流程

SpringMvc啓動以及加載過程中以及講到Spring啓動加載過程,現在看下以及請求進來的過程以及數據流轉過程,首先在看源碼之前簡單對SpringMvc請求過程有一個簡單的大方向的瞭解:

 第一步就是獲取,然後在Web Spring獲取後根據request 中url來從HandlerMap查詢Handler

第二bu

  1. 請求數據經過DispatchServerlet
  2. 通過request 獲取url查詢Handler
  3. Handler調用相應的 Controller方法獲取結果
  4. 組裝成ModelAndView
  5. ModelAndView解析成view
  6. 返回給客戶端

可以看到DispatchServlet是控制整過的控制者,以及邏輯分發者接下在再看下該類的UML圖,可以看到這個類主要是Spring以及Servlet的一個橋樑既有實現接口Servlet相關的接口,也有Spring相關的接口,一開始主要這裏主要涉及Servlet接口相關的。從UML圖可以看到它是HttpServlet的子類,那麼他有一個很重要的一個性質接受用戶的請求,web配置的URL請求攔截的請求都會通過該類的

void service(HttpServletRequest req, HttpServletResponse resp)

方法處理。從代碼上看,這個類的service方法主要通過父類FrameWorkServlet實現:

FrameWorkServlet.service:


	/**
	 * Override the parent class implementation in order to intercept PATCH requests.
	 */
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        //獲取請求方法:POST  GET PUT 等
		HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
		if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
			processRequest(request, response);
		}
		else {
            //調用HttpServlet service方法
			super.service(request, response);
		}
	}

再看下父類HTTPServlet的方法:

 protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        //獲取不同的請求方法類型
        String method = req.getMethod();

        //根據不同的請求類型走不同的方法
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
            
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);
            
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
            
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
            
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
            
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }
    

這塊代碼功能很簡單就是獲取請求的  方法類型,不同的請求類型走不同的邏輯,這些可以交給子類實現,這裏用了模板模式,在FrameServlet重寫了些 doGet  doPost方法:

	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}

每一個方法最後都會調用processRequest這個方法,而這個方法最核心的是調用了

protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
      throws Exception;

這個方法被DispatchServlet實現了,也就是說:一個請求過來最終的公共邏輯會走到DispatchServlet#doService方法

接下來就是真正的邏輯開始了。這個方法看代碼其實最核心的調用

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception 

所以我們直接從這個方法開始看:

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

				// Determine handler for the current request.
                //獲取處理Handler(重點)
				mappedHandler = getHandler(processedRequest);
                //沒有找到Handler  說明404啦
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
                //獲取一個適配器(重點)
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
                //這裏執行所有的和這個請求有關的攔截器,執行preHandle方法
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
                //適配器調用Handler方法,處理請求以及Handler,獲取modelAndView
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
                //這裏執行所有的和這個請求有關的攔截器,執行postHandle方法
				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				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()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

這裏我們重點關注一下幾個過程:

  1. 獲取MapHandler過程,以及這個對象包含的信息
  2. HandlerAdapter執行過程
  3. HandlerAdapter角色作用

接下來我看從這三個方面來看下,下面都是基於註解的方式來走的(@Controller @RequestMapping)

MapHandler的獲取

	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		for (HandlerMapping hm : this.handlerMappings) {
			if (logger.isTraceEnabled()) {
				logger.trace(
						"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
			}
            //從HandlerMapping中獲取Handler
			HandlerExecutionChain handler = hm.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
		return null;
	}

在this.handlerMappings代表配置不同的類型,我們直接看debug的截圖:

可以看到有三個HandlerMapping,其中SimpleUrlHandlerMapping是配置加載的,BeanNameURLHandlerMapping是默認實現的,RequestMappingHandlerMapping是基於@Controller @RequestMapping實現的。所以我們只用了註解實現的,我們只關心這塊邏輯就好。接下來看下Mapping的getHandler方法:

@Override
	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 = getApplicationContext().getBean(handlerName);
		}
        //獲取這個請求相關的攔截器,並且和Handler組裝成一個對象
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
		if (CorsUtils.isCorsRequest(request)) {
			CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
			CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
			CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}
		return executionChain;
	}

以上代碼只完成兩個事情:獲取一個請求相關的Handler  以及攔截器,看下這兩個方法:

獲取Handler

	@Override
	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        //獲取請求URL
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		if (logger.isDebugEnabled()) {
			logger.debug("Looking up handler method for path " + lookupPath);
		}
        //加一個共享鎖
		this.mappingRegistry.acquireReadLock();
		try {
            //獲取HandlerMethod
			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 + "]");
				}
			}
            //生成創建Handler
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}



protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<Match>();
        //獲取一個Match對象,在下面看下這個debug數據內容(標註1)
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
		if (directPathMatches != null) {
            //把可以和這個匹配的Match對象加入一個List中(標註2)
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
			// No choice but to go through all mappings...
			addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
		}

		if (!matches.isEmpty()) {
            //把剛剛的Matches排序(標註3)
			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
			Match bestMatch = matches.get(0);
			if (matches.size() > 1) {
				if (CorsUtils.isPreFlightRequest(request)) {
					return PREFLIGHT_AMBIGUOUS_MATCH;
				}
				Match secondBestMatch = matches.get(1);
                //有兩個一樣Match,那麼就會拋出異常
				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);
            //返回Match的handlerMethod
			return bestMatch.handlerMethod;
		}
		else {
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
		for (T mapping : mappings) {
			T match = getMatchingMapping(mapping, request);
			if (match != null) {
                //將拿到的match和mapping包裝成一個對象
				matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
			}
		}
	}

上面兩個方法主要獲取Handler的過程:

  1. 首先獲取T泛型集合(這個T是一個啥)
  2. 將Match集合排序獲取最優的(是啥排序策略)
  3. 返回最優Match.Handler(這個又是一個啥)

上面我們知道了這個過程,但是對裏面的數據卻沒有一個感性的認識,現在直接看debug數據就行。

首先看下標註1,獲取一個List,其實是從this.urlLookup這個Map中獲取的:

 這個數據結構內容是,key放的是我們的Url,value是一個list,list的每一個對象是怎麼來的呢?其實這個數據來源就是註解@RequestMapping中各個轉化的內容,也就是一個出現多個一樣的的Url的處理方法(後面會有如何選其中的一個方法)。回答第一個問題,T是一個包含了註解信息的對象,包括 url Post/Get  等

然後就到了註解2,把我們剛剛拿到的所有的註解的信息會構造一個Match,拿着之前註解信息還會從this.mappingRegistry獲取一個Handler。

我們可以看到獲取的value是一個HandlerMethod對象,它是記錄的主要是方法的信息,例如這個url對應的Controller bean  Method,以及方法的參數信息(第三個對象答案)。也就是一個Match對象有一個@RequestMapping註解信息以及方法的信息

接下來看下標註3,標註3主要對多個Match進行選取最優的Match,有兩個最優的那麼就會拋異常,我們從代碼獲取比較器一步步走進去我們可以看到最終是按照@RequestMapping信息對象(RequestMappingInfo)來排序的(上面第二個問題的答案),,這裏就不詳細看了,裏面代碼比較簡單。

以上就是獲取Handler的邏輯:

  1. 根據URL獲取註解的信息對象
  2. 根據註解信息對象獲取具體的方法信息對象
  3. 根據註解信息對象排序選出最優的哪一個方法信息Handler  返回,反之就會拋異常

         HandlerInterceptor獲取

在獲取完Handler後獲取攔截器,組裝成 HandlerExecutionChain

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;
                   //攔截器可以匹配URL,就會加入到鏈表中
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

 

HandlerAdapter

我們在上面一部已經獲取了URL對應的Handler,裏面主要的要的處理的方法信息,這個請求交給哪一個Controller的哪一個方法,現在HandlerAdapter其實起的是一個執行的過程,以及提供各種上下文的對象完成數據映射轉換,並且調用方法完成業務邏輯

/**
	 * Return the HandlerAdapter for this handler object.
	 * @param handler the handler object to find an adapter for
	 * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
	 */
	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (logger.isTraceEnabled()) {
				logger.trace("Testing handler adapter [" + ha + "]");
			}
            //獲取可以支持的適配器,這個和controller配置有關係,註解實現的返回RequestMappingHandlerAdapter
			if (ha.supports(handler)) {
				return ha;
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

這裏按照註解實現那麼就會返回RequestMappingHandlerAdapter,從主流程handle->handleInternal->invokeHandlerMethod方法:

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);//構建執行器
			//設置請求參數到Controller轉換對象
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
            //設置返回值參數轉換對象		invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
            //設置參數綁定對象
			invocableMethod.setDataBinderFactory(binderFactory);

			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
			asyncWebRequest.setTimeout(this.asyncRequestTimeout);

			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			asyncManager.setTaskExecutor(this.taskExecutor);
			asyncManager.setAsyncWebRequest(asyncWebRequest);
			asyncManager.registerCallableInterceptors(this.callableInterceptors);
			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

			if (asyncManager.hasConcurrentResult()) {
				Object result = asyncManager.getConcurrentResult();
				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
				asyncManager.clearConcurrentResult();
				if (logger.isDebugEnabled()) {
					logger.debug("Found concurrent result value [" + result + "]");
				}
				invocableMethod = invocableMethod.wrapConcurrentResult(result);
			}
            //執行方法
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}
            //生成modelAndView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

上面的流程就是通過Handler以及上下文一些工具對象(各種Convert類)構建一個新的執行類進行執行。

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        //執行獲取返回值
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
				mavContainer.setRequestHandled(true);
				return;
			}
		}
		else if (StringUtils.hasText(getResponseStatusReason())) {
			mavContainer.setRequestHandled(true);
			return;
		}

		mavContainer.setRequestHandled(false);
		try {
            //對返回的參數進行轉換寫入到Response中
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
			}
			throw ex;
		}
	}
	public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        //轉化獲取controller需要的值
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
					"' with arguments " + Arrays.toString(args));
		}
        //通過反射調用bean的處理方法,拿到返回值
		Object returnValue = doInvoke(args);
		if (logger.isTraceEnabled()) {
			logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
					"] returned [" + returnValue + "]");
		}
		return returnValue;
	}

上面的邏輯主要分爲兩步:

  1. 獲取controller方法執行的參數
  2. 通過反射執行方法

接下來看下參數的獲取過程:

	private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        //獲取controller參數信息
		MethodParameter[] parameters = getMethodParameters();
		Object[] args = new Object[parameters.length];
		for (int i = 0; i < parameters.length; i++) {
			MethodParameter parameter = parameters[i];
			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
			args[i] = resolveProvidedArgument(parameter, providedArgs);
			if (args[i] != null) {
				continue;
			}
            //查找該參數能支持的轉化獲取的類
			if (this.argumentResolvers.supportsParameter(parameter)) {
				try {//獲取轉化需要的值
					args[i] = this.argumentResolvers.resolveArgument(
							parameter, mavContainer, request, this.dataBinderFactory);
					continue;
				}
				catch (Exception ex) {
					if (logger.isDebugEnabled()) {
						logger.debug(getArgumentResolutionErrorMessage("Failed to resolve", i), ex);
					}
					throw ex;
				}
			}
			if (args[i] == null) {
				throw new IllegalStateException("Could not resolve method parameter at index " +
						parameter.getParameterIndex() + " in " + parameter.getMethod().toGenericString() +
						": " + getArgumentResolutionErrorMessage("No suitable resolver for", i));
			}
		}
		return args;
	}

這一步主要識別一些根據參數以及標記例如註解等來拿到 HandlerMethodArgumentResolver 對象,例如參數帶了 @RequestJsonbody 會有一個專門的類RequestResponseBodyMethodProcessor 來獲取參數,帶了@RequestParam 會有RequestParamMethodArgumentResolver類來獲取參數。

還要一部就是在拿到返回值對返回值也有一個類似的轉化的流程在

invokeAndHandle->this.returnValueHandlers.handleReturnValue

中,會調用

@Override
	public void handleReturnValue(Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

		HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
		if (handler == null) {
			throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
		}
		handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
	}



	private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) {
		boolean isAsyncValue = isAsyncReturnValue(value, returnType);
		for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
			if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
				continue;
			}
			if (handler.supportsReturnType(returnType)) {
				return handler;
			}
		}
		return null;
	}

這裏如果通過拿到返回值得信息,例如註解,類等信息,決定拿到哪一個

HandlerMethodReturnValueHandler

來處理返回值。

 

以上就是主要的流程,回顧一下:

  1. 獲取Servlet請求
  2. 獲取請求 Url獲取具體符合的方法集合
  3. 選取最優的方法
  4. 獲取轉換的Controller方法的執行參數
  5. 反射執行
  6. 獲取結果,並且轉換設置到Response中
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章