Spring MVC學習(一)

環境 Spring 4.2.3
一下內容學習總結於《精通Spring 4.x——企業應用開發實戰》,跟開濤學習Spring MVC

Spring MVC 體系結構

來自網絡
整個框架中DispatcherServlet處於核心的位置,他負責協調和組織不同 的組件以完成請求處理並返回相應的工作。 Spring MVC通過一個前端Servlet接受所有的請求,並將具體的工作委託 給其他組件進行處理,DispatcherServlet就是SpringMVC的前端的Servlet。

下面對Spring MVC處理請求的整體過程講解

  1. 客戶端發出一個HTTP請求,Web應用服務器接受到這個請求,如果匹配 DispatcherServlet的請求映射路徑(在web.xml指定),則Web容器將請求轉 交給 DispatcherServlet 處理。例如:
 <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.html</url-pattern>
        <!--通過servlet-mapping指定DispatcherServlet處理所有的.html爲後綴的http請求-->
    </servlet-mapping>
  1. DispatcherServlet接受處理這個請求後,根據這個請求的信息(URL,請 求參數,報文頭,Cookie等)以HandlerMapping的配置找到處理請求的處理器(Handler)。可將HanderMapping看作路由控制器,將Handlei•看作目標 主機。實際上任伯I 一個Object都可以看作請求處理器。
  2. 當DispatcherServlet根據HandlerMapping得到對應當前請求的Hanlder 後,通過HandlerAdapter對Handler進行封裝,再以統一的是適配器接口調用 Handler。HandlerAdapter是一個適配器,它用統一的接口對各種Handler方法 進行調用。
  3. 處理器完成業務邏輯的處理後將放回的ModelAndView給 DispatcherServlet, ModelAnd View包含了視圖邏輯名,和模式數據信息。
  4. ModelAndView包含邏輯視圖名而非是真正的視圖對象。DispatcherServlet 倍由ViewResolver完成邏輯視圖名到真實視圖對象的解析工作。
  5. 得到真正的視圖對象View後,DispatchersServlet就使用這個View對象對 ModelAndView中的模型數據進行視圖渲染。
  6. 最終返回到客戶到的可能是HTML, XML、JSON、PDF等

以上每一步驟都包含豐富的知識點。

要了解Spring MVC 框架機制工作機理,也要知道幾個問題

問題

  1. DispatcherServlet框架如何攔截特定的HTTP請求,並交由Spring MVC處理?
  2. 位於Web層的Spring容器(WebApplicationContext)如何與位於業務層的Spring容器(ApplicationContext)建立關聯,以使Web層的Bean可以調用業務層的Bean?
  3. 如何初始化SpringMVC的各個組件,並將他們裝配到DispatcherServlet中?

項目結構

1、配置DispatcherServlet,截取特定的URL請求。

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- ① -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/appcationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet><!-- ② -->
        <servlet-name>springmvc</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping><!-- ③ -->
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.html</url-pattern>
        <!--通過servlet-mapping指定DispatcherServlet處理所有的.html爲後綴的http請求-->
    </servlet-mapping>
</web-app>

①:contextConfigLocation:,表示用於加載Bean的配置文件。通過contextConfigLocation參數指定業務層Spring容器的配置文件;
②:配置名爲springmvc的DispatcherServlet,他默認會自動加載/WEB/INF/springmvc-servlet.xml(servlet-Name-servlet.xml)的Webc層的Spring配置文件,啓動Web層的Spring容器。
③:所有帶.html爲後綴的HTTP請求會被DispatcherServlet截獲處理。

我們也可通過Java 編程方式來配置Servlet容器。不需要web.xml,思路一樣
參考官方描述

將web,xml文件的配置全部註解掉,添加SpringmvcApplicationInitializer類,實現WebApplicationInitializer接口。 啓動,效果是一樣的。

package com.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class SpringmvcApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("/WEB-INF/springmvc-servlet.xml");
        ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(appContext));
        dynamic.setLoadOnStartup(1);
        dynamic.addMapping("*.html*");
    }
}

可能有人會疑問爲什麼實現WebApplicationInitializer接口就能配置Servlet了呢?

在Spring 3.0環境中,容器會在類路徑中查找實現javax.servlet.ServletContainerInitializer的類,如果返現有實現的類,就會調用它,配置Servlet容器。在Spring中,org.springframework.web.SpringServletContainerInitializer類實現了ServletContainerInitializer接口,同時這個類會查找實現org.springframework.web.WebApplicationInitializer接口的類,並將配置任務交給這些實現類去完成。

擴充知識:

applicationContext.xml與servlet-Name-servlet.xml 區別,關係與加載順序
引言:

  1. 多個Spring容器之間可設置子父的關係的,以實現良好的解耦。

  2. 這裏“Web層”Spring容器將作爲“業務層”Spring容器的子容器,即 “Web層”容器可以引用“業務層”容器的Bean,而“業務層”容器訪問不到“Web層”容器的Bean。

關係與區別:

  1. applicationContext.xml文件通常用於加載業務層spring系統級別的組件,比如bean的初始化
  2. servlet-Name-servlet.xml文件通常用於加載controller層需要的類,比如攔截器,mvc標籤加載的類
  3. 如果直接使用SpringMVC是可以不添加applicationContext.xml文件的,其實我的applicatiContext.xml是空,如下。因爲applicationContext.xml是隨着ContextLoaderListener的加載兒執行的。由於沒有配置applicationContext.xml所以我們就可以去掉web.xml文件中的 context-param標籤、listener標籤。
    直接採用SpringMVC,只需要把所有相關配置放到servlet-Name-servlet.xml中就OK了

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--沒有內容-->
</beans>

加載先後:
以下內容摘自
首先applicationContext.xml是隨ContextLoaderListener的加載而執行的,而servlet-Name-servlet.xml是隨DispatcherServlet的加載而執行的,在web.xml中;
加載順序是listener>filter>servlet;

2、探究DispatcherServlet的內部邏輯

DispatcherServlet詳解
圖三

來自網絡

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章