SpringMVC基礎原始碼分析(一)

情韻發表於2023-03-02

實現Controller的三種方式分析

每種實現的方式對應的HanderAdapter都不同。

實現Controller介面

該介面對應的HanderAdapterSimpleControllerHandlerAdapter

image-20230302193001463

使用案列:

 public class LeController implements Controller {

	 @Override
	 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		 // 建立資料檢視類
		 ModelAndView mv = new ModelAndView();
		 // 填充資料
		 mv.addObject("msg","北方情韻");
		 // 跳轉的檢視
		 mv.setViewName("index");
		 return mv;
	 }
 }

配置對應的bean資訊,這裡的name就是訪問該Controller的路徑。

<bean class="cn.lele.controller.LeController" name="/le" />

image-20230302192439527

我們可以透過debug那個執行鏈就可以知道。

image-20230302193816106

實現HttpRequestHandler介面

該介面對應的HanderAdapterHttpRequestHandlerAdapter

image-20230302194119786

使用案例:

 public class YueController implements HttpRequestHandler {
     @Override
     public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         request.setAttribute("msg","實現介面HttpRequestHandler");
         request.getRequestDispatcher("/WEB-INF/pages/index.jsp").forward(request,response);
     }

 }

配置對應的bean資訊,這裡的name就是訪問該Controller的路徑。

<bean class="cn.lele.controller.YueController" name="/yue" />

image-20230302194358371

繼續檢視當前物件的執行鏈

image-20230302194510537

這兩種方式大體上是類似的,我們可以區別的看一下,他們是怎麼處理的。

先看實現HttpRequestHandlerAdapter介面的:

image-20230302194828062

進入1075行程式碼:

image-20230302195104082

可以發現,這是把當前Controller強轉為HttpRequestHander,然後再執行HttpRequestHanderAdapterhandleRequest方法。(實際就是去執行我們Controller裡面的方法。)

image-20230302195206479

HttpRequestHandler正是我們Contoller類實現的HttpRequestHandler

image-20230302195708545

同理,我們去看一下實現Controller介面的類的處理方法。

image-20230302195830409

一樣,都是先強轉為介面類,然後執行對應的方法,也就是我們自己實現的方法:

image-20230302195925956

注意:當前的所處位置:

image-20230302195957002

使用註解的方式

待補充

探究HandlerAdapter的裝配規則

一直都很疑惑:

image-20230302200218040

為什麼不裝配全部都能用,只裝配一種,不符合的就不能用了呢?

未配置HandlerAdapter

觀察DispatcherServlet的初始化方法:

可以看到有對HandlerAdapter的初始化,點進去加斷點。

image-20230302200635511

開始Debug:

image-20230302201006875

image-20230302201217525

根據註釋,我們可以知道如果此時HandlerAdapters如果為空的話將載入初始化的HandlerAdapters

image-20230302201509490

可以看到,在664行載入了四個HandlerAdapter

image-20230302201646916

進入此方法繼續debug檢視:

注意:DispatcherServlet的初始化方法只執行一次,後面需要重新啟動tomcat才能繼續進入初始化方法。

image-20230302201903668

重啟後,繼續Debug:

image-20230302202053167

往下走,可以看到這裡讀取到了幾個HandlerAdapter

image-20230302202511819

很明顯872行程式碼是讀取了什麼檔案

image-20230302202739434

重新Debug可以發現這裡讀取的是org/springframework/web/servlet/DispatcherServlet.properties檔案。

image-20230302202904925

DispatcherServlet.properties:

......

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
	org.springframework.web.servlet.function.support.HandlerFunctionAdapter


......

檔案裡內容不少,我這裡只留下了HandlerAdapter的資訊了

繼續往下看怎麼處理的:

下面我感覺應該是利用泛型和反射得到所有的處理器。

image-20230302204028529

配置了HandlerAdapter

如果我們再容器中裝配了Adapter:

image-20230302204619120

重啟tomcat,繼續Debug

image-20230302204651428

可以看到642行讀取到了我們配置的兩個HandlerAdapter,並且再645行賦值給了DispatcherServlet的handlerAdapters,此時方法就會結束了。因為下面都不符合條件了。

image-20230302204909088

總結:

如果我們在容器裡新增了HandlerAdapter,那麼就不會透過讀取本地的檔案新增預設的四個HandlerAdapter。

如果沒在容器中新增HandlerAdapter,機會讀取本地的DispatcherServlet.properties裡面的四個HandlerAdapter。

相關文章