在上一个Spring MVC表单处理示例中 ,我们应该使用SimpleFormController来处理单页表单提交,这非常简单明了。
但是,有时您可能需要处理“ 向导表单 ”,该向导表单需要将表单处理成多个页面,并要求用户逐页填写表单。 在此向导表单情况下,主要关注的是如何存储模型数据(用户填写的数据)并将其带到多个页面中?
SAbstractWizardFormController
幸运的是,Spring MVC附带了AbstractWizardFormController类,可以轻松处理此向导表单。 在本教程中,我们向您展示如何使用AbstractWizardFormController类在多个页面上存储和带来表单数据,应用验证并在最后一页显示表单数据。
1.向导表单页面
本演示共5页,按以下顺序工作:
[User] --> WelcomePage --> Page1 --> Page2 --> Page3 --> ResultPage
使用AbstractWizardFormController ,页面顺序由提交按钮的“名称”确定:
- _finish:完成向导表单。
- _cancel:取消向导窗体。
- _targetx:移至目标页面,其中x是从零开始的页面索引。 例如_target0 , _target1等。
1. WelcomePage.jsp
欢迎页面,带有用于启动向导表单过程的超链接。
<html>
<body>
<h2>Handling multipage forms in Spring MVC</h2>
Click here to start playing -
<a href="user.htm">AbstractWizardFormController example</a>
</body>
</html>
2. Page1Form.jsp
第1页,带有“用户名”文本框,显示错误消息(如果有),并包含2个提交按钮,其中:
- _target1 –移至第2页。
- _cancel –取消向导表单过程并将其移至“取消”页面
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<style>
.error {
color: #ff0000;
}
.errorblock {
color: #000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
</head>
<body>
<h2>Page1Form.jsp</h2>
<form:form method="POST" commandName="userForm">
<form:errors path="*" cssClass="errorblock" element="div" />
<table>
<tr>
<td>Username :</td>
<td><form:input path="userName" />
</td>
<td><form:errors path="userName" cssClass="error" />
</td>
</tr>
<tr>
<tr>
<td colspan="3"><input type="submit" value="Next"
name="_target1" /> <input type="submit" value="Cancel"
name="_cancel" /></td>
</tr>
</table>
</form:form>
</body>
</html>
3. Page2Form.jsp
第2页,带有“密码”字段,显示错误消息(如果有),并包含3个提交按钮,其中:
- _target0 –移至第1页。
- _target2 –移至第3页。
- _cancel –取消向导表单过程并将其移至“取消”页面
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<style>
.error {
color: #ff0000;
}
.errorblock {
color: #000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
</head>
<body>
<h2>Page2Form.jsp</h2>
<form:form method="POST" commandName="userForm">
<form:errors path="*" cssClass="errorblock" element="div" />
<table>
<tr>
<td>Password :</td>
<td><form:password path="password" />
</td>
<td><form:errors path="password" cssClass="error" />
</td>
</tr>
<tr>
<tr>
<td colspan="3"><input type="submit" value="Previous"
name="_target0" /> <input type="submit" value="Next"
name="_target2" /> <input type="submit" value="Cancel"
name="_cancel" /></td>
</tr>
</table>
</form:form>
</body>
</html>
4. Page3Form.jsp
第3页,带有“备注”文本框,显示错误消息(如果有),并包含3个提交按钮,其中:
- _target1 –移至第2页。
- _finish –完成向导表单处理并将其移至完成页面。
- _cancel –取消向导表单过程并将其移至“取消”页面。
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<style>
.error {
color: #ff0000;
}
.errorblock {
color: #000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
</head>
<body>
<h2>Page3Form.jsp</h2>
<form:form method="POST" commandName="userForm">
<form:errors path="*" cssClass="errorblock" element="div" />
<table>
<tr>
<td>Remark :</td>
<td><form:input path="remark" />
</td>
<td><form:errors path="remark" cssClass="error" />
</td>
</tr>
<tr>
<tr>
<td colspan="3"><input type="submit" value="Previous"
name="_target1" /> <input type="submit" value="Finish"
name="_finish" /> <input type="submit" value="Cancel"
name="_cancel" /></td>
</tr>
</table>
</form:form>
</body>
</html>
5. ResultForm.jsp
显示从前3页收集的所有表单数据。
<html>
<body>
<h2>ResultForm.jsp</h2>
<table>
<tr>
<td>UserName :</td>
<td>${user.userName}</td>
</tr>
<tr>
<td>Password :</td>
<td>${user.password}</td>
</tr>
<tr>
<td>Remark :</td>
<td>${user.remark}</td>
</tr>
</table>
</body>
</html>
2.型号
创建一个模型类来存储表单的数据。
文件:User.java
package com.mkyong.common.model;
public class User{
String userName;
String password;
String remark;
//getter and setter methods
}
3. AbstractWizardFormController
扩展AbstractWizardFormController ,只需重写以下方法
- processFinish –用户单击“ _finish ”名称的提交按钮时触发 。
- processCancel –用户单击名称为“ _cancel ”的提交按钮时触发 。
- formBackingObject –使用“用户”模型类将所有表单数据存储在多个页面中。
文件:UserController.java
package com.mkyong.common.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractWizardFormController;
import com.mkyong.common.model.User;
import com.mkyong.common.validator.UserValidator;
public class UserController extends AbstractWizardFormController{
public UserController(){
setCommandName("userForm");
}
@Override
protected Object formBackingObject(HttpServletRequest request)
throws Exception {
return new User();
}
@Override
protected ModelAndView processFinish(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
//Get the data from command object
User user = (User)command;
System.out.println(user);
//where is the finish page?
return new ModelAndView("ResultForm", "user", user);
}
@Override
protected ModelAndView processCancel(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
//where is the cancel page?
return new ModelAndView("WelcomePage");
}
}
一个简单的控制器,用于返回“ WelcomePage ”视图。
文件:WelcomeController.java
package com.mkyong.common.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class WelcomeController extends AbstractController{
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("WelcomePage");
}
}
4.多页/向导表单验证
在SimpleFormController
,创建一个验证器类,将所有验证逻辑放入validate()方法内,然后将验证器装饰性地注册到简单表单控制器。
但是,它在AbstractWizardFormController中有点不同。 首先,创建一个验证器类,以及每个页面的验证方法,如下所示:
档案:UserValidator.java
package com.mkyong.common.validator;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import com.mkyong.common.model.User;
public class UserValidator implements Validator{
@Override
public boolean supports(Class clazz) {
//just validate the User instances
return User.class.isAssignableFrom(clazz);
}
//validate page 1, userName
public void validatePage1Form(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName",
"required.userName", "Field name is required.");
}
//validate page 2, password
public void validatePage2Form(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password",
"required.password", "Field name is required.");
}
//validate page 3, remark
public void validatePage3Form(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "remark",
"required.remark", "Field name is required.");
}
@Override
public void validate(Object target, Errors errors) {
validatePage1Form(target, errors);
validatePage2Form(target, errors);
validatePage3Form(target, errors);
}
}
File:User.properties –用于存储错误消息的属性
required.userName = Username is required!
required.password = Password is required!
required.remark = Remark is required!
并且,在向导表单控制器( UserController.java
)中,通过手动调用验证器来覆盖validatePage() (不再像简单表单控制器那样声明)。
请参阅UserController.java的更新版本。
public class UserController extends AbstractWizardFormController{
//other methods, see above
@Override
protected void validatePage(Object command, Errors errors, int page) {
UserValidator validator = (UserValidator) getValidator();
//page is 0-indexed
switch (page) {
case 0: //if page 1 , go validate with validatePage1Form
validator.validatePage1Form(command, errors);
break;
case 1: //if page 2 , go validate with validatePage2Form
validator.validatePage2Form(command, errors);
break;
case 2: //if page 3 , go validate with validatePage3Form
validator.validatePage3Form(command, errors);
break;
}
}
}
在validatePage()方法中,使用“ switch ”函数确定正在调用的页面并将其与相应的验证器关联。 该页面的索引为0。
5.弹簧配置
声明向导表单控制器( UserController.java
),以正确的顺序放置所有页面并注册一个验证器。
<bean class="com.mkyong.common.controller.UserController" >
<property name="pages">
<list>
<!-- follow sequence -->
<value>Page1Form</value> <!-- page1, _target0 -->
<value>Page2Form</value> <!-- page2, _target1 -->
<value>Page3Form</value> <!-- page3, _target2 -->
</list>
</property>
<property name="validator">
<bean class="com.mkyong.common.validator.UserValidator" />
</property>
</bean>
注意
在“页面”属性中,列表值的顺序用于定义向导表单中页面的顺序。
查看完整示例:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean class="com.mkyong.common.controller.WelcomeController" />
<bean class="com.mkyong.common.controller.UserController" >
<property name="pages">
<list>
<!-- follow sequence -->
<value>Page1Form</value> <!-- page1 -->
<value>Page2Form</value> <!-- page2 -->
<value>Page3Form</value> <!-- page3 -->
</list>
</property>
<property name="validator">
<bean class="com.mkyong.common.validator.UserValidator" />
</property>
</bean>
<!-- Register User.properties for validation error message -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="User" />
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
5.演示
网址: http:// localhost:8080 / SpringMVC / welcome.htm
1. WelcomePage.jsp ,单击链接,移至Page1Form.jsp 。
2. Page1Form.jsp ,包含一个“用户名”文本框字段和两个按钮:
- “下一个”按钮–移至Page2Form.jsp。
- “取消”按钮–移至WelcomePage.jsp
如果在提交表单时“用户名”为空,则显示错误消息。
3. Page2Form.jsp ,包含一个“ password”字段和3个按钮:
- “上一个”按钮–移至Page1Form.jsp。
- “下一个”按钮–移至Page3Form.jsp。
- “取消”按钮–移至WelcomePage.jsp。
4. Page3Form.jsp ,包含一个“备注”文本框字段和3个按钮:
- “上一个”按钮–移至Page2Form.jsp。
- “完成”按钮–移至ResultForm.jsp。
- “取消”按钮–移至WelcomePage.jsp。
5. ResultForm.jsp ,显示所有表单数据。
下载源代码
下载它– SpringMVC-MultiPage-Form-Handling-Example.zip (12KB)
参考文献
翻译自: https://mkyong.com/spring-mvc/spring-mvc-handling-multipage-forms-with-abstractwizardformcontroller/