向導式表單 (向導 1 → 向導 2 → ... → 完成) 是複雜業務數據收集的標準交互模式。Spring MVC 提供 AbstractWizardFormController 內置支援多頁面流轉、逐頁驗證、取消/完成處理,本文以簡歷向導為例完整演示配置與實現。
規則:必填項非空驗證,「下一步」驗證當前頁,「上一步」不阻攔但仍驗證,「取消」中斷流程,「完成」提交全部數據。
package com.unmi.bean;
public class Resume {
private String workPlace; // 期望地點
private int salary; // 期望薪資
private String name; // 姓名
private String mobile; // 手機
private String experience; // 工作經歷
private String projects; // 項目經驗
// getter/setter 略
}
package com.unmi.webapp.controller;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractWizardFormController;
import com.unmi.bean.Resume;
public class ResumeWizardController extends AbstractWizardFormController {
public ResumeWizardController() {
setCommandClass(Resume.class);
}
// 完成提交處理
@Override
protected ModelAndView processFinish(HttpServletRequest request,
HttpServletResponse response,
Object command, BindException errors) {
Resume resume = (Resume) command;
// resumeService.submitResume(resume);
return new ModelAndView("congratulations"); // 邏輯視圖名
}
// 逐頁驗證
@Override
protected void validatePage(Object command, Errors errors, int page) {
ResumeValidator validator = (ResumeValidator) getValidator();
Resume resume = (Resume) command;
switch (page) {
case 0: // 求職意向
validator.validateWorkPlace("workPlace", errors);
break;
case 1: // 基本信息
validator.validateName("name", errors);
validator.validateMobile("mobile", errors);
break;
// 頁 2、3 (經歷/項目) 無必填驗證
}
}
}
<beans>
<bean name="/createResume.html" class="com.unmi.webapp.controller.ResumeWizardController">
<property name="pages">
<list>
<value>intention</value> <!-- page 0 -->
<value>baseinfo</value> <-- page 1 -->
<value>experience</value> <-- page 2 -->
<value>projects</value> <-- page 3 -->
<value>congratulations</value> <-- page 4 (完成頁) -->
</list>
</property>
<property name="validator">
<bean class="com.unmi.webapp.validator.ResumeValidator"/>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/resume/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
視圖解析:intention → /resume/intention.jsp 等。
<form:form action="/createResume.html" method="post" commandName="command">
<!-- 頁面特定字段 -->
<form:input path="workPlace"/>
<form:errors path="workPlace" cssClass="error"/>
<!-- 導航按鈕 (關鍵命名規範) -->
<input type="submit" name="_target0" value="上一步"/> <!-- 目標頁索引 0 -->
<input type="submit" name="_target2" value="下一步"/> <!-- 目標頁索引 2 -->
<input type="submit" name="_finish" value="完成"/>
<input type="submit" name="_cancel" value="取消"/>
</form:form>
| 參數名 | 觸發動作 | 說明 |
|---|---|---|
_target{index} | 跳轉到指定頁面索引 | 「上一步」_target0、「下一步」_target{current+1} |
_finish | 調用 processFinish() | 最終提交,會先觸發當前頁驗證 |
_cancel | 調用 processCancel() | 中斷向導,可覆寫做清理 |
package com.unmi.webapp.validator;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import com.unmi.bean.Resume;
public class ResumeValidator implements Validator {
@Override
public boolean supports(Class> clazz) { return Resume.class.equals(clazz); }
@Override
public void validate(Object target, Errors errors) {
// 標準 validate() 不會被 AbstractWizardFormController 自動調用
// 可在 validatePage(page, true) 中手動調用
}
public void validateWorkPlace(String field, Errors errors) {
// 從資源文件讀取錯誤碼
ValidationUtils.rejectIfEmptyOrWhitespace(errors, field, "resume.workPlace.required");
}
public void validateName(String field, Errors errors) { ... }
public void validateMobile(String field, Errors errors) { ... }
}
// 版本一:簡單逐頁驗證 (最常用)
protected void validatePage(Object command, Errors errors, int page) { ... }
// 版本二:完成時額外驗證 (含 finish 標誌)
protected void validatePage(Object command, Errors errors, int page, boolean finish) {
validatePage(command, errors, page);
if (finish) {
// 跨頁一致性檢查,如日期邏輯、金額平衡
// validator.validate(command, errors); // 調用標準 validate()
}
}

包含源碼、JAR、國際化資源文件:SpringWizardForm.rar
注意:Spring 3.0+ 推薦使用
@Controller+@SessionAttributes+ 手動狀態機實現向導,AbstractWizardFormController已標記過時。本文方案適用於 Spring 2.x 維護項目或理解向導控制器核心協議 (_target/_finish/_cancel、逐頁驗證、Session 狀態保持) 的教學場景。