@ModelAttribute аннотация, когда его использовать? - PullRequest
34 голосов
/ 31 декабря 2011

Допустим, у нас есть сущность Person, контроллер PersonController и страница edit.jsp (создание нового или редактирование существующего человека)

Контроллер

@RequestMapping(value = "/edit", method = RequestMethod.POST)
public String editPerson(@RequestParam("fname") String fname, Model model) {
    if(fname == null || fname.length() == 0){
        model.addAttribute("personToEditOrCreate", new Person());
    }
    else{
        Person p = personService.getPersonByFirstName(fname);
        model.addAttribute("personToEditOrCreate", p);
    }

    return "persons/edit";
}

@RequestMapping(value = "/save", method = RequestMethod.POST)
public String savePerson(Person person, BindingResult result) {

    personService.savePerson(person);
    return "redirect:/home";
}

edit.jsp

<form:form method="post" modelAttribute="personToEditOrCreate" action="save">
    <form:hidden path="id"/> 
    <table>
        <tr>
            <td><form:label path="firstName">First Name</form:label></td>
            <td><form:input path="firstName" /></td>
        </tr>
        <tr>
            <td><form:label path="lastName">Last Name</form:label></td>
            <td><form:input path="lastName" /></td>
        </tr>
        <tr>
            <td><form:label path="money">Money</form:label></td>
            <td><form:input path="money" /></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Add/Edit Person"/>
            </td>
        </tr>
    </table> 

</form:form>

Я пробую приведенный выше код (без использования аннотации @ModelAttribute в методе savePerson, и она работает правильно. Почему и когда мне нужно добавить аннотацию к объекту person:

@RequestMapping(value = "/save", method = RequestMethod.POST)
public String savePerson(@ModelAttribute("personToEditOrCreate") Person person, BindingResult result) {

    personService.savePerson(person);
    return "redirect:/home";
}

Ответы [ 3 ]

55 голосов
/ 13 ноября 2014

Вам не нужно @ModelAttribute ( параметр ) только для того, чтобы использовать Бин в качестве параметра

Например, эти методы-обработчики прекрасно работают с этими запросами:

@RequestMapping("/a")
void pathA(SomeBean someBean) {
  assertEquals("neil", someBean.getName());
}

GET /a?name=neil

@RequestMapping(value="/a", method=RequestMethod.POST)
void pathAPost(SomeBean someBean) {
  assertEquals("neil", someBean.getName());
}

POST /a
name=neil

Используйте @ModelAttribute ( метод ) для загрузки данных по умолчанию в вашу модель при каждом запросе - например, из базы данных, особенно при использовании @SessionAttributes.Это можно сделать в Controller или ControllerAdvice:

@Controller
@RequestMapping("/foos")
public class FooController {

  @ModelAttribute("foo")
  String getFoo() {
    return "bar";  // set modelMap["foo"] = "bar" on every request
  }

}

Любой JSP, перенаправленный на FooController:

${foo} //=bar

или

@ControllerAdvice
public class MyGlobalData {

  @ModelAttribute("foo")
  String getFoo() {
    return "bar";  // set modelMap["foo"] = "bar" on every request
  }

}

Любой JSP:

${foo} //=bar

Используйте @ModelAttribute ( параметр ), если вы хотите использовать результат @ModelAttribute ( method ) в качестве по умолчанию :

@ModelAttribute("attrib1")
SomeBean getSomeBean() {
  return new SomeBean("neil");  // set modelMap["attrib1"] = SomeBean("neil") on every request
}

@RequestMapping("/a")
void pathA(@ModelAttribute("attrib1") SomeBean someBean) {
  assertEquals("neil", someBean.getName());
}

GET /a

Используйте @ModelAttribute ( параметр ), чтобы получить объект, сохраненный в атрибуте flash :

@RequestMapping("/a")
String pathA(RedirectAttributes redirectAttributes) {
  redirectAttributes.addFlashAttribute("attrib1", new SomeBean("from flash"));
  return "redirect:/b";
}

@RequestMapping("/b")
void pathB(@ModelAttribute("attrib1") SomeBean someBean) {
  assertEquals("from flash", someBean.getName());
}

GET /a

Используйте @ModelAttribute ( параметр ), чтобы получить объект, хранящийся в @SessionAttributes

@Controller
@SessionAttributes("attrib1")
public class Controller1 {

    @RequestMapping("/a")
    void pathA(Model model) {
        model.addAttribute("attrib1", new SomeBean("neil")); //this ends up in session due to @SessionAttributes on controller
    }

    @RequestMapping("/b")
    void pathB(@ModelAttribute("attrib1") SomeBean someBean) {
        assertEquals("neil", someBean.getName());
    }
}

GET /a
GET /b
2 голосов
/ 31 декабря 2011

Ваш вопрос, кажется, уже получен ответ:

Что такое @ModelAttribute в Spring MVC?

Подводя итог ответу и сообщению в блоге: когда вы хотите, чтобы объект поддержки формы (экземпляр Person) сохранялся в запросах.

В противном случае, без аннотации метод сопоставления запросов будет предполагать, что Person является новым объектом и никоим образом не связан с вашим объектом поддержки формы. Кстати, пост в блоге, на который ссылается этот постер, действительно потрясающий, и его обязательно нужно прочитать.

0 голосов
/ 26 июля 2016

@ModelAttribute в аргументе метода указывает, что аргумент будет получен из модели. Если его нет в модели, сначала будет создан экземпляр аргумента, а затем добавлен в модель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...