環境 Spring 4.2.3
一下內容學習總結於《精通Spring 4.x——企業應用開發實戰》,跟開濤學習Spring MVC
Spring MVC 體系結構
整個框架中DispatcherServlet處於核心的位置,他負責協調和組織不同 的組件以完成請求處理並返回相應的工作。 Spring MVC通過一個前端Servlet接受所有的請求,並將具體的工作委託 給其他組件進行處理,DispatcherServlet就是SpringMVC的前端的Servlet。
下面對Spring MVC處理請求的整體過程講解
- 客戶端發出一個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>
- DispatcherServlet接受處理這個請求後,根據這個請求的信息(URL,請 求參數,報文頭,Cookie等)以HandlerMapping的配置找到處理請求的處理器(Handler)。可將HanderMapping看作路由控制器,將Handlei•看作目標 主機。實際上任伯I 一個Object都可以看作請求處理器。
- 當DispatcherServlet根據HandlerMapping得到對應當前請求的Hanlder 後,通過HandlerAdapter對Handler進行封裝,再以統一的是適配器接口調用 Handler。HandlerAdapter是一個適配器,它用統一的接口對各種Handler方法 進行調用。
- 處理器完成業務邏輯的處理後將放回的ModelAndView給 DispatcherServlet, ModelAnd View包含了視圖邏輯名,和模式數據信息。
- ModelAndView包含邏輯視圖名而非是真正的視圖對象。DispatcherServlet 倍由ViewResolver完成邏輯視圖名到真實視圖對象的解析工作。
- 得到真正的視圖對象View後,DispatchersServlet就使用這個View對象對 ModelAndView中的模型數據進行視圖渲染。
- 最終返回到客戶到的可能是HTML, XML、JSON、PDF等
以上每一步驟都包含豐富的知識點。
要了解Spring MVC 框架機制工作機理,也要知道幾個問題
問題
- DispatcherServlet框架如何攔截特定的HTTP請求,並交由Spring MVC處理?
- 位於Web層的Spring容器(WebApplicationContext)如何與位於業務層的Spring容器(ApplicationContext)建立關聯,以使Web層的Bean可以調用業務層的Bean?
- 如何初始化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 區別,關係與加載順序
引言:
-
多個Spring容器之間可設置子父的關係的,以實現良好的解耦。
-
這裏“Web層”Spring容器將作爲“業務層”Spring容器的子容器,即 “Web層”容器可以引用“業務層”容器的Bean,而“業務層”容器訪問不到“Web層”容器的Bean。
關係與區別:
- applicationContext.xml文件通常用於加載業務層spring系統級別的組件,比如bean的初始化
- servlet-Name-servlet.xml文件通常用於加載controller層需要的類,比如攔截器,mvc標籤加載的類
- 如果直接使用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;