@ModelAttribute annotation, cuándo usarlo?

Digamos que tenemos una entidad Person, un controlador PersonController y una página edit.jsp (creando una nueva o editando una persona existente)

Controlador

@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

 
First Name
Last Name
Money

Estoy intentando el código anterior (sin utilizar la anotación @ModelAttribute en el método savePerson, y funciona correctamente. Por qué y cuándo debo agregar la anotación al objeto persona:

 @RequestMapping(value = "/save", method = RequestMethod.POST) public String savePerson(@ModelAttribute("personToEditOrCreate") Person person, BindingResult result) { personService.savePerson(person); return "redirect:/home"; } 

No necesita @ModelAttribute ( parámetro ) solo para usar un Bean como parámetro

Por ejemplo, estos métodos de manejo funcionan bien con estas solicitudes:

 @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 

Use @ModelAttribute ( método ) para cargar datos predeterminados en su modelo en cada solicitud, por ejemplo desde una base de datos, especialmente cuando usa @SessionAttributes . Esto se puede hacer en un Controller o en un ControllerAdvice :

 @Controller @RequestMapping("/foos") public class FooController { @ModelAttribute("foo") String getFoo() { return "bar"; // set modelMap["foo"] = "bar" on every request } } 

Cualquier JSP enviado por FooController :

 ${foo} //=bar 

o

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

Cualquier JSP:

 ${foo} //=bar 

Utilice @ModelAttribute ( parámetro ) si desea usar el resultado de @ModelAttribute ( método ) como valor predeterminado :

 @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 

Use @ModelAttribute ( parámetro ) para obtener un objeto almacenado en un atributo 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 

Use @ModelAttribute ( parámetro ) para obtener un objeto almacenado por @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 

Su pregunta parece haber sido respondida ya:

¿Qué es @ModelAttribute en Spring MVC?

Para resumir la respuesta y la publicación de blog: cuando desea que su objeto de respaldo de formulario (instancia de Persona) persista en todas las solicitudes.

De lo contrario, sin la anotación, el método mapeado de solicitud asumirá que Persona es un objeto nuevo y de ninguna manera está vinculado a su objeto de respaldo de formulario. La publicación de blog que el póster hace referencia es realmente impresionante, definitivamente una lectura obligada.

Un @ModelAttribute en un argumento de método indica que el argumento se recuperará del modelo. Si no está presente en el modelo, el argumento se instanciará primero y luego se agregará al modelo.