高級用戶註冊需收集大量信息,單頁「超級表單」會嚇退用戶。向導式分步表單可降低心理負擔,但傳統 MVC 框架需自行處理前進/後退/取消、分步驗證、數據保持等複雜流程。Spring MVC 的 AbstractWizardFormController 內建完整向導工作流,開發者僅需擴展關鍵方法即可快速構建強大向導。
public class FullUserRegisterController extends AbstractWizardFormController {
private String cancelView, successView;
private BbtForum bbtForum;
// 必須實現:完成向導後的業務處理
protected ModelAndView processFinish(HttpServletRequest req, HttpServletResponse res,
Object command, BindException errors) throws Exception {
FullUser user = (FullUser) command;
bbtForum.registerFullUser(user);
return new ModelAndView(getSuccessView(), "fullUser", user);
}
// 可選:取消向導處理
protected ModelAndView processCancel(HttpServletRequest req, HttpServletResponse res,
Object command, BindException errors) throws Exception {
return new ModelAndView(getCancelView());
}
// getter/setter 省略
}
<bean name="/fullRegisterUser.html" class="com.baobaotao.web.user.FullUserRegisterController">
<property name="bbtForum" ref="bbtForum"/>
<property name="commandClass" value="com.baobaotao.domain.FullUser"/>
<property name="pages" value="fullRegister,relation,favorite"/>
<property name="cancelView" value="main"/>
<property name="successView" value="welcome"/>
<property name="validator">
<bean class="com.baobaotao.domain.FullUserValidator"/>
</property>
</bean>
pages 定義向導頁面順序(索引 0,1,2),cancelView/successView 為邏輯視圖名。
getTargetPage() 根據請求參數 _target{index} 決定跳轉頁面。在 JSP 中構造按鈕:
<!-- relation.jsp (索引1) -->
<input type="submit" name="_target0" value="上一步"/> <!-- 回到 fullRegister -->
<input type="submit" name="_target2" value="下一步"/> <!-- 進入 favorite -->
<!-- favorite.jsp (索引2,最後一步) -->
<input type="submit" name="_target1" value="上一步"/>
<input type="submit" name="_finish" value="確定"/> <!-- 觸發 processFinish -->
<input type="submit" name="_cancel" value="取消"/> <!-- 觸發 processCancel -->
避免過早驗證(屬性尚未收集)或過晚驗證(錯誤頁面跨度大),必須在 validatePage() 中按頁面索引分步驗證:
public class FullUserValidator implements Validator {
public boolean supports(Class clazz) { return clazz.equals(FullUser.class); }
public void validate(Object cmd, Errors errors) { /* 完整驗證 */ }
public void validateStep1(Object cmd, Errors errors) { /* 第1步:用戶名/密碼/Email */ }
public void validateStep2(Object cmd, Errors errors) { /* 第2步:地址/電話 */ }
}
protected void validatePage(Object command, Errors errors, int page, boolean finish) {
FullUserValidator v = (FullUserValidator) getValidator();
if (page == 0) v.validateStep1(command, errors);
else if (page == 1) v.validateStep2(command, errors);
else if (finish) v.validate(command, errors); // 最後提交全量驗證
}