springmvc詳解

spring-mvc 

spring <wbr>MVC詳解(轉) 

如圖 
請求首先通過DispatcherServlet。servlet根據HandlerMapping,來處理請求,並根據請求,來找到Controller,Controller執行完畢後,發送一個ModelAndView,並告訴需要展示哪個視圖。根據這個視圖,servlet找到這個視圖的ViewResolver,並由這個ViewResolver生成對應的view,並輸出。 

配置servlet 
springmvc是基於servlet的,因此需要在web.xml配置。 
<servlet> 
<servlet-name>roadrantz</servlet-name> 
<servlet-class>org.springframework.web.servlet.DispatcherServlet 
</servlet-class> 
<load-on-startup>1</load-on-startup> 
</servlet> 

默認情況下,DispatcherServlet會加載這個servletname-servlet.xml文件,將這個文件作爲spring的配置文件(淡然可以和全局的加載器,也就是全局的監聽器和監聽器加載的配置文件結合使用)。如上面我們定義的servlet-name的名字是roadrantz,因此它會加載roadrantz-servlet.xml。 

之後當然是要配置這個servlet對應的映射的了。 
<servlet-mapping> 
<servlet-name>roadrantz</servlet-name> 
<url-pattern>*.htm</url-pattern> 
</servlet-mapping> 

事實上,我們應該把配置分成多個文件。這樣,基於springmvc的配置只在servletname-servlet.xml中,和其他部分的配置(如事務管理,數據源等配置則在另外一個地方,因爲他們是通用的)是分開的。 

WebApplicationContext 
WebApplicationContext是ApplicationContext的子類它提供了爲WEB應用服務的更多功能。 
我們可以通過RequestContextUtils來獲取WebApplicationContext 

DispatcherServlet 
會配置如下的bean 
Bean type Explanation 
controllers mvc中的C 
handler mappings 處理器影射器,它會根據請求,查找到實際的請求處理者 
view resolvers 視圖解析器 
locale resolver 本地化解析器,提供國際化的支持 
Theme resolver 主題解析器 
multipart file 文件上傳解析器 
handler exception resolvers 異常處理器 

DispatcherServlet配置完成後,當相應的請求到達時,處理就開始了。 處理流程是 
1.找到WebApplicationContext並將其綁定到請求的一個屬性上, 以便控制器和處理鏈上的其它處理器能使用WebApplicationContext。 默認的屬性名爲DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE。 

2.將本地化解析器(localResolver)綁定到請求上,這樣使得處理鏈上的處理器在處理請求(準備數據、顯示視圖等等) 時能進行本地化處理。若不使用本地化解析器,也不會有任何副作用,因此如果不需要本地化解析,忽略它即可。 

3.將主題解析器綁定到請求上,這樣視圖可以決定使用哪個主題。如果你不需要主題,可以忽略它,不會有任何影響。 

4.如果上傳文件解析器被指定,Spring會檢查每個接收到的請求是否存在上傳文件,如果存在, 這個請求將被封裝成MultipartHttpServletRequest以便被處理鏈中的其它處理器使用 (關於文件上傳的更多內容請參考Section 13.8.2, “使用MultipartResolver”)。 

5.找到合適的處理器,執行和這個處理器相關的執行鏈(預處理器,後置處理器,控制器),以便爲視圖準備模型數據(用於渲染)。 

6.如果模型數據被返回,就使用配置在WebApplicationContext中的視圖解析器顯示視圖, 否則視圖不會被顯示。有多種原因可以導致返回的數據模型爲空,比如預處理器或後處理器可能截取了請求,這可能是出於安全原因, 也可能是請求已經被處理,沒有必要再處理一次。 

DispatcherServlet的初始化參數 
contextClass 實現了WebApplicationContext的類。默認是XmlWebApplicationContext。 
contextConfigLoSctraintgitohnat 與全局的contextConfigLoSctraintgitohnat參數可以共存 
namespace WebApplicationContext的命名空間。默認是[servlet-name]-servlet 


多個配置文件的方式 
1.基於監聽器的方式: 
定義監聽器 
<listener> 
<listener-class>org.springframework. 
web.context.ContextLoaderListener</listener-class> 
</listener> 
以及配置全局監聽器的配置屬性。 
注意 
有些比較老的容器,在初始化servlet之前,並不會初始化監聽器,因此如果可能會被部署到這樣的容器的話,需要將監聽器,改成另外一個servlet 
ContextLoaderServlet 
將它置於DispatcherServlet之前。 

不管是監聽器還是ContextLoaderServlet,這兩個全局的裝載器,在沒有指定配置文件的情況下,會查找/WEB-INF/applicationContext.xml。 
但我們會有更多的配置文件,可以通過屬性contextConfigLocation來設置 
如 
<context-param> 
<param-name>contextConfigLocation</param-name> 
<param-value> 
/WEB-INF/spitter-security.xml 
classpath:service-context.xml 
classpath:persistence-context.xml 
classpath:dataSource-context.xml 
</param-value> 
</context-param> 
這個屬性的值,和spring的資源Resource加載方式一樣,可以帶classpath:,file:,等前綴。 

這裏先給出一個非註解方式的使用方式。 
主頁 
主頁是一個web應用必須有的(這裏說的必須,你懂得)。 
當然先需要一個controller了。 
package com.roadrantz.mvc; 
import java.util.List; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.springframework.web.servlet.ModelAndView; 
import org.springframework.web.servlet.mvc.AbstractController; 
import com.roadrantz.service.RantService; 
public class HomePageController extends AbstractController { 
public HomePageController() { 


protected ModelAndView handleRequestInternal( 
HttpServletRequest request, HttpServletResponse response) 
throws Exception { 
List recentRants = rantService.getRecentRants(); 

//定義modelandview,home表示會返回home.jsp(是不是jsp由視圖解析器決定)。 
return new ModelAndView("home", 
"rants", recentRants); 


private RantService rantService; 

public void setRantService(RantService rantService) { 
this.rantService = rantService; 




ModelAndView對象 
ModelAndView封裝了視圖已經模型數據。 
注意,如果一個controller,return類型非null或者非viod,且沒有寫@ResponseBody註解的,最後都會被封裝成ModelAndView,對與返回的一個普通的bean的時候,分裝後的ModelAndView如下圖 

spring <wbr>MVC詳解(轉)  

new ModelAndView("home", "rants", recentRants); 
如上,第一個參數是視圖名字。之後的參數是以模型對象將被傳遞給視圖。 

下面是配置這個controller 
<bean name="/home.htm" 
class="com.roadrantz.mvc.HomePageController"> 
<property name="rantService" ref="rantService" /> 
</bean> 
這裏首先沒有使用id,而是使用name,這裏的原因是因爲有特殊字符/和.id不支持。而使用name。 

當一個請求home.htm(這個請求位於根目錄下,如果非根目錄是無法訪問的,如127.0.0.1/daowole/home.htm是可以訪問的,但是127.0.0.1/daowole/abc/home.htm是無法訪問的。如果想要它不管通過哪個目錄,只要是最後的資源是home.htm都可以訪問,可以把bean的name改成name="home.htm",那麼127.0.0.1/daowole/abc/home.htm還是127.0.0.1/daowole/home.htm都可以訪問了。)的話,那麼就會被訪問到這裏來。這裏可以發現我們無需配置HandlerMapping,因爲springmvc有一個默認的handlermapping,BeanNameUrlHandlerMapping。它是使用URL模式的基本名字。 

由於上面的的視圖使用的是jsp視圖,因此直接return一個jsp頁面,自然沒有問題了。 
而對應jsp視圖,springmvc自然還提供了其他配置(相對普通jsp而言),這需要使用到一個jsp的解析器,org.springframework.web.servlet.view.InternalResourceViewResolver。 
<bean id="viewResolver" 
class="org.springframework.web. 
servlet.view.InternalResourceViewResolver"> 
<property name="prefix"> 
<value>/WEB-INF/jsp/</value> 
</property> 
<property name="suffix"> 
<value>.jsp</value> 
</property> 
</bean> 
這個會再controller返回的時候,會拼裝前綴和後綴,再查找文件。如果找到,它來處理是自然的。 
home拼裝前綴和後綴後就是/WEB-INF/jsp/home.jsp 

對於spring3.0版本的,如果使用了Spring 3.0.4或以上版本的話,可以使用 
<mvc:resources location="" mapping=""/> 
在servletname-servlet.xml文件中。 
這種情況就解決了如果我們把url映射定義爲/(這會由springmvc處理所有的請求),那麼圖片,js等靜態資源會被由springmvc處理。它會把mapping指定的路徑(ant風格)映射到location中。 
<mvc:resources mapping="/resources 
public class HelloController 
    extends AbstractCommandController { 
... 


<bean id="urlMapping" 
class="org.springframework.web.servlet.handler.metadata.CommonsPathMapHandlerMapping" /> 


SimpleUrlHandlerMapping 

<bean id="simpleUrlMapping" 
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 
<property name="mappings"> 
<props> 
<prop key="test.html">homeController</prop> 
</props> 
</property> 
</bean> 
如上,當任何一種方式訪問到test.html,都由id=homeController的bean處理 

mappings是一個java.util.Properties類型的。 

ControllerClassNameHandlerMapping使用 

package com.cgodo.daowole.action; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.springframework.web.servlet.ModelAndView; 
import org.springframework.web.servlet.mvc.AbstractController; 

public class SampleController extends AbstractController { 
protected ModelAndView handleRequestInternal(HttpServletRequest arg0, 
HttpServletResponse arg1) throws Exception { 
ModelAndView mav = new ModelAndView("index"); 
mav.addObject("message", "Hello World!"); 

return mav; 


<bean id="urlMapping" 
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" /> 
如上,我們可以通過test.html(這裏的後綴.html和你的web.xml配置有關)。就能訪問。而不需要再增加其他的配置了。 

DefaultAnnotationHandlerMapping 根據@RequestMapping註解要查找action 

對於支持DefaultAnnotationHandlerMapping 版本的spring,如果沒有對應 
handlermapping,那麼DispatcherServlet會分別建立 
BeanNameUrlHandlerMapping 
和 
DefaultAnnotationHandlerMapping 

多個handlemapping同時處理,也是可以的。我們也可以通過order屬性。來配置mapping的排序。 
如 
<bean id="beanNameUrlMapping" class="org.springframework.web. 
➥ servlet.handler.BeanNameUrlHandlerMapping"> 
<property name="order"><value>1</value></property> 
</bean> 
<bean id="simpleUrlMapping" class="org.springframework.web. 
➥ servlet.handler.SimpleUrlHandlerMapping"> 
<property name="order"><value>0</value></property> 
<property name="mappings"> 
… 
</property> 
</bean> 
這裏的話,SimpleUrlHandlerMapping排序是0,因此它首先被servlet詢問,如果這個SimpleUrlHandlerMapping有結果回來(標示它來處理),那麼就進行處理,而沒有的話,將詢問下一個,也就是BeanNameUrlHandlerMapping。 

控制器 

spring <wbr>MVC詳解(轉)  

如圖,spring的控制器,由Controller接口定義。 
可以將控制器歸類爲6類 
View類型: 
ParameterizableViewController 
UrlFilenameViewController 
當控制器只需要顯示靜態視圖時。 

Simple類型 
Controller (interface) 
AbstractController 

Throwaway類型 
ThrowawayController 

Multiaction類型 
MultiActionController 
當action中有多個執行代碼(方法)。 

Command類型 
BaseCommandController 
AbstractCommandController 
action可以獲取請求的一個或多個參數,並將參數封裝成一個對象。還能對參數進行驗證。 

Form類型 
AbstractFormController 
SimpleFormController 
擁有表單處理功能。 

Wizard類型 
AbstractWizardFormController 
當一個應用,由多個步驟組成,每一個步驟走完之後,得到一個結果,類似嚮導。 

AbstractCommandController 
直接繼承AbstractController,自然可以訪問到request,來獲取參數,完成參數驗證,但是這樣會讓你的action變得複雜。 
package com.cgodo.daowole.action; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.springframework.validation.BindException; 
import org.springframework.web.servlet.ModelAndView; 
import org.springframework.web.servlet.mvc.AbstractCommandController; 

import com.cgodo.daowole.model.Page; 

@SuppressWarnings("deprecation") 
public class SampleController extends AbstractCommandController { 

public SampleController() { 
setCommandClass(Page.class); 
setCommandName("page"); 


@SuppressWarnings("unchecked") 

發佈了32 篇原創文章 · 獲贊 8 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章