2015-06-03 2 views
5

Я хочу создать веб-сайт, отображающий форму. Поля формы зависят от параметра запроса (а также компонента бэк-формы). Это мой контроллер, который предоставляет различные формы:Как разместить общие объекты в контроллере Spring?

@Controller 
public class TestController { 

    @Autowired 
    private MyBeanRegistry registry; 

    @RequestMapping("/add/{name}") 
    public String showForm(@PathVariable String name, Model model) { 
     model.addAttribute("name", name); 
     model.addAttribute("bean", registry.lookup(name)); 

     return "add"; 
    } 

} 

Соответствующий вид выглядит следующим образом:

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> 
<head> 
</head> 
<body> 
    <form method="post" th:action="@{|/add/${name}|}" th:object="${bean}"> 
     <th:block th:replace="|${name}::fields|"></th:block> 
     <button type="submit">Submit</button> 
    </form> 
</body> 
</html> 

Ниже приведен пример фрагмента, который отображает поля формы:

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> 
<head> 
</head> 
<body> 
    <th:block th:fragment="fields"> 
     <label for="firstName">First name</label><br /> 
     <input type="text" id="firstName" th:field="*{firstName}" /><br /> 
     <label for="lastName">Last name</label><br /> 
     <input type="text" id="lastName" th:field="*{lastName}" /> 
    </th:block> 
</body> 
</html> 

Взглянув вверх по бобам будет выглядеть так:

public class MyExampleBean { 

    private String firstName; 

    private String lastName; 

    // Getters & setters 

} 

Форма отображается правильно, но как я могу получить форму обратно в контроллер? И как я могу проверить поданный компонент? Я попробовал следующий метод, но, очевидно он не может работать:

@RequestMapping(value = "/add/{name}", method = RequestMethod.POST) 
public String processForm(@PathVariable String name, @Valid Object bean) { 
    System.out.println(bean); 

    return "redirect:/add/" + name; 
} 

Spring создает новый экземпляр Object но представленные значения теряются. Итак, как я могу выполнить эту задачу?

+0

Похоже, проблема области видимости, есть параметр, чтобы сказать вы хотите объем сеанса для этой формы? –

+0

Я не задал рамки для формы. – stevecross

ответ

2

Если вы только хотели иметь дело с ограниченным числом бобов, вы могли бы ВГ e one @RequestMapping метод для каждого компонента, все делегирования частному методу, который сделает работу. Вы можете найти пример here.

Если вы хотите, чтобы иметь возможность принять боб динамически, вам придется делать вручную, что весна делает автомагически:

  • использовать только запрос, а не модель атрибута
  • найти компонент в реестре по имени PathVariable
  • сделать явно связывание

Но мы надеемся, Spring предлагает подлодку классы WebDataBinder как помощники:

@RequestMapping(value = "/add/{name}", method = RequestMethod.POST) 
public String processForm(@PathVariable String name, WebRequest request) { 
    //System.out.println(bean); 

    Object myBean = registry.lookup(name); 
    WebRequestDataBinder binder = new WebRequestDataBinder(myBean); 
    // optionnaly configure the binder 
    ... 
    // trigger actual binding of request parameters 
    binder.bind(request); 
    // optionally validate 
    binder.validate(); 
    // process binding results 
    BindingResult result = binder.getBindingResult(); 
    ... 

    return "redirect:/add/" + name; 
} 
+0

Спасибо. Второй подход работает очень хорошо, но как добавить подтверждение? Я добавил валидатор для своего объекта, используя 'binder.addValidators()'. Валидатор проверяет, являются ли 'firstName' и' lastName' из приведенного выше примера пустыми, используя 'ValidationUtils'. Когда я отправляю пустую форму и проверяю 'BindingResult', она говорит, что ошибок нет. – stevecross

+0

Я только что увидел, что мне нужно вызвать 'binder.validate()' после привязки. – stevecross

+0

Похоже, я забыл это ... Сообщение отредактировано –

0

Что касается проверки я не знаю, но для извлечения значения, вы можете попробовать ниже

(ВНИМАНИЕ: я не пробовал этот код, так как я не мог в момент написания) ,

Изменение processForm обработчика для обработки HttpServletRequest INSEAD типа Object, и получить sumbitted значения из карты paramters, пример:

@RequestMapping(value="/add/{name}", method=RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) 
public String processForm(@PathVariable String name, HttpServletRequest request) { 
    Map<String, String[]> parameterMap = request.getParameterMap(); 
    ... 
} 
0

Вы должны внести два изменения в свой код,

  1. Аннотировать свой TestController с @SessionAttributes("bean"), он сохранит ваш атрибут модели с именем bean, сохраненным в сеансе

  2. Добавить @ModelAttribute("bean") в ваш метод processForm, поэтому processForm(@PathVariable String name, @Valid @ModelAttribute("bean") Object bean). Как атрибут модели bean зарегистрирован как атрибут сеанса, а также он будет получать его из сессии, и будет держать значения

Если ваш метод processForm проживает в другом контроллере, убедитесь, аннотировать, что контроллер с @SessionAttributes("bean") а

Ниже следует пример рабочего контроллера

@SessionAttributes("bean") 
@Controller 
public class TestController { 

    @Autowired 
    private MyBeanRegistry registry; 

    @RequestMapping("/add/{name}") 
    public String showForm(@PathVariable String name, Model model) { 
     model.addAttribute("name", name); 
     model.addAttribute("bean", registry.lookup(name)); 

     return "add"; 
    } 

    @RequestMapping(value = "/add/{name}", method = RequestMethod.POST) 
    public String processForm(@PathVariable String name, @Valid @ModelAttribute("bean") Object bean) { 
     System.out.println(bean); 
     return "redirect:/add/" + name; 
    } 
} 
+0

Поражает цель создания приложений RESTful –

Смежные вопросы