1. 程式人生 > >Spring MVC 初始化和流程

Spring MVC 初始化和流程

Spring MVC 元件與流程

  • 概念
    Spring MVC的核心在於其流程,這是使用Spring MVC框架的基礎,Spring MVC是一種基於Servlet的技術,它提供了核心控制器DispatcherServlet和相關的元件,並制定了鬆散的結構,以適應各種靈活的需要。
  • 原理
    首先,Spring MVC框架是圍繞DispatcherServlet而工作的,所以這個類是其最為重要的類。因為它可以攔截HTTP傳送過來的請求,在servlet初始化(呼叫init方法)時,Spring MVC會根據配置,獲取配置資訊,從而得到統一資源識別符號和處理器(Handler)質檢的對映關係(HandlerMapping),為了更加靈活和增強功能,Spring MVC還會給處理器加入攔截器,所以還可以在處理器執行前後加入自己的程式碼,這樣就構成了一個處理器的執行鏈,並根據上下文初始化試圖解析器等內容,當處理器返回的時候就可以通過檢視解析器定位檢視,然後將資料模型渲染到檢視中,用來響應使用者的請求了。
  • 流程1
    當一個請求到來時,DispatcherServlet首先通過請求和事先解析好的HandlerMapping配置,找到對應的處理器(Handler),這樣就準備開始執行處理器和攔截器組成的執行鏈,
    而執行處理器需要有一個對應的環境,這樣它就有了一個處理器的介面卡,通過這個介面卡就能執行對應的處理器及其攔截器,這裡的處理器包含了控制器的內容和其他增強的功能,在處理器返回模型和檢視給DispacherServlet後,DispacherServlet就會把對應的檢視資訊傳遞給檢視解析器。
  • 流程2
    當Spring MVC啟動的時候就會去解析 XXXController的註解,然後生成對應的URI和請求的對映關係,並註冊對應的方法。當請求來到的時候,首先根據URI找到對應的HandlerMapping,然後組織為一個執行鏈,通過請求型別找到RequestMappingHandlerAdapter,它的例項是在DispatcherServlet初始化的時候進行建立的。然後通過它去執行HandlerExecutionChain的內容,最終在XXXController的方法中將檢視返回給DispatchServlet。

註解解釋

  • @Controller:代表該類是一個控制器,Spring MVC描述的時候就會把它作為控制器載入進來。
  • @RequestMapping:指定了對應的請求的URI,Spring MVC在初始化的時候就會將這些資訊解析,存封起來,於是便有了HandlerMapping。當發生請求時,Spring MVC就會去使用這些資訊去找到對應的控制器提供服務。

單詞解釋:
ContextLoaderListener:
實現了介面ServletContextListener,ServletContextListener的作用是可以在整個Web工程前後加入自定義程式碼,所以可以在Web工程初始化之前,它先完成Spring Ioc容器的初始化,也可以在Web工程關閉之時完成Spring Ioc容器的資源進行釋放。

Spring MVC 初始化
整個Spring MVC初始化,配置了DispatcherServlet和ContextLoaderListener,所以Spring MVC初始化會涉及兩個上下文的初始化及Spring Ioc容器上下文和對映請求上下文。

  • 初始化Spring Ioc上下文
    Java Web容器為其生命週期中提供ServletContextListener介面,這個介面可以在Web容器初始化和生命週期中執行一定的邏輯,就是說,通過它可以使得在DispatcherServlet初始化前就可以完成Spring Ioc容器的初始化,也可以在結束期完成對Spring Ioc容器的銷燬,只要實現ServletContextListener介面的方法就可以了。
  • 初始化對映請求上下文
    對映請求上下文是通過DispatcherServlet初始化的,它和普通的Servlet也是一樣的,可以根據自己的需要配置它在啟動時初始化,或者等待使用者第一次請求的時候進行初始化。如果在Web工程中並沒有註冊ContextLoaderListener,這個時候DispatcherServlet就會在其初始化的時候進行對Spring Ioc容器的初始化。
    什麼時候初始化DispatcherServlet?
    可以讓DispatcherServlet在伺服器啟動期間完成Spring Ioc容器的初始化,我們可以在Web容器剛啟動的時候,也可以在Web容器載入DispatcherServlet的時候進行初始化。建議在Web容器剛開始的時候進行初始化,因為在整個Web的初始化中,不只是DispatcherServlet需要Spring Ioc的資源,其他的元件可能也需要。

Spring MVC 核心元件
按照載入順序:
1. MultipartResolver:檔案解析器。用於支援伺服器的檔案上傳。
2. LocaleResolver:國際化解析器,可以提供國際化的功能。
3. ThemeResolver:主題解析器,類似於軟體面板的轉換功能。
4. HandlerMapping:Spring MVC中十分重要的內容,它會包裝使用者提供一個控制器的方法和對它的一些攔截器,通過呼叫它就能夠執行控制器。
5. handlerAdapter:處理介面卡,因為處理器會在不同的上下文中執行,所以Spring MVC會先找到合適的介面卡,然後執行處理器服務方法。
6. HandlerExceptionResolver:處理器異常解析器,處理器有可能產生異常,如果產生異常,則可以通過異常解析器來處理它。比如出現異常後跳轉到統一的異常處理頁面。
7. RequestToViewNameTranslator:檢視邏輯名稱轉換器,有時候在控制器中返回一個檢視的名稱,通過它可以找到實際的檢視。當處理器沒有返回邏輯檢視名等相關資訊時,自動將請求URL對映為邏輯檢視名。
8. ViewResolver:檢視解析器,當控制器返回後,通過試圖解析器會把邏輯檢視名稱進行解析,然後定位實際檢視。

使用註解配置方式初始化
由於在Servlet 3.0之後的規範允許取消web.xml配置,只使用註解方式便可以了,所以在Servlet 3.1之後的版本也提供了註解方式的配置。只要繼承一個類 AbstractAnnotationConfigDispatcherServletInitializer,然後實現它所定義的方法。
只要繼承它就能實現DispatcherServlet對映關係和Spring Ioc容器的初始化工作。
配置類代如下:

package com.bob.analyst.admin.aop;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{

    //Spring Ioc 容器配置
    @Override
    protected Class<?>[] getRootConfigClasses() {
        //可以返回Spring 的Java 配置檔案陣列
        return new Class<?>[] {};
    }

    //DispatcherServlet的URI對映關係配置
    @Override
    protected Class<?>[] getServletConfigClasses() {
        //可以返回Spring 的Java配之間資料
        return new Class<?>[]{};
    }

    //DispatcherServlet 攔截內容
    @Override
    protected String[] getServletMappings() {
        return new String[]{"*.do"};
    }

}

備註:

  • 如果getRootConfigClasses方法返回為空,就不載入自定義的Bean到Spring Ioc容器中,而getServletConfigClasses載入了WebConfig,則它就是一個URI和控制器的對映關係類。由此產生Web請求上下文。
  • Servlet 3.0之後的版本允許動態載入 Servlect,只是按照規範需要實現ServletContainerInitializer介面而已。於是Spring MVC框架自己的包內實現了一個類,它就是SpringServletContainerInitializer,它實現了ServletContainerInitializer介面,這樣就能通過它去載入開發者提供的配置類了。

載入類如下:

package com.bob.analyst.admin.aop;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
//定義掃描的包,載入控制器
@ComponentScan("com.*")
//啟用Spring Web MVC
@EnableWebMvc
public class WebConfig {

    /**
     * 建立檢視解析器
     * @return 檢視解析器
     */
    @Bean(name="viewResolver")
    public InternalResourceViewResolver ViewResolverinitViewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}

備註:
@EnableWebMvc 註解代表它啟動Spring MVC框架的配置。