@Controller - более гибкий способ определения формы / мастера. Вы должны отобразить методы на запросы на основе запрошенного пути / параметров запроса / метода запроса. Таким образом, вместо определения списка представлений и обработки запроса на основе некоторого обязательного параметра «step», вы можете определять шаги вашего мастера по своему усмотрению (также объект команды будет обрабатываться более прозрачно). Вот как вы можете эмулировать классическую функциональность AWFC (это только пример, вы можете сделать гораздо больше).
@Controller
@RequestMapping("/wizard.form")
@SessionAttributes("command")
public class WizardController {
/**
* The default handler (page=0)
*/
@RequestMapping
public String getInitialPage(final ModelMap modelMap) {
// put your initial command
modelMap.addAttribute("command", new YourCommandClass());
// populate the model Map as needed
return "initialView";
}
/**
* First step handler (if you want to map each step individually to a method). You should probably either use this
* approach or the one below (mapping all pages to the same method and getting the page number as parameter).
*/
@RequestMapping(params = "_step=1")
public String processFirstStep(final @ModelAttribute("command") YourCommandClass command,
final Errors errors) {
// do something with command, errors, request, response,
// model map or whatever you include among the method
// parameters. See the documentation for @RequestMapping
// to get the full picture.
return "firstStepView";
}
/**
* Maybe you want to be provided with the _page parameter (in order to map the same method for all), as you have in
* AbstractWizardFormController.
*/
@RequestMapping(method = RequestMethod.POST)
public String processPage(@RequestParam("_page") final int currentPage,
final @ModelAttribute("command") YourCommandClass command,
final HttpServletResponse response) {
// do something based on page number
return pageViews[currentPage];
}
/**
* The successful finish step ('_finish' request param must be present)
*/
@RequestMapping(params = "_finish")
public String processFinish(final @ModelAttribute("command") YourCommandClass command,
final Errors errors,
final ModelMap modelMap,
final SessionStatus status) {
// some stuff
status.setComplete();
return "successView";
}
@RequestMapping(params = "_cancel")
public String processCancel(final HttpServletRequest request,
final HttpServletResponse response,
final SessionStatus status) {
status.setComplete();
return "canceledView";
}
}
Я пытался варьировать сигнатуры методов, чтобы вы могли получить представление о гибкости, о которой я говорил. Конечно, в этом есть намного больше: вы можете использовать метод запроса (GET или POST) в @RequestMapping
, вы можете определить метод с аннотацией @InitBinder
и т. Д.
РЕДАКТИРОВАТЬ: У меня был несопоставленный метод, который я исправил (кстати, вам нужно убедиться, что у вас нет неоднозначных сопоставлений - запросов, которые могут быть сопоставлены более чем одному методу) или несопоставленные запросы - запросы, которые не могут быть сопоставлены ни с каким методом). Также взгляните на @SessionAttributes, @SessionStatus и @ModelAttribute, которые также необходимы для полной имитации поведения классического AWFC (я уже редактировал код, чтобы прояснить это).