# 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
## 4.11、AbstractWizardFormController
向導控制器類提供了多步驟(向導)表單的支持(如完善個人資料時分步驟填寫基本信息、工作信息、學校信息等)
**假設現在做一個完善個人信息的功能,分三個頁面展示:**
1、頁面1完善基本信息;
2、頁面2完善學校信息;
3、頁面3完善工作信息。
這里我們要注意的是當用戶跳轉到頁面2時頁面1的信息是需要保存起來的,還記得AbstractFormController中的sessionForm嗎??如果為true則表單數據存放到session中,哈哈,AbstractWizardFormController就是使用了這個特性。

**向導中的頁碼從0開始;**
**PARAM_TARGET = "_target":**
用于選擇向導中的要使用的頁面參數名前綴,如“_target0”則選擇第0個頁面顯示,即圖中的“wizard/baseInfo”,以此類推,如“_target1”將選擇第1頁面,要得到的頁碼為去除前綴“_target”后的數字即是;
**PARAM_FINISH = "_finish":**
如果請求參數中有名為“_finish”的參數,表示向導成功結束,將會調用processFinish方法進行完成時的功能處理;
**PARAM_CANCEL = "_cancel":**
如果請求參數中有名為“_cancel”的參數,表示向導被取消,將會調用processCancel方法進行取消時的功能處理;
**向導中的命令對象:**
向導中的每一個步驟都會把相關的參數綁定到命令對象,該表單對象默認放置在session中,從而可以跨越多次請求得到該命令對象。
接下來具體看一下如何使用吧。
**(1、修改我們的模型數據以支持多步驟提交:**?
1. public?class?UserModel?{??
2. private?String?username;??
3. private?String?password;??
4. private?String?realname;?//真實姓名??
5. private?WorkInfoModel?workInfo;??
6. private?SchoolInfoModel?schoolInfo;??
7. //省略getter/setter??
8. }??
1. public?class?SchoolInfoModel?{??
2. private?String?schoolType;?//學校類型:高中、中專、大學??
3. private?String?schoolName;?//學校名稱??
4. private?String?specialty;?//專業??
5. //省略getter/setter??
6. }??
1. public?class?WorkInfoModel?{??
2. private?String?city;?//所在城市??
3. private?String?job;?//職位??
4. private?String?year;?//工作年限??
5. //省略getter/setter??
6. }??
**(2、控制器**
1. package?cn.javass.chapter4.web.controller;??
2. //省略import??
3. public?class?InfoFillWizardFormController?extends?AbstractWizardFormController?{??????
4. public?InfoFillWizardFormController()?{??
5. setCommandClass(UserModel.class);??
6. setCommandName("user");??
7. }??
8. protected?Map?referenceData(HttpServletRequest?request,?int?page)?throws?Exception?{??
9. Map?map?=?new?HashMap();??
10. if(page==1)?{?//如果是填寫學校信息頁?需要學校類型信息??
11. map.put("schoolTypeList",?Arrays.asList("高中",?"中專",?"大學"));??
12. }??
13. if(page==2)?{//如果是填寫工作信息頁?需要工作城市信息??
14. map.put("cityList",?Arrays.asList("濟南",?"北京",?"上海"));??
15. }??
16. return?map;??
17. }?????
18. protected?void?validatePage(Object?command,?Errors?errors,?int?page)?{??
19. //提供每一頁數據的驗證處理方法??
20. }??
21. protected?void?postProcessPage(HttpServletRequest?request,?Object?command,?Errors?errors,?int?page)?throws?Exception?{??
22. //提供給每一頁完成時的后處理方法??
23. }??
24. protected?ModelAndView?processFinish(HttpServletRequest?req,?HttpServletResponse?resp,?Object?command,?BindException?errors)?throws?Exception?{??
25. //成功后的處理方法??
26. System.out.println(command);??
27. return?new?ModelAndView("redirect:/success");??
28. }??
29. protected?ModelAndView?processCancel(HttpServletRequest?request,?HttpServletResponse?response,?Object?command,?BindException?errors)?throws?Exception?{??
30. //取消后的處理方法??
31. System.out.println(command);??
32. return?new?ModelAndView("redirect:/cancel");??
33. }??
34. }??
**page頁碼:**是根據請求中以“_target”開頭的參數名來確定的,如“_target0”,則頁碼為0;
**referenceData:**提供每一頁需要的表單支持對象,如完善學校信息需要學校類型,page頁碼從0開始(而且根據請求參數中以“_target”開頭的參數來確定當前頁碼,如_target1,則page=1);
**validatePage:**驗證當前頁的命令對象數據,驗證應根據page頁碼來分步驟驗證;
**postProcessPage:**驗證成功后的后處理;
**processFinish:**成功時執行的方法,此處直接重定向到/success控制器(詳見CancelController);
**processCancel:**取消時執行的方法,此處直接重定向到/cancel控制器(詳見SuccessController);
其他需要了解:
**allowDirtyBack和allowDirtyForward:**決定在當前頁面驗證失敗時,是否允許向導前移和后退,默認false不允許;
**onBindAndValidate(HttpServletRequest request, Object command, BindException errors, int page):**允許覆蓋默認的綁定參數到命令對象和驗證流程。
**(3、spring配置文件(chapter4-servlet.xml)**
1. <bean?name="/infoFillWizard"???
2. class="cn.javass.chapter4.web.controller.InfoFillWizardFormController">??
3. <property?name="pages">??
4. <list>??
5. <value>wizard/baseInfo</value>??
6. <value>wizard/schoolInfo</value>??
7. <value>wizard/workInfo</value>??
8. </list>??
9. </property>??
10. </bean>??????
**pages:**表示向導中每一個步驟的邏輯視圖名,當InfoFillWizardFormController的page=0,則將會選擇“wizard/baseInfo”,以此類推,從而可以按步驟選擇要展示的視圖。
**(4、向導中的每一步視圖**
**(4.1、基本信息頁面(第一步) baseInfo.jsp:**?
1. <form?method="post">??
2. 真實姓名:<input?type="text"?name="realname"?value="${user.realname}"><br/>??
3. <input?type="submit"?name="_target1"?value="下一步"/>??
4. </form>??
**當前頁碼為0;**
**name="_target1":**表示向導下一步要顯示的頁面的頁碼為1;
**(4.2、學校信息頁面(第二步) schoolInfo.jsp:**
1. <form?method="post">??
2. 學校類型:<select?name="schoolInfo.schoolType">??
3. <c:forEach?items="${schoolTypeList?}"?var="schoolType">??
4. <option?value="${schoolType?}"???
5. <c:if?test="${user.schoolInfo.schoolType?eq?schoolType}">??
6. selected="selected"??
7. </c:if>??
8. >??
9. ${schoolType}??
10. </option>??
11. </c:forEach>??
12. </select><br/>??
13. 學校名稱:<input?type="text"?name="schoolInfo.schoolName"?value="${user.schoolInfo.schoolName}"/><br/>??
14. 專業:<input?type="text"?name="schoolInfo.specialty"?value="${user.schoolInfo.specialty}"/><br/>??
15. <input?type="submit"?name="_target0"?value="上一步"/>??
16. <input?type="submit"?name="_target2"?value="下一步"/>??
17. </form>??
**(4.3、工作信息頁面(第三步) workInfo.jsp:**
1. <form?method="post">??
2. 所在城市:<select?name="workInfo.city">??
3. <c:forEach?items="${cityList?}"?var="city">??
4. <option?value="${city?}"???
5. <c:if?test="${user.workInfo.city?eq?city}">selected="selected"</c:if>??
6. >??
7. ${city}??
8. </option>??
9. </c:forEach>??
10. </select><br/>??
11. 職位:<input?type="text"?name="workInfo.job"?value="${user.workInfo.job}"/><br/>??
12. 工作年限:<input?type="text"?name="workInfo.year"?value="${user.workInfo.year}"/><br/>??
13. <input?type="submit"?name="_target1"?value="上一步"/>??
14. <input?type="submit"?name="_finish"?value="完成"/>??
15. <input?type="submit"?name="_cancel"?value="取消"/>??
16. </form>??
**當前頁碼為2;**
**name="_target1":上一步,**表示向導上一步要顯示的頁面的頁碼為1;
**name="_finish":向導完成,**表示向導成功,將會調用向導控制器的**processFinish方法**;
**name="_cancel":向導取消,**表示向導被取消,將會調用向導控制器的**processCancel方法**;
到此向導控制器完成,此處的向導流程比較簡單,如果需要更復雜的頁面流程控制,可以選擇使用Spring Web Flow框架。
## 4.12、ParameterizableViewController
參數化視圖控制器,不進行功能處理(即靜態視圖),根據參數的邏輯視圖名直接選擇需要展示的視圖。?
1. <bean?name="/parameterizableView"???
2. class="org.springframework.web.servlet.mvc.ParameterizableViewController">??
3. <property?name="viewName"?value="success"/>??
4. </bean>??
該控制器接收到請求后直接選擇參數化的視圖,這樣的好處是在配置文件中配置,從而避免程序的硬編碼,比如像幫助頁面等不需要進行功能處理,因此直接使用該控制器映射到視圖。
## 4.13、AbstractUrlViewController
提供根據請求URL路徑直接轉化為邏輯視圖名的支持基類,即不需要功能處理,直接根據URL計算出邏輯視圖名,并選擇具體視圖進行展示:
**urlDecode:**是否進行url解碼,不指定則默認使用服務器編碼進行解碼(如Tomcat默認ISO-8859-1);
**urlPathHelper:**用于解析請求路徑的工具類,默認為org.springframework.web.util.UrlPathHelper。
UrlFilenameViewController是它的一個實現者,因此我們應該使用UrlFilenameViewController。
## 4.14、UrlFilenameViewController
將請求的URL路徑轉換為邏輯視圖名并返回的轉換控制器,即不需要功能處理,直接根據URL計算出邏輯視圖名,并選擇具體視圖進行展示:
根據請求URL路徑計算邏輯視圖名;?
1. <bean?name="/index1/*"???
2. class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>??
3. <bean?name="/index2/**"???
4. class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>??
5. <bean?name="/*.html"???
6. class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>??
7. <bean?name="/index3/*.html"???
8. class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>??
**/index1/*:**可以匹配/index1/demo,但不匹配/index1/demo/demo,如/index1/demo邏輯視圖名為demo;
**/index2/**:**可以匹配/index2路徑下的所有子路徑,如匹配/index2/demo,或/index2/demo/demo,“/index2/demo”的邏輯視圖名為demo,而“/index2/demo/demo”邏輯視圖名為demo/demo;
**/*.html:**可以匹配如/abc.html,邏輯視圖名為abc,后綴會被刪除(不僅僅可以是html);
**/index3/*.html:**可以匹配/index3/abc.html,邏輯視圖名也是abc;
上述模式為Spring Web MVC使用的Ant-style?模式進行匹配的:
1. ?????匹配一個字符,如/index??可以匹配?/index1?,?但不能匹配?/index?或?/index12??
2. *????匹配零個或多個字符,如/index1/*,可以匹配/index1/demo,但不匹配/index1/demo/demo?
3. **???匹配零個或多個路徑,如/index2/**:可以匹配/index2路徑下的所有子路徑,如匹配/index2/demo,或/index2/demo/demo?
5. 如果我有如下模式,那Spring該選擇哪一個執行呢?當我的請求為“/long/long”時如下所示:?
6. /long/long?
7. /long/**/abc??
8. /long/**?
9. /**?
10. Spring的AbstractUrlHandlerMapping使用:最長匹配優先;?
11. 如請求為“/long/long”?將匹配第一個“/long/long”,但請求“/long/acd”?則將匹配?“/long/**”,如請求“/long/aa/abc”則匹配“/long/**/abc”,如請求“/abc”則將匹配“/**”??
UrlFilenameViewController還提供了如下屬性:
**prefix:**生成邏輯視圖名的前綴;
**suffix:**生成邏輯視圖名的后綴;
1. protected?String?postProcessViewName(String?viewName)?{??
2. return?getPrefix()?+?viewName?+?getSuffix();??
3. }??
1. <bean?name="/*.htm"?class="org.springframework.web.servlet.mvc.UrlFilenameViewController">??
2. <property?name="prefix"?value="test"/>??
3. <property?name="suffix"?value="test"/>??
4. </bean>??
當**prefix=“test”,suffix=“test”**,如上所示的**/*.htm:**可以匹配如/abc.htm,但邏輯視圖名將變為testabctest。
[
私塾在線學習網](http://sishuok.com/)原創內容([http://sishuok.com](http://sishuok.com/))
原創內容,轉載請注明私塾在線【[http://sishuok.com/forum/blogPost/list/5254.html](http://sishuok.com/forum/blogPost/list/0/5234.html)】
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC