4.11、AbstractWizardFormController
向?qū)Э刂破黝愄峁┝硕嗖襟E(向?qū)В┍韱蔚闹С郑ㄈ缤晟苽€人資料時(shí)分步驟填寫基本信息、工作信息、學(xué)校信息等)
假設(shè)現(xiàn)在做一個完善個人信息的功能,分三個頁面展示:
1、頁面1完善基本信息;
2、頁面2完善學(xué)校信息;
3、頁面3完善工作信息。
這里我們要注意的是當(dāng)用戶跳轉(zhuǎn)到頁面2時(shí)頁面1的信息是需要保存起來的,還記得AbstractFormController中的sessionForm嗎??如果為true則表單數(shù)據(jù)存放到session中,哈哈,AbstractWizardFormController就是使用了這個特性。
向?qū)е械捻摯a從0開始;
PARAM_TARGET = "_target":
用于選擇向?qū)е械囊褂玫捻撁鎱?shù)名前綴,如“_target0”則選擇第0個頁面顯示,即圖中的“wizard/baseInfo”,以此類推,如“_target1”將選擇第1頁面,要得到的頁碼為去除前綴“_target”后的數(shù)字即是;
PARAM_FINISH = "_finish":
如果請求參數(shù)中有名為“_finish”的參數(shù),表示向?qū)С晒Y(jié)束,將會調(diào)用processFinish方法進(jìn)行完成時(shí)的功能處理;
PARAM_CANCEL = "_cancel":
如果請求參數(shù)中有名為“_cancel”的參數(shù),表示向?qū)П蝗∠?,將會調(diào)用processCancel方法進(jìn)行取消時(shí)的功能處理;
向?qū)е械拿顚ο螅?/b>
向?qū)е械拿恳粋€步驟都會把相關(guān)的參數(shù)綁定到命令對象,該表單對象默認(rèn)放置在session中,從而可以跨越多次請求得到該命令對象。
驅(qū)動式項(xiàng)目構(gòu)建
內(nèi)置高效可靠的代碼生成器
支持多種數(shù)據(jù)模型,根據(jù)數(shù)據(jù)庫表生成常規(guī)重復(fù)性代碼,使研發(fā)工程師更專注于業(yè)務(wù)邏輯代碼的實(shí)現(xiàn),大幅提升其工作效率,解放其重復(fù)性工作

OPEN CI
開源規(guī)范化項(xiàng)目管理解決方案,實(shí)現(xiàn)軟件流水線式生產(chǎn),保證正確性、可靠性
向?qū)絼?chuàng)建、導(dǎo)入項(xiàng)目,集成版本控制(GIT/SVN)、項(xiàng)目管理(Trac/Redmine)、代碼質(zhì)量(Sonar)、持續(xù)集成(Jenkins)
私有部署,統(tǒng)一管理,為開發(fā)者而生
愿意了解框架技術(shù)或者源碼的朋友直接加求求2042849237
接下來具體看一下如何使用吧。
(1、修改我們的模型數(shù)據(jù)以支持多步驟提交:
Java代碼
public?class?UserModel?{
private?String?username;
private?String?password;
private?String?realname;?//真實(shí)姓名
private?WorkInfoModel?workInfo;
private?SchoolInfoModel?schoolInfo;
//省略getter/setter
}
Java代碼
public?class?SchoolInfoModel?{
private?String?schoolType;?//學(xué)校類型:高中、中專、大學(xué)
private?String?schoolName;?//學(xué)校名稱
private?String?specialty;?//專業(yè)
//省略getter/setter
}
Java代碼
public?class?WorkInfoModel?{
private?String?city;?//所在城市
private?String?job;?//職位
private?String?year;?//工作年限
//省略getter/setter
}
(2、控制器
Java代碼
package?cn.javass.chapter4.web.controller;
//省略import
public?class?InfoFillWizardFormController?extends?AbstractWizardFormController?{
public?InfoFillWizardFormController()?{
setCommandClass(UserModel.class);
setCommandName("user");
}
protected?Map?referenceData(HttpServletRequest?request,?int?page)?throws?Exception?{
Map?map?=?new?HashMap();
if(page==1)?{?//如果是填寫學(xué)校信息頁?需要學(xué)校類型信息
map.put("schoolTypeList",?Arrays.asList("高中",?"中專",?"大學(xué)"));
}
if(page==2)?{//如果是填寫工作信息頁?需要工作城市信息
map.put("cityList",?Arrays.asList("濟(jì)南",?"北京",?"上海"));
}
return?map;
}
protected?void?validatePage(Object?command,?Errors?errors,?int?page)?{
//提供每一頁數(shù)據(jù)的驗(yàn)證處理方法
}
protected?void?postProcessPage(HttpServletRequest?request,?Object?command,?Errors?errors,?int?page)?throws?Exception?{
//提供給每一頁完成時(shí)的后處理方法
}
protected?ModelAndView?processFinish(HttpServletRequest?req,?HttpServletResponse?resp,?Object?command,?BindException?errors)?throws?Exception?{
//成功后的處理方法
System.out.println(command);
return?new?ModelAndView("redirect:/success");
}
protected?ModelAndView?processCancel(HttpServletRequest?request,?HttpServletResponse?response,?Object?command,?BindException?errors)?throws?Exception?{
//取消后的處理方法
System.out.println(command);
return?new?ModelAndView("redirect:/cancel");
}
}
page頁碼:是根據(jù)請求中以“_target”開頭的參數(shù)名來確定的,如“_target0”,則頁碼為0;
referenceData:提供每一頁需要的表單支持對象,如完善學(xué)校信息需要學(xué)校類型,page頁碼從0開始(而且根據(jù)請求參數(shù)中以“_target”開頭的參數(shù)來確定當(dāng)前頁碼,如_target1,則page=1);
validatePage:驗(yàn)證當(dāng)前頁的命令對象數(shù)據(jù),驗(yàn)證應(yīng)根據(jù)page頁碼來分步驟驗(yàn)證;
postProcessPage:驗(yàn)證成功后的后處理;
processFinish:成功時(shí)執(zhí)行的方法,此處直接重定向到/success控制器(詳見CancelController);
processCancel:取消時(shí)執(zhí)行的方法,此處直接重定向到/cancel控制器(詳見SuccessController);
其他需要了解:
allowDirtyBack和allowDirtyForward:決定在當(dāng)前頁面驗(yàn)證失敗時(shí),是否允許向?qū)耙坪秃笸?,默認(rèn)false不允許;
onBindAndValidate(HttpServletRequest request, Object command, BindException errors, int page):允許覆蓋默認(rèn)的綁定參數(shù)到命令對象和驗(yàn)證流程。
(3、spring配置文件(chapter4-servlet.xml)
Java代碼

class="cn.javass.chapter4.web.controller.InfoFillWizardFormController">
wizard/baseInfo
wizard/schoolInfo
wizard/workInfo
pages:表示向?qū)е忻恳粋€步驟的邏輯視圖名,當(dāng)InfoFillWizardFormController的page=0,則將會選擇“wizard/baseInfo”,以此類推,從而可以按步驟選擇要展示的視圖。
(4、向?qū)е械拿恳徊揭晥D
(4.1、基本信息頁面(第一步) baseInfo.jsp:
Java代碼
真實(shí)姓名:
當(dāng)前頁碼為0;
name="_target1":表示向?qū)乱徊揭@示的頁面的頁碼為1;
(4.2、學(xué)校信息頁面(第二步) schoolInfo.jsp:
Java代碼
學(xué)校類型:
selected="selected"
>
${schoolType}
學(xué)校名稱:
專業(yè):
(4.3、工作信息頁面(第三步) workInfo.jsp:
Java代碼
所在城市:
selected="selected"
>
${city}
職位:
工作年限:
當(dāng)前頁碼為2;
name="_target1":上一步,表示向?qū)弦徊揭@示的頁面的頁碼為1;
name="_finish":向?qū)瓿桑?/b>表示向?qū)С晒Γ瑢{(diào)用向?qū)Э刂破鞯?b>processFinish方法;
name="_cancel":向?qū)∠?/b>表示向?qū)П蝗∠瑢{(diào)用向?qū)Э刂破鞯?b>processCancel方法;
到此向?qū)Э刂破魍瓿?,此處的向?qū)Я鞒瘫容^簡單,如果需要更復(fù)雜的頁面流程控制,可以選擇使用Spring Web Flow框架。
4.12、ParameterizableViewController
參數(shù)化視圖控制器,不進(jìn)行功能處理(即靜態(tài)視圖),根據(jù)參數(shù)的邏輯視圖名直接選擇需要展示的視圖。
Java代碼
class="org.springframework.web.servlet.mvc.ParameterizableViewController">
該控制器接收到請求后直接選擇參數(shù)化的視圖,這樣的好處是在配置文件中配置,從而避免程序的硬編碼,比如像幫助頁面等不需要進(jìn)行功能處理,因此直接使用該控制器映射到視圖。
4.13、AbstractUrlViewController
提供根據(jù)請求URL路徑直接轉(zhuǎn)化為邏輯視圖名的支持基類,即不需要功能處理,直接根據(jù)URL計(jì)算出邏輯視圖名,并選擇具體視圖進(jìn)行展示:
urlDecode:是否進(jìn)行url解碼,不指定則默認(rèn)使用服務(wù)器編碼進(jìn)行解碼(如Tomcat默認(rèn)ISO-8859-1);
urlPathHelper:用于解析請求路徑的工具類,默認(rèn)為org.springframework.web.util.UrlPathHelper。
UrlFilenameViewController是它的一個實(shí)現(xiàn)者,因此我們應(yīng)該使用UrlFilenameViewController。
4.14、UrlFilenameViewController
將請求的URL路徑轉(zhuǎn)換為邏輯視圖名并返回的轉(zhuǎn)換控制器,即不需要功能處理,直接根據(jù)URL計(jì)算出邏輯視圖名,并選擇具體視圖進(jìn)行展示:
根據(jù)請求URL路徑計(jì)算邏輯視圖名;
Java代碼
class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
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?模式進(jìn)行匹配的:
Java代碼
?????匹配一個字符,如/index??可以匹配?/index1?,?但不能匹配?/index?或?/index12
*????匹配零個或多個字符,如/index1/*,可以匹配/index1/demo,但不匹配/index1/demo/demo
**???匹配零個或多個路徑,如/index2/**:可以匹配/index2路徑下的所有子路徑,如匹配/index2/demo,或/index2/demo/demo
如果我有如下模式,那Spring該選擇哪一個執(zhí)行呢?當(dāng)我的請求為“/long/long”時(shí)如下所示:
/long/long
/long/**/abc
/long/**
/**
Spring的AbstractUrlHandlerMapping使用:最長匹配優(yōu)先;
如請求為“/long/long”?將匹配第一個“/long/long”,但請求“/long/acd”?則將匹配?“/long/**”,如請求“/long/aa/abc”則匹配“/long/**/abc”,如請求“/abc”則將匹配“/**”
UrlFilenameViewController還提供了如下屬性:
prefix:生成邏輯視圖名的前綴;
suffix:生成邏輯視圖名的后綴;
Java代碼
protected?String?postProcessViewName(String?viewName)?{
return?getPrefix()?+?viewName?+?getSuffix();
}
Java代碼
當(dāng)
prefix=
“test
”,suffix=
“test
”
,如上所示的
/*.htm
:
可以匹配如/abc.htm,但邏輯視圖名將變?yōu)閠estabctest。
分布式
分布式服務(wù):Dubbo+Zookeeper+Proxy+Restful
分布式消息中間件:KafKa+Flume+Zookeeper
分布式緩存:Redis??? 分布式文件:FastDFS
負(fù)載均衡:Keepalived+Nginx+Proxy(三重負(fù)載)
歡迎大家一起學(xué)習(xí)研究相關(guān)技術(shù)愿意了解框架技術(shù)或者源碼的朋友直接加求求(企鵝):2042849237
更多詳細(xì)源碼參考來源:http://minglisoft.cn/technology