1. 程式人生 > 實用技巧 >SpringMVC之RequestMapping執行過程(HandlerAdapter篇)

SpringMVC之RequestMapping執行過程(HandlerAdapter篇)

寫在前面

如果想搞清楚 引數解析結果集處理 的邏輯,RequestMappingHandlerAdapter 是我們必須要弄明白的類。

下面以一段 Hello World 程式碼為例:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {
	
	@RequestMapping(value="/sayHello")
        @ResponseBody
	public String printHello(@RequestParam(defaultValue = "guest") String name) {
		return "hello, " + name;
	}
}

說得通俗一點,就是 printHello 執行之前,SpringMVC 框架幹了點什麼? printHello 返回值之後,SpringMVC 框架幹了點什麼? printHello 假如發生了異常,SpringMVC 框架又為我們看了點什麼?

概述 RequestMappingHandlerAdapter

RequestMappingHandlerAdapter 有兩個成員變數:

  • HandlerMethodArgumentResolverComposite 本身也是實現 HandlerMethodArgumentResolver 介面的,還包含一組 HandlerMethodArgumentResolver

    介面例項,目的只是為了把介面卡的遍歷邏輯放在其中。

  • HandlerMethodReturnValueHandlerComposite 實現了 HandlerMethodReturnValueHandler 介面,同時還包含一組 HandlerMethodReturnValueHandler 介面例項,目的也是包裝迴圈的程式碼。

初始化 RequestMappingHandlerAdapter

RequestMappingHandlerAdapter 又實現了 InitializingBean 介面,因此在 Spring 容器載入該 Bean 時,會觸發 afterPropertiesSet()

方法。

Spring中的InitializingBean介面的使用 介紹了 Spring Bean 初始化的兩個方法,一個是實現 InitializingBean,另一個是 init-method 。

那麼複習一下,RequestMappingHandlerAdapter 加入到 Spring 容器中的時機是什麼時候呢?

答:在 DispatcherServlet # initStrategies 中呼叫 initHandlerAdapters 初始化 處理器介面卡。

想進一步瞭解該知識點的,可以參考這篇文章 詳細解讀 DispatcherServlet 初始化過程(帶時序圖)

初始化 RequestMappingHandlerAdapter Bean 的過程如圖所示:

@Override
public void afterPropertiesSet() {
	// Do this first, it may add ResponseBody advice beans
	initControllerAdviceCache();
        // 獲取引數解析器
	if (this.argumentResolvers == null) {
		List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
		this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
	}
        // @InitBinder 註解相關的引數解析器
	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);
	}
}

總結

RequestMappingHandlerAdapter 是 SpringMVC 實現 引數解析結果集處理 的核心類之一。

其中,解析引數的介面為 HandlerMethodArgumentResolver

處理結果集的介面為 HandlerMethodReturnValueHandler

RequestMappingHandlerAdapter 實現了 InitializingBean,因此初始化的過程在 afterPropertiesSet() 方法中。

getDefaultArgumentResolvers() 方法中,我們可以找到各種各樣常見的引數是如何解析的。

getDefaultReturnValueHandlers() 方法中,我們可以找到各種各樣常見的返回值是如何處理的。