Spring mvc 是Spring 架構最重要的子產品之一。它建構于強大的Spring IOC 容器之上,大量使用容器的特性就行簡化。
M model 模式----封裝視圖展示的應用資料
V view 視圖-----隻是顯示資料,不包含任何業務邏輯
C controller 控制器----接受使用者請求并調用後端服務進行業務處理
工作原理:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQ3chVEa0V3bT9CX5RXa2Fmcn9CXwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVP9EVT1sGVNZWOXlFcG5mYshmMZZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39zM0gTN0cjM3ETOycDMzEDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
圖1.Spring MVC中請求處理主流程
核心元件是位于中心的Dispatcher Servlet控制器,該核心控制器需要在Java Web項目中的Web.xml檔案中進行描述。
從圖 1 中可以看出,其作為 MVC 架構的前端控制器,每個 Web 請求都必須通過它,以便使它能夠管理整個請求處理過程。
Request — 1
來自使用者的請求被 Dispatcher Servle 攔截下來
Request — 2.1
Dispatcher Servlet 将請求推送到 Handler Mapping 映射,在上下文環境中找到對應的 Controller (一個用 @Controller 進行修飾的 java 類 spring 3.0 )
Controller 經過 Handler Mapping 處理,請求被定位到對應的控制器類,再經過 Dispatcher Servlet 進行分發
request—2.2
請求被分發到指定的攔截器類中進行處理,這裡可以調用一些業務邏輯的服務類進行特定功能的實作,而資料的傳輸一般采用 model 屬性進行封裝 model.addtribute(“propertyName”,(Object) property)
ModelAndViow
最後傳回一個視圖名稱 viewName
View Name
Dispatcher Servlet 攔截并讓發送給視圖解析器進行解析
視圖解析器 View Resolver ,按照優先級進行解析
View
确定下視圖名稱與路徑
Modle
屬性在 View 中進行實作與初始化
Response—1
容器攔截并準備傳回
Response — 2
mvc 架構将實作好的視圖(資料注入後)頁面傳回給使用者
上訴邏輯的實作,需要在 Java Web 項目中的 Web 描述符 web.xml (配置檔案)進行部署。
關鍵是配置 servlet ,要使用 Spring mvc 必須配置其核心的控制器類——Dispatcher Servlet ,當然可以配置多個 DispatcherServlet 執行個體,以友善團隊間的協作開發。如圖 2 ,圖 3 所示。
1.<servlet> :
确定一個 servlet 和其實作的類,這裡實作的類是 DispathcerServlet
<Sevlet-name> : 第一個作用是與 <servlet-mapping> 中 <serlvet-name> 進行關聯,并根據其下的 <url-pattern> 進行請求路徑的攔截;
第二個作用是讓 DispatcherServlet 決定加載哪個 Spring MVC 配置檔案。預設情況下,如圖 3 查找的是 mannage 加上 -servlet.xml 的檔案;也可以自己在 <servlet> 參數 contextConfigLocation中明确指定一個配置檔案,如圖 2 查找的是 product-service.xml 檔案。
<url-pattern> 中 ’ / ’ 表示目前路徑下的所有請求
圖 2 product-servlet
圖3 manage-servlet
2.采用<context-param>加載上下文檔案
為了讓 Spring 加載 court-servlet.xml 之外的檔案,還必須在 web.xml 中定義 serlvet 監聽器(<listener>) ContextLoaderListener 。
預設情況下,它加載配置檔案 /WEB-INF/applicationContext.xml ;也可以在上下文 參數<param-name>contextConfigLocation中指定自己的檔案<param-value>/WEB-INF/manage-service.xml(你可以指定多個用逗号或者空格分隔的配置檔案),如圖 4 所示。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/base-service.xml ,
/WEB-INF/base2-service.xml </param-value>
</context-param>
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class>
</listener>
圖 4 context-param
ContextLoaderListener 加載指定的 Bean 配置檔案到根應用上下文中,而每個DispatcherServlet 将其配置檔案加載到自己的應用上下文,并且引用根應用上下文為其上級。每個 DispatcherServlet 執行個體加載的上下文可以通路甚至覆寫根應用上下文中聲明的 Bean( 反之則不行 ) 。但是, DispatcherServlet 執行個體加載的上下文無法互相通路。
現在大的環境已經配置好了,剩下的就是采用 @Controller 修飾控制器,這時我們知道哪個類是控制器類,哪個類一般的 JAVA 類了,但是讓 spring mvc 容器知道呢?
3. 采用 <context:component-scan> 元素啟用 Spring 的元件掃描功能。
product-service.xml
首先加入如下元素,讓其掃描指定包中的類
<context:component-scan
base-package="com.future.product.web" />
然後還需要加入下面 2 個聲明,因而在 web 上下文中注冊
DefaultAnnotationHandlerMapping和 AnnotationMethodHandlerAdapter執行個體,它們分别在類級别和方法級别處理 @ReqeustMapping 注解。
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.future.product.web.CountTimeInterceptor" />
</list>
</property>
</bean>
類級别的處理,可以加入自定義的攔截器 <property>
CountTmieInerceptor.java 是實作 HandlerInterceptor 接口或者繼承 HandlerInterceptorAdapter 的 java 類,可以在 Controller 類執行方法前後進行額外的操作
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="com.future.product.web.ProductBindingInitializer"></bean>
</property>
</bean>
方法級别的處理,可以加入自定義的方法 binding 類 <property>
ProductBindingInitializer.java 是實作 WebBindingInitializer 接口,實作自定義屬性的轉化與編輯。
現在大體上環境已經部署好了,下面通過一個簡單的例子來進行驗證、體會。
Eclipse + Tomcat7.0 +Spring MVC
1.項目在Eclipse中的結構如圖4所示。
圖 4 應用層次結構
2.需要導入的包如下:
commons-logging-1.1.1.jar
commons-logging-api-1.1.jar
log4j-1.2.16.jar
org.springframework.asm-3.0.7.RELEASE.jar
org.springframework.beans-3.0.7.RELEASE.jar
org.springframework.context.support-3.0.7.RELEASE.jar
org.springframework.context-3.0.7.RELEASE.jar
org.springframework.core-3.0.7.RELEASE.jar
org.springframework.expression-3.0.7.RELEASE.jar
org.springframework.jdbc-3.0.7.RELEASE.jar
org.springframework.web.portlet-3.0.7.RELEASE.jar
org.springframework.web.servlet-3.0.7.RELEASE.jar
org.springframework.web-3.0.7.RELEASE.jar
standard-1.1.2.jar
3.Web.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Future Future Future </display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/base-service.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>product</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/product-service.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>manage</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>product</servlet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/product/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>manage</servlet-name>
<url-pattern>/manage/*</url-pattern>
</servlet-mapping>
</web-app>
4.base.xml中還沒有具體寫東西,就先不管了,下面的是product-service.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" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.future.login.web" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="order" value="1" />
</bean>
</beans>
5.在 com.future.login.web 編寫一個 Login.java
package com.future.login.web;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@RequestMapping("/login")
@SessionAttributes("user")
public class Login {
@RequestMapping(method = RequestMethod.GET)
public String welcome(HttpServletRequest request){
return "welcome";
}
@RequestMapping(value = "/pr" ,method = RequestMethod.GET)
public String welcome2(HttpServletRequest request){
return "welcome";
}
}
6.在 WEB-INF/jsp/ 目錄下建立 Welcime.jsp
<body>
<h1> 歡迎您 2</h1>
<hr />
</body>