1. 程式人生 > 實用技巧 >[Re] SpringMVC-6

[Re] SpringMVC-6

SpringMVC 執行流程

  1. 請求過來,前端控制器 (DispatcherServlet) 呼叫 doDispatcher() 進行處理
  2. 根據 HandlerMapping 中儲存的請求對映資訊找到處理當前請求的處理器執行鏈 (HandlerExecutionChain = Handler + Interceptor)
  3. 根據當前處理器找到它的介面卡(HandlerAdapter)
  4. 攔截器的 preHandle 順序執行
  5. 介面卡執行目標方法
    → @ModelAttribute 標註的方法提前執行
    → 確定目標方法用的引數
        → 有註解
        → 無註解
            → 是否是 ServletAPI
            → 是否是 Model / Map 型別
            → 是否自定義型別
                → 看隱含模型中是否有同名的,有就賦值
                → 如果沒有,看是否是 @SessionAttributes 標註的屬性
                → 如果都不是,利用反射建立物件
    → 執行目標方法,返回 ModelAndView
    
  6. 攔截器的 postHandle 逆序執行
  7. 處理結果(頁面渲染過程)
    → 若有異常,使用異常解析器(HandlerExceptionResolver) 處理異常,然後返回 mav
    → 呼叫 render() 進行頁面渲染
        → 檢視解析器根據檢視名得到檢視物件
        → 檢視物件呼叫 render() 完成渲染
    
  8. 攔截器的 afterCompletion 逆序執行

與 Spring 整合

  • 目的:分工明確
    • SpringMVC 的配置檔案就來配置和網站轉發邏輯以及網站功能有關的(各種解析器、支援 Ajax ...)
    • Spring 的配置檔案來配置和業務有關的(事務控制、資料來源 ...)
  • Spring 和 SpringMVC 分容器:
    • SpringMVC 管理控制器元件
      <context:component-scan base-package="cn.edu.nuist" use-default-filters="false">
          <context:include-filter type="annotation"
                  expression="org.springframework.stereotype.Controller"/>
          <context:include-filter type="annotation" 
                  expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
      </context:component-scan>
      
    • Spring 管理業務邏輯元件
      <context:component-scan base-package="cn.edu.nuist" use-default-filters="true">
          <context:exclude-filter type="annotation"
                  expression="org.springframework.stereotype.Controller"/>
          <context:exclude-filter type="annotation" 
                  expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
      </context:component-scan>
      
  • web.xml
    <!-- Spring 容器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- SpringMVC 容器 -->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMVC.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <!-- Map all requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
  • 啟動 Server
  • SpringMVC 的 IOC 容器中的 bean 可以來引用 Spring IOC 容器中的 bean,返回來呢 ?
    • 反之則不行!Spring IOC 容器中的 bean 不能來引用 SpringMVC IOC 容器中的 bean!
    • 多個 Spring IOC 容器之間可以設定為父子關係,以實現良好的解耦。
    • Spring MVC 配置檔案中引用業務層的 bean,故 SpringMVC Web 層容器可作為 "業務層" Spring 容器的子容器:即 Web 層容器可以引用業務層容器的 bean,而業務層容器卻訪問不到 Web 層容器的 bean