Spring MVC обрабатывает многостраничные формы с помощью AbstractWizardFormController
В последнемSpring MVC form handling example мы должны использоватьSimpleFormController для обработки отправки одностраничной формы, что довольно просто и легко.
Но, иногда, вам может понадобиться иметь дело с «wizard form», для которого нужно обрабатывать форму на несколько страниц и просить пользователя заполнять форму постранично. Основная проблема в этой ситуации в форме мастера - как сохранить данные модели (данные, заполненные пользователем) и перенести их на несколько страниц?
SAbstractWizardFormController
К счастью, Spring MVC поставляется с классомAbstractWizardFormController, чтобы легко обрабатывать эту форму мастера. В этом руководстве мы покажем вам, как использовать классAbstractWizardFormController для хранения и переноса данных формы на несколько страниц, применения проверки и отображения данных формы на последней странице.
1. Страницы форм мастера
5 страниц для этой демонстрации, работают в следующих последовательностях:
[User] --> WelcomePage --> Page1 --> Page2 --> Page3 --> ResultPage
СAbstractWizardFormController последовательность страниц определяется «именем» кнопки отправки:
-
_finish: завершить форму мастера.
-
_cancel: отменить форму мастера.
-
_targetx: перейти на целевую страницу, где x - это нулевой индекс страницы. e.g _target0, _target1 and etc.
1. WelcomePage.jsp
Страница приветствия с гиперссылкой для запуска процесса формы мастера.
Handling multipage forms in Spring MVC
Click here to start playing -
AbstractWizardFormController example
2. Page1Form.jsp
Страница 1, с текстовым полем «имя пользователя», отображает сообщение об ошибке, если таковое имеется, и содержит 2 кнопки отправки, где:
-
_target1 - перейти на страницу 2.
-
_cancel - отменить процесс формы мастера и переместить его на страницу отмены
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
Page1Form.jsp
Username :
3. Page2Form.jsp
Страница 2, с полем «пароль», отображает сообщение об ошибке, если таковое имеется, и содержит 3 кнопки отправки, где:
-
_target0 - перейти на страницу 1.
-
_target2 - перейти на страницу 3.
-
_cancel - отменить процесс формы мастера и переместить его на страницу отмены
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
Page2Form.jsp
Password :
4. Page3Form.jsp
Страница 3, с текстовым полем «примечание», выводит сообщение об ошибке, если таковое имеется, и содержит 3 кнопки отправки, где:
-
_target1 - перейти на страницу 2.
-
_finish - завершить процесс формы мастера и переместить его на конечную страницу.
-
_cancel - отменить процесс формы мастера и переместить его на страницу отмены.
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
Page3Form.jsp
Remark :
5. ResultForm.jsp
Отображение всех данных формы, собранных с предыдущих 3 страниц.
ResultForm.jsp
| UserName : | ${user.userName} |
| Password : | ${user.password} |
| Remark : | ${user.remark} |
2. модель
Создайте класс модели для хранения данных формы.
Файл: User.java
package com.example.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.example.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.example.common.model.User;
import com.example.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.example.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.example.common.validator;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import com.example.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), разместите все страницы в правильном порядке и зарегистрируйте валидатор.
Page1Form Page2Form Page3Form
Note
В свойстве «pages» порядок значений списка используется для определения последовательности страниц в форме мастера.
Смотрите полный пример:
Page1Form Page2Form Page3Form /WEB-INF/pages/ .jsp
5. Demo
1. WelcomePage.jsp, щелкните ссылку, перейдите кPage1Form.jsp.

2. Page1Form.jsp, содержит поле текстового поля «имя пользователя» и 2 кнопки:
-
Кнопка «Далее» - перейти к Page2Form.jsp.
-
Кнопка «отмена» - перейти на WelcomePage.jsp

Если при отправке формы имя пользователя пусто, отобразите сообщение об ошибке.

3. Page2Form.jsp, содержит поле «пароль» и 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 (12 КБ)