本文作者來自:http://ttwang.iteye.com/blog/1680301
作爲一個 J2EE 的開發者,我們基本上是開發基於 WEB 的應用系統。事實上,工作流,狀態管理以及驗證都是需要解決的重要功能。而 HTTP 協議的無狀態性決定了這些功能都不容易實現。 Spring 的 WEB 框架就是來幫助我們解決這些問題的。使用 Spring ,我們可以讓 WEB 框架自動將傳遞進來的請求參數填充到模型對象中,同時提供驗證和錯誤處理。還可以管理用戶在 WEB 表單中創建的對象的狀態。在瞭解 SpringMVC 之前,我們先來複習下 MVC.
MVC 從邏輯上把應用分爲模型組件,視圖組件和控制器組件。其中控制器組件又可以細分爲:前端控制器組件和後端控制器組件。
我們來看一下 MVC 的基本工作流程:
首先是客戶端(通常是瀏覽器)發出一個請求。第一個接受這個請求的組件一般是一個前端控制器。它將不同的請求交給不同的後端控制器來處理,而在後端控制器裏面又可以調用相應的模型對象來處理具體的業務邏輯,最後再返回一個特定的視圖響應給客戶端。
現在大家應該可以理解 MVC 的設計思想了。拿我們比較熟悉的 struts 框架來說,前端控制器就是 ActionServlet, 後端控制器就是 Action. 請求的 URL 和後端控制器的映射關係在 struts-config.xml 上的 <action-mappings> 裏面配置,模型對象就是我們平常寫的 DAO/DTO ,返回的視圖類型一般就是 jsp 了。
那麼,在 spring MVC 中又是怎樣的呢 ? ,我們先按上面對號入座地說一下。第一個接受這個請求的前端控制器叫 DispatcherServlet ,後端控制器叫 Controller 。負責處理請求 URL 和後端控制器映射的叫 HandMapping ,它有多種類型,比較靈活,也是在一個 xml 文件上進行配置。負責業務邏輯處理的模型對象一般也是我們平常寫的 DAO/DTO 組件。只是它最後的返回更靈活, Controller 返回一個 ModelAndView 對象給 DispatcherServlet , ModelAndView 可以攜帶一個視圖對象,也可以攜帶一個視圖對象的邏輯名。如果攜帶的是一個視圖對象的邏輯名,那 DispatcherServlet 需要一個 ViewResolver 來查找用於渲染迴應的視圖對象。最後, DispatcherServlet 將請求分派給 ModelAndView 對象指定的視圖對象。視圖對象負責渲染返回給客戶的迴應。
我們學習知識,一樣要注意運用類比遷移的方法。有人說,我學會了 struts ,但學不會 springMVC 。這是說不過去的。因爲二者的思想完全一致。所以,我們只需要學習它們不一樣的地方就可以啦。好,我們現在先跑一個最簡單的例子,讓大家對構建 SpringMVC 的基本步驟有個直觀的認識。大家要邊跑邊跟 struts 做比較。
(1) 建立動態 web 工程,導入 spring 的 jar 包。
(2) 配置 DispatcherServlet
DispatcherServlet 是 SpringMVC 的核心,將下面 Servlet 的註冊信息登記在 web.xml 中。一定要記住: Servlet 跟伴侶一樣,要結婚,先得註冊登記!
< servlet >
< servlet-name > test </ servlet-name > < servlet-class > org.springframework.web.servlet.DispatcherServlet </ servlet-class >
< load-on-startup > 1 </ load-on-startup >
</ servlet >
< servlet-mapping >
< servlet-name > test </ servlet-name >
< url-pattern > *.do </ url-pattern >
</ servlet-mapping >
(3) 編寫 Controller ,做核心配置文件,並配置 url 和 Controller 的映射
package com.wepull.test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class HelloController implements Controller{
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
request.setAttribute( "hello" , "welcome to spring!" );
return new ModelAndView( " welcome " );
}
}
我們知道 Struts 有個 XML 格式的核心配置文件, springMVC 當然也有,在 WEB-INF 下新建一 XML 文件 : test -servlet.xml. 注意,這裏的 test 取決於 servlet 的名字 . 當 DispatcherServlet 載入後,它將試圖從這個文件中載入應用上下文。
<? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
<!-- 缺省映射處理器,不需要明確聲明,但聲明後就非常清楚使用的是哪個映射處理器 --> < bean id = "beanNameUrlMapping"
class = "org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" >
</ bean >
<!-- 這裏的 name 屬性有兩個職責,既定義 Bean 的名字,也定義需要這個控制器處理的 URL 樣式 -->
< bean name = "/hello.do"
class = "com.wepull.test.HelloController" >
</ bean >
</ beans >
上面可能有人奇怪,爲什麼不用 id 屬性,而設置 name 屬性。這裏是因爲 URL 中含有 XML id 屬性非法字符——特別是斜槓( / ) ;
(4) 配置一個視圖解析器將控制器與 JSP 結合起來。
將解析器的配置片段加到上面的 test-servlet.xml 中。
< bean id = "viewResolver"
class = "org.springframework.web.servlet.view.InternalResourceViewResolver" >
< property name = "prefix" value = "/WEB-INF/jsp/" />
< property name = "suffix" value = ".jsp" />
</ bean >
InternalResourceViewResolver 在 ModelAndView 返回的視圖名前加上 prefix 屬性配置的前綴 , 再在最後加上 suffix 屬性配置的後綴。由於 HelloController 返回的 ModelAndView 中視圖名爲 welcome, 所以 InternalResourceViewResolver 將在 /WEB-INF/jsp/welcome.jsp 處查找視圖。
(5) 編寫呈現給用戶的 jsp 文件。
/WEB-INF/jsp/welcome.jsp
<%@ page contentType = "text/html; charset=UTF-8" %>
<%@ page isELIgnored = "false" %>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns = "http://www.w3.org/1999/xhtml" >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" />
< title > Hello World! </ title >
</ head >
< body >
< h2 >
${hello}
</ h2 >
</ body >
</ html >
完成後啓動服務器,在瀏覽器地址欄上輸入 http://locahost:8080/projectName/hello.do 就可以訪問了。
對照一下,我們發現 SpringMVC 跟 Struts 大同小異。只是有兩處映射, SpringMVC 做的相對靈活。哪兩處呢?
(1) url 和動作 ( 後端控制器 ) 的映射。
springMVC 裏有個映射處理器 (HandlerMapping) 的概念。它實際上是一個處理器映射 Bean, 用來將一個控制器指定到一個 URL 上。 Spring 提供了三種有用的 HandlerMapping 的實現:
—— BeanNameUrlHandlerMapping
根據控制器的名字將控制器映射到 URL
—— SimpleUrlHandlerMapping
用上下文配置文件中定義的屬性集合將控制器映射到 URL
—— CommonsPathMapHandlerMapping
使用控制器代碼中的元數據將控制器映射到 URL
(2) 邏輯視圖名和視圖對象的映射。
springMVC 裏還有個視圖解析器 (ViewResolver) 的概念。它決定了 ModelAndView 對象的邏輯視圖名如何解析成一個用於將結果渲染給用戶的視圖 Bean..Spring 有四種 ViewResolver 實現:
—— InternalResourceViewResolver
將邏輯視圖名解析成一個用模板文件 ( 如 JSP 和 Velocity 模板 ) 渲染的視圖對象
—— BeanNameViewResolver
將邏輯視圖名解析成一個 DispatcherServlet 應用上下文中的視圖 Bean
—— ResourceBundleViewResolver
將邏輯視圖名解析成一個 ResourceBundler 中的視圖對象
—— XmlViewResolver
從一個 XML 文件中解析視圖 Bean, 這個文件是從 DispatcherServlet 應用上下文中分離出來的。