最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中HandlerAdapter接口源碼解析

 更新時間:2023年11月18日 08:40:19   作者:立小研先森  
這篇文章主要介紹了Spring中HandlerAdapter接口源碼解析,HandlerAdapter是一個適配器接口類,適配器模式是指兩個不兼容接口之間的橋梁,要想讓一個接口使用另外一個接口的實現(xiàn)中間可以加一層適配器類,需要的朋友可以參考下

HandlerAdapter接口源碼

HandlerAdapter是一個適配器接口類,適配器模式是指兩個不兼容接口之間的橋梁,要想讓一個接口使用另外一個接口的實現(xiàn)中間可以加一層適配器類;舉個例子:筆記本沒有網(wǎng)線接口,那我想連接網(wǎng)線接通網(wǎng)絡如何實現(xiàn)呢?我可以買一個以太網(wǎng)轉(zhuǎn)換器,網(wǎng)線插入轉(zhuǎn)換器上,轉(zhuǎn)換器插入筆記本上就實現(xiàn)了連接網(wǎng)絡的功能,那這個轉(zhuǎn)換器起到的就是一個適配器的作用;在接口訪問控制器方法的時候是通過HandlerAdapter接口的實現(xiàn)類來進行的,本文以最常用的RequestMappingHandlerAdapter適配器類為主線索來講解。

接口的源碼如下:

public interface HandlerAdapter {
	/**
	 * 判定是否支持傳入的handler
	 */
	boolean supports(Object handler);
	/**
	 * 使用給定的handler來處理當前request請求
	 */
	@Nullable
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
	/**
	 * 返回handler最后修改的時間
	 */
	long getLastModified(HttpServletRequest request, Object handler);
}

HandlerAdapter的實現(xiàn)類有多個,我們以RequestMappingHandlerAdapter適配器類為主線索,而此類又是AbstractHandlerMethodAdapter抽象類的子類;

如下是RequestMappingHandlerAdapter適配器類的關(guān)系圖

在這里插入圖片描述

1.HandlerAdapter接口的初始化

容器加載時DispatcherServlet中的初始化方法initStrategies方法會被調(diào)用,里面的

  /**
  * 容器中HandlerAdapter接口實現(xiàn)類集合
  **/
  @Nullable
	private List<HandlerAdapter> handlerAdapters;	
	/**
	 * 初始化handlerAdapters集合,如果在BeanFactory中沒有HandlerAdapter,那么將使用默認
	 * 的SimpleControllerHandlerAdapter
	 */
	private void initHandlerAdapters(ApplicationContext context) {
		this.handlerAdapters = null;
		//判定是否檢測所有的HandlerAdapter
		if (this.detectAllHandlerAdapters) {
			//查看容器中所有實現(xiàn)了HandlerAdapter的bean 
			Map<String, HandlerAdapter> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerAdapters = new ArrayList<>(matchingBeans.values());
				// We keep HandlerAdapters in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerAdapters);
			}
		}
		else {
			try {
				HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
				this.handlerAdapters = Collections.singletonList(ha);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerAdapter later.
			}
		}

		// Ensure we have at least some HandlerAdapters, by registering
		// default HandlerAdapters if no other adapters are found.
		if (this.handlerAdapters == null) {
			this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
						"': using default strategies from DispatcherServlet.properties");
			}
		}
	}

上面的代碼是從容器中獲取HandlerAdapter接口實現(xiàn)類的bean集合

2.RequestMappingHandlerAdapter處理request請求

前端發(fā)送過來一個request請求首先進入DispatcherServlet的doService方法,再進入doDispatch方法,那我們看下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);
				//通過request請求獲取HandlerExecutionChain處理器執(zhí)行程序鏈
        //也即通過request獲取匹配的HandlerMapping實現(xiàn)類,通過實現(xiàn)類的getHandler
        //方法獲取HandlerExecutionChain處理程序執(zhí)行器鏈類,里面包含了請求對應的HandlerMethod
        //及對應的所有攔截器
				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}
				//根據(jù)上面獲取到的HandlerMethod獲取匹配到的適配器類
				// 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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
				//根據(jù)適配器對象調(diào)用具體的方法(如:RequestMappingHandlerAdapter)
				// Actually invoke the handler.
				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) {
				// 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);
				}
			}
		}
	}

跳出本文分析的正文流程,來分析下AbstractHandlerMethodAdapter適配器類;

Abstract base class for {@link HandlerAdapter} implementations that support
handlers of type {@link HandlerMethod}.

源碼注解說明類抽象類的實現(xiàn)support方法判定是否支持HandlerMethod;

	/**
	* 判定適配器類是否支持HandlerMethod
	**/
	@Override
	public final boolean supports(Object handler) {
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}

getHandlerAdapter方法實現(xiàn)源碼:

	/**
	 * 獲取可以處理handler的HandlerAdapter適配器類
	 */
	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
        //判定適配器類是否支持HandlerMethod
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

ha.handle(processedRequest, response, mappedHandler.getHandler());方法會調(diào)用AbstractHandlerMethodAdapter適配器類的handle方法:

	@Override
	@Nullable
	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}

而handleInternal方法最終會調(diào)用RequestMappingHandlerAdapter類的handlerInternal方法:

@Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No synchronization on session demanded at all...
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}

handleInternal方法又會調(diào)用invokeHandlerMethod方法:

	@Nullable
	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);
			//創(chuàng)建HandlerMethod的子類ServletInvocableHandlerMethod的實例對象
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			if (this.argumentResolvers != null) {
        //設置參數(shù)解析器
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			if (this.returnValueHandlers != null) {
        //設置返回值處理程序
				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();
				LogFormatUtils.traceDebug(logger, traceOn -> {
					String formatted = LogFormatUtils.formatValue(result, !traceOn);
					return "Resume with async result [" + formatted + "]";
				});
				invocableMethod = invocableMethod.wrapConcurrentResult(result);
			}
			//調(diào)用ServletInvocableHandlerMethod類的invokeAndHandle方法
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

上面的方法會涉及到參數(shù)解析器的初始化、返回值處理程序的初始化,那這些返回值處理程序和參數(shù)解析程序如何初始化的呢?RequestMappingHandlerAdapter類實現(xiàn)了InitializingBean接口,該類加載后會調(diào)用afterPropertiesSet方法,會對這些處理程序進行初始化;

	@Override
	public void afterPropertiesSet() {
		// Do this first, it may add ResponseBody advice beans
		initControllerAdviceCache();
		//參數(shù)解析器初始化
		if (this.argumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
    //InitBinder的參數(shù)解析器初始化
		if (this.initBinderArgumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
    //返回值處理程序初始化
		if (this.returnValueHandlers == null) {
			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
		}
	}

調(diào)用ServletInvocableHandlerMethod.invokeAndHandle方法源碼如下:

	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//調(diào)用控制器方法,獲取返回值
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

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

		mavContainer.setRequestHandled(false);
		Assert.state(this.returnValueHandlers != null, "No return value handlers");
		try {
      //將返回值交給HandlerMethodReturnValueHandlerComposite返回值代理類
      //選擇合適的HandlerMethodReturnValueHandler實現(xiàn)類處理返回值
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(formatErrorForReturnValue(returnValue), ex);
			}
			throw ex;
		}
	}

調(diào)用InvocableHandlerMethod.invokeForRequest方法源碼:

	/**
	* 獲取request請求參數(shù),調(diào)用控制器方法
	**/
  @Nullable
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//獲取request請求方法的參數(shù)
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Arguments: " + Arrays.toString(args));
		}
		return doInvoke(args);
	}

調(diào)用InvocableHandlerMethod.doInvoke(Object… args)方法源碼:

	/**
	* 使用給定的參數(shù)調(diào)用控制器方法
	**/
	@Nullable
	protected Object doInvoke(Object... args) throws Exception {
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
      //調(diào)用真實最終的控制器方法,并返回執(zhí)行后的結(jié)果
			return getBridgedMethod().invoke(getBean(), args);
		}
		catch (IllegalArgumentException ex) {
			assertTargetBean(getBridgedMethod(), getBean(), args);
			String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
			throw new IllegalStateException(formatInvokeError(text, args), ex);
		}
		catch (InvocationTargetException ex) {
			// Unwrap for HandlerExceptionResolvers ...
			Throwable targetException = ex.getTargetException();
			if (targetException instanceof RuntimeException) {
				throw (RuntimeException) targetException;
			}
			else if (targetException instanceof Error) {
				throw (Error) targetException;
			}
			else if (targetException instanceof Exception) {
				throw (Exception) targetException;
			}
			else {
				throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
			}
		}
	}

到此這篇關(guān)于Spring中HandlerAdapter接口源碼解析的文章就介紹到這了,更多相關(guān)HandlerAdapter接口源碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JVM參數(shù)-Xms和-Xmx的作用及說明

    JVM參數(shù)-Xms和-Xmx的作用及說明

    這篇文章主要介紹了JVM參數(shù)-Xms和-Xmx的作用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java服務器端微信、支付寶支付和退款功能

    java服務器端微信、支付寶支付和退款功能

    這篇文章主要為大家詳細介紹了java服務器端微信、支付寶支付和退款功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • 基于zipoutputStream的簡單使用

    基于zipoutputStream的簡單使用

    這篇文章主要介紹了基于zipoutputStream的簡單使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 詳解在Spring Boot框架下使用WebSocket實現(xiàn)消息推送

    詳解在Spring Boot框架下使用WebSocket實現(xiàn)消息推送

    這篇文章主要介紹了詳解在Spring Boot框架下使用WebSocket實現(xiàn)消息推送,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • Gateway網(wǎng)關(guān)源碼解析

    Gateway網(wǎng)關(guān)源碼解析

    這篇文章主要介紹了Gateway微服務網(wǎng)關(guān),負載均衡,熔斷和限流,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • 解決idea 項目編譯后沒有class文件的問題

    解決idea 項目編譯后沒有class文件的問題

    這篇文章主要介紹了解決idea 項目編譯后沒有class文件的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • java基于TCP協(xié)議實現(xiàn)聊天程序

    java基于TCP協(xié)議實現(xiàn)聊天程序

    這篇文章主要為大家詳細介紹了java基于TCP協(xié)議實現(xiàn)聊天程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Java微信退款開發(fā)

    Java微信退款開發(fā)

    這篇文章主要為大家詳細介紹了Java微信退款開發(fā)的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • Springmvc加ajax實現(xiàn)上傳文件并頁面局部刷新

    Springmvc加ajax實現(xiàn)上傳文件并頁面局部刷新

    這篇文章主要介紹了Springmvc加ajax實現(xiàn)上傳文件并頁面局部刷新,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • Java中漢字轉(zhuǎn)拼音pinyin4j用法實例分析

    Java中漢字轉(zhuǎn)拼音pinyin4j用法實例分析

    這篇文章主要介紹了Java中漢字轉(zhuǎn)拼音pinyin4j用法,結(jié)合實例形式較為詳細的分析了pinyin4j庫的具體使用技巧,需要的朋友可以參考下
    2015-12-12

最新評論

玉林市| 陇南市| 景泰县| 丰县| 宣武区| 嘉兴市| 屏南县| 宽甸| 黔西县| 醴陵市| 东宁县| 潞西市| 太原市| 砀山县| 大同县| 沾益县| 九江市| 康马县| 赤水市| 新干县| 柳州市| 通许县| 海安县| 涿鹿县| 平安县| 灌云县| 和平区| 临夏县| 泊头市| 资中县| 焉耆| 兰溪市| 绍兴县| 浪卡子县| 仁怀市| 木里| 大悟县| 新和县| 东港市| 祁连县| 开阳县|