Spring MVC y la anotación @ModelAttribute

1. Información general

Una de las anotaciones Spring-MVC más importantes es la anotación @ModelAttribute.

El @ModelAttribute es una anotación que se une a un parámetro del método o el valor de retorno del método a un atributo de modelo llamada y luego lo expone a una vista web.

En el siguiente ejemplo, demostraremos la usabilidad y funcionalidad de la anotación, a través de un concepto común: un formulario enviado por un empleado de una empresa.

2. El @ModelAttribute en profundidad

Como reveló el párrafo introductorio, @ModelAttribute se puede usar como parámetro de método o a nivel de método.

2.1 A nivel de método

Cuando la anotación se usa a nivel de método, indica que el propósito de ese método es agregar uno o más atributos del modelo. Dichos métodos admiten los mismos tipos de argumentos que los métodos @RequestMapping, pero no se pueden asignar directamente a las solicitudes.

Echemos un vistazo a un ejemplo rápido aquí para comenzar a comprender cómo funciona esto:

@ModelAttribute public void addAttributes(Model model) { model.addAttribute("msg", "Welcome to the Netherlands!"); } 

En el ejemplo, mostramos un método que agrega un atributo llamado msg a todos los modelos definidos en la clase del controlador.

Por supuesto, veremos esto en acción más adelante en el artículo.

En general, Spring-MVC siempre hará una llamada primero a ese método, antes de llamar a cualquier método de manejo de solicitudes. Es decir, los métodos @ModelAttribute se invocan antes de que se invoquen los métodos del controlador anotados con @RequestMapping . La lógica detrás de la secuencia es que, el objeto modelo debe crearse antes de que comience cualquier procesamiento dentro de los métodos del controlador.

También es importante que anote la clase respectiva como @ControllerAdvice. Por lo tanto, puede agregar valores en Modelo que se identificarán como globales. En realidad, esto significa que para cada solicitud existe un valor predeterminado, para cada método en la parte de respuesta.

2.2 Como argumento de método

Cuando se usa como argumento de método, indica que el argumento debe recuperarse del modelo. Cuando no está presente, primero debe instanciarse y luego agregarse al modelo y, una vez presente en el modelo, los campos de argumentos deben completarse a partir de todos los parámetros de solicitud que tienen nombres coincidentes.

En el fragmento de código que sigue, el atributo del modelo de empleado se completa con datos de un formulario enviado al extremo addEmployee . Spring MVC hace esto detrás de escena antes de invocar el método de envío:

@RequestMapping(value = "/addEmployee", method = RequestMethod.POST) public String submit(@ModelAttribute("employee") Employee employee) { // Code that uses the employee object return "employeeView"; }

Más adelante en este artículo veremos un ejemplo completo de cómo usar el objeto employee para completar la plantilla employeeView .

Entonces, enlaza los datos del formulario con un bean. El controlador anotado con @RequestMapping puede tener argumentos de clase personalizados anotados con @ModelAttribute .

Esto es lo que comúnmente se conoce como enlace de datos en Spring-MVC, un mecanismo común que le evita tener que analizar cada campo de formulario individualmente.

3. Ejemplo de formulario

En esta sección, proporcionaremos el ejemplo al que se hace referencia en la sección de descripción general: un formulario muy básico que solicita a un usuario (empleado de una empresa, en nuestro ejemplo específico) que ingrese alguna información personal (específicamente nombre e identificación). Una vez completado el envío y sin ningún error, el usuario espera ver los datos enviados anteriormente, que se muestran en otra pantalla.

3.1 La vista

Primero creemos un formulario simple con campos de identificación y nombre:

 Name  Id    

3.2 El controlador

Aquí está la clase de controlador, donde se implementa la lógica para la vista mencionada anteriormente:

@Controller @ControllerAdvice public class EmployeeController { private Map employeeMap = new HashMap(); @RequestMapping(value = "/addEmployee", method = RequestMethod.POST) public String submit( @ModelAttribute("employee") Employee employee, BindingResult result, ModelMap model) { if (result.hasErrors()) { return "error"; } model.addAttribute("name", employee.getName()); model.addAttribute("id", employee.getId()); employeeMap.put(employee.getId(), employee); return "employeeView"; } @ModelAttribute public void addAttributes(Model model) { model.addAttribute("msg", "Welcome to the Netherlands!"); } }

En el método submit () tenemos un objeto Empleado vinculado a nuestra Vista . ¿Puedes ver el poder de esta anotación? Puede mapear sus campos de formulario a un modelo de objetos tan simplemente como eso. En el método, estamos obteniendo valores del formulario y configurándolos en ModelMap .

Al final, devolvemos employeeView , lo que significa que el archivo JSP respectivo se llamará como representante de View .

Además, también existe un método addAttributes () . Su propósito es agregar valores en el Modelo que serán identificados globalmente. Es decir, se devolverá un valor predeterminado como respuesta para cada solicitud a cada método de controlador. También tenemos que anotar la clase específica como @ControllerAdvice .

3.3 El modelo

Como se mencionó anteriormente, el objeto Model es muy simplista y contiene todo lo que requieren los atributos "front-end". Ahora, echemos un vistazo a un ejemplo:

@XmlRootElement public class Employee { private long id; private String name; public Employee(long id, String name) { this.id = id; this.name = name; } // standard getters and setters removed }

3.4 Conclusión

El @ControllerAdvice ayuda a un controlador y, en particular, a los métodos @ModelAttribute que se aplican a todos los métodos @RequestMapping . Por supuesto, nuestro método addAttributes () será el primero en ejecutarse, antes que el resto de los métodos @RequestMapping .

Teniendo esto en cuenta y después de ejecutar submit () y addAttributes () , podríamos referirnos a ellos en la Vista devuelta de la clase Controller , mencionando su nombre de pila dentro de un dúo de llaves dolarizadas, como por ejemplo $ {nombre} .

3.5 Vista de resultados

Imprimamos ahora lo que recibimos del formulario:

${msg}

Name : ${name} ID : ${id}

4. Conclusión

En este tutorial investigamos el uso de la anotación @ModelAttribute , tanto para argumentos de método como para casos de uso de nivel de método .

La implementación de este sencillo tutorial se puede encontrar en el proyecto github.