Cada día se usa más Spring MVC como framework de capa de presentación. Con los años se ha pasado de un modelo MVC con fuerte uso de ficheros XML a un modelo en el que priman las anotaciones. Una de las anotaciones más habituales es Spring MVC @ModelAttribute que nos permite realizar un binding de los datos que tenemos en un formulario de Spring con la capa de backend.
@ModelAttribute
Supongamos que tenemos un Controller en Spring MVC con dos métodos que mapean URLs (formularioPersona y verPersona)
package com.arquitecturajava.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import com.arquitecturajava.negocio.Persona; @Controller public class PersonaController { @RequestMapping(value ="/verPersona") public String enviar(Persona persona) { return "verPersona"; } @RequestMapping(value="/formularioPersona") public String formularioPersona(@ModelAttribute("persona") Persona persona) { return "formularioPersona"; } }
Como se puede observar la url de /formularioPersona asignará un objeto Persona al Modelo utilizando la anotación @ModelAttribute. Este objeto Persona será inicializado con los valores por defecto. El siguiente paso será ligar la Persona a los campos del formulario.
Para realizar esta operación se utilizan las librerías de etiquetas de Spring MVC.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <form:form modelAttribute="persona" action="verPersona.do" method="post"> Nombre:<form:input id="nombre" path="nombre" /> Edad:<form:input id="edad" path="edad" /> <form:button value="enviar" >enviar</form:button> </form:form> </body> </html>
Como se puede observar es suficiente con definir el atributo “modelAttribute” en el formulario y asignar el objeto Persona. Al solicitar la URL el framework nos mostrará el formulario con los datos a rellenar.
De esta forma quedan completamente ligadas ambas partes. Al rellenar el formulario y pulsar sobre el botón de enviar se ejecutará el mapeo de “/verPersona”.Este mapeo como se puede observar inyecta un objeto Persona al método “enviar” . Este objeto contendrá los datos que hemos rellenado en el formulario.
Recibida esta información los datos serán pasados a la página “verPersona” que nos mostrará la información
Para mostrar la información correctamente usaremos Expression Language:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> ${persona.nombre} ${persona.edad} </body> </html>
Spring aporta muchas facilidades a la hora de trabajar con el clásico modelo MVC
Otros artículos relacionados:
Hola. En el caso de usar una superclase llamada Oferta y tres subclases Vuelo, Hotel, Alquiler. Cuando todos los métodos que hemos creado apuntan de algún modo a Oferta como parámetro (los que lo tengan), como podemos crear un objeto Vuelo (el formulario tenía todos los campos para crear Vuelo) a partir de el objeto que contiene los datos del formulario siendo de tipo Oferta? @RequestMapping(value=”/add/{tipo}”, method=RequestMethod.POST) public String addOfertaForm(@PathVariable(“tipo”) String tipo, @ModelAttribute(“newOferta”) Oferta newOferta){ if(tipo.equals(“Vuelo”)){ newOferta= new Vuelo(); }else if(tipo.equals(“Hotel”)){ newOferta= new Hotel(); }else{ newOferta= new Alquiler(); } xolloService.addXollo(newXollo); return “redirect:/”; } No sé como puedo… Read more »
Hola.
Querría hacer una pregunta relacionada con los Formularios de Spring mvc. Si tenemos una clase bean y se va a usar como modelAttribute para un formulario web. ¿Como trabajar si dicho bean tiene un atributo que es otro bean? Vea la entidad abajo.
¿En el jsp como se trabajaría con dicho atributo que no es dato primitivo?
@Entity
public class Rol implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long idPersona;
private String nombre;
private String apellidos;
private String telefono;
@ManyToOne
@JoinColumn(name="idDireccion")
private Direccion direccion;
Quizás sería mejor generar un ViewModel como si fuera un DTO con la estructura de la vista
Buenas, no me queda del todo claro, te referís a esto :
@RequestMapping(value =”/verPersona”)
public String enviar(Persona persona) {
return “verPersona”;
}
debe ser así?
@RequestMapping(value =”/verPersona”)
public String enviar(@ModelAttribute(“persona”) Persona persona) {
return “verPersona”;
}
Las dos opciones son validas
Hola Cecilio, te faltaria poner @ModelAttribute(“persona”) por que sino daria una excepcion
gracias 🙂
Un saludo Cecilio, como haría cuando por ejemplo un campo de la clase Persona es un objeto propio, por ejemplo una clase Direcciòn que a su vez tendría calle, casa, num. de casa, etc.
public class Persona {
String nombre;
int edad;
Direccion direccion;
}
public class Direccion {
String calle;
String casa;
int numCasa;
}
No tengo claro que este soportado por la anotación un workaround sería pasar dos model atributes con direccion uno y otro con persona y luego usar el método setDireccion de persona para relacionarlo. Es lo que primero se me ocurre 🙂
Un saludo
Tal vez esta respuesta llegue tarde para Jose O. pero se que para algunos ayudara me tope con le mismo problema y lo resolvi poniendo el nombre del objeto compuesto seguido de un punto y el atributo ejemplo:
${persona.direccion.calle} ó ${direccion.calle}
¿Para qué sirve el Model en el Spring MVC?
Es la parte que carga los datos que vienen de los servicios