Contacto

Nos puedes enviar un artículo a publicar (si te fue útil, seguro que a otros también).
Nos puedes sugerir temas/profundidad de interés.
correo-e - perfil

Busquedas

Formulario con Spring MVC

 Vamos a modificar el proyecto anterior con spring mvc (Implementar Spring MVC) para incluir un formulario de ejemplo.
 Para esta tarea, vamos a crear nuestra propia clase que actúa como controller, que hereda de SimpleFormController. Usamos dos páginas (vistas), una encargada de mostrar el formulario, y otra para los resultados.

1) Primero modificar el archivo de configuración del servlet que funciona como Front Controller ( Dispatcher Servlet), en nuestro proyecto, el archivo: dispatcher-servlet.xml

1.1) Lo primero que indicamos en la configuración del 'Handler Mapping', cuál es la url del formulario, y el nombre del controlador responsable de manejar esa url. Para esto, se agrega la siguiente línea: <prop key="usuario.htm">usuController</prop>
 Básicamente, lo que estamos indicando en esta línea es: Las consultas a la url 'usuario.htm' redirigir al Controller con nombre: 'usuController'.

EL bloque completo de la configuración del HandlerMapping :
<bean id="urlMapping"  
 class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
   <property name="mappings">
      <props>
         <prop key="index.htm">indexController</prop>
        <prop key="usuario.htm">usuController</prop>
      </props>
   </property>
</bean>


1.2) Se tiene que agregar un bloque que mapea el nombre del controlador usado en el HandlerMapping (usuController), con la clase que implementa ese controlador.
  Aquí se también se configura cuál es la página (vista) inicial, y cual es la página a desplegar, cuando el procesamiento del formulario termine con éxito.
   Nota: En esta sección se configura la clase encargada de la validación. No lo hacemos ahora para dar más claridad al ejemplo.

<bean id="usuController" class="test.controller.UsuarioController" >
   <property name="formView" value="usuario"/>
   <property name="successView" value="resultadoUsuario" />
   <property name="commandClass" value="test.bean.Usuario"/>
   <property name="commandName" value="usuario"/>
</bean>

 Lo que estamos indicando en este bloque, es que el controlador del formulario, cuyo nombre (id) es 'usuController', se implementa en la clase 'test.controller.UsuarioController'.
 La vista inicial (propiedad 'formView'), tiene el nombre 'usuario', por lo que la página con el formulario es: usuario.jsp (ver la configuración de 'viewResolver' en el articulo anterior Implementar Spring MVC ).
 La vista final (propiedad 'successsView'), una vez que el contoller procesa correctamente el formulario, es 'resultadoUsuario' (resultadoUsuario.jsp).
 Mediante 'commandClass' se define la clase que es usada para almacenar los campos del formulario. Esta clase es inyectada en el controlador por spring.
 Por últino, 'commandName', es el nombre lógico con el que se accede desde la vista (por ejemplo, desde el formulario), a la clase definida en 'commandName'.

 3) Creamos la clase definida en 'commandClass' (clase Usuario.java, en el paquete 'test.bean'). Esta clase puede ser una clase común (POJO), con los atributos necesarios en las diferentes vistas, y los get's y set's correspondientes.
  Nota: En el siguiente código no se muestran los get/set, pero se tienen que incluir.
package test.bean;
/**
* @author dlix
*/
 public class Usuario {
   private String nombre;
   private String apellido;
   private String equipo;
@Override
   public String toString() {
    return "Nombre - " + nombre + " , Apellido - " + apellido + ", Equipo - " + equipo;
  }
          /* incluir getters y setters */
}

 4) Creamos el Controller, extendiendo la clase SimpleFormController.  Este controlador nos permite manejar de forma sencilla el ciclo de un formulario. 
 package test.controller;
  import java.util.HashMap;
  import java.util.Map;
  import javax.servlet.http.HttpServletRequest;
  import org.springframework.validation.BindException;
  import org.springframework.web.servlet.ModelAndView;
  import org.springframework.web.servlet.mvc.SimpleFormController;
  import test.bean.Usuario;
/**
* @author dlix
*/
public class UsuarioController extends SimpleFormController {
/* Si no se agrega commandClass en la configuración del servlet, se puede incluir
* en el constructor.
    public UsuarioController() {
      setCommandClass(Usuario.class);
      setCommandName("usuario");
    }
*/
  @Override
      protected ModelAndView onSubmit(Object command, BindException errors) throws Exception {
Usuario usuarioActual = (Usuario)command;
   /*
   * Incluir aquí código para manejo del formulario
   */
      // se prepara datos para la página final
   Map model = new HashMap();
   model.put("titulo", "Datos Ingresados en el Formulario");
   model.put(getCommandName(), usuarioActual);
    return new ModelAndView(getSuccessView(), model) ;
   }
}

  Cuando se genera un request con la url del formulario (usuario.htm), se envía el request a nuestro controlador. De ser necesario, se puede
hacer tareas previas a mostrar la página inicial (por ejemplo, iniciar variable / campo del formulario). Luego se muestra la página usuario.jsp
 

  Cuando se envía el formulario al servidor, se ejecuta el método onSubmit, que tiene como parámetro un objeto ('command'), que representa el formulario, en nuestro caso, el parámetro 'command' corresponde al objeto 'Usuario'. Spring es el encargado de inyectar el objeto, ingresando los datos de los atributos que corresponde a los campos de la página.
 El método retorna un objeto del tipo 'ModelAndView', el cual contiene un Map con los datos disponibles en la próxima página a mostrar, y el nombre lógico de la página que se tiene que desplegar.
 Los datos que hemos incluido en este Map son, el propio bean que representa el 'formulario' con la clave que retorna el método 'getCommandName()', y un String con la clave "titulo" y el valor "Datos Ingresados en el Formulario", el cuál incluimos con el propósito de mostrar como podemos agregar diferente información para ser enviada a la página.
 El nombre lógico se agrega por medio de 'getSuccessView()', que obtiene la vista que se había configurado en 'dispacher-servlet', en la propiedad 'successView' (la página 'resultadoUsuario.jsp').

 5) Tenemos que crear las vistas. Necesitamos 2 páginas, una con el formulario, y otra que será desplegada en caso de que el procesamiento del formulario no contenga errores. Estas páginas las incluimos en el directorio 'WEB-INF/jsp'
  Nota: Usamos un par de taglib que nos facilita la creación de las páginas, y el control de errores.

 5.1) La página con el formulario, usuario.jsp .
  Para generar el código html del formulario, usamos el tag de spring <from:from ...="">. en la propiedad commandName indicamos cual de los beans que pueden estar configurados en dispatcher-servlet (commandName - commandClass), se tiene que usar para los datos de éste formulario. Usamos la clase representada por 'usuario' (test.bean.Usuario).
  Las cajas de texto los implementamos con otro tag de spring, <form:input path="...">. Se indica con la propiedad 'path', el atributo dentro de la clase representada por 'commandName' en el formulario, donde se almacena / obtiene la información del input. En la clase 'commandClass' tiene que existir el atributo, con el get y set correspondiente.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@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=UTF-8">
<title>Form Usuario</title>
</head>
<body>
<h1>Ingresar datos</h1>
<form:form commandName="usuario" method="post">
Equipo de futbol preferido: <select name="equipo">
<option value="danubio">Danubio</option>
<option value="manya" selected="true">Manya</option>
<option value="defensor">Defensor</option>
</select><br />
Nombre:
<form:input title="Nombre" path="nombre"/><br/>
Apellido:
<form:input path="apellido"/><br />
<input type="submit" value="Enviar Datos">
</form:form>
</body>
</html>


 5.2) La página donde mostramos el resultado (en dispatcher-servlet, 'successView'), resultadoUsuario.jsp
   Para mostrar los datos del Model que se agrego en el Controller, usamos ${keyDelMap}.
  En particular, con la clave 'usuario', se insertó la clase Usuario, por lo que accedemos a sus atributos de la forma: 'usuario.nombreAtributo'
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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=UTF-8">
<title>Resultado del Formulario</title>
</head>
<body>
<h1> ${titulo}</h1>
Nombre: ${usuario.nombre} <br/>
Apellido: ${usuario.apellido} <br/>
Equipo de Futbol: ${usuario.equipo}<br/>
Datos en toString(): ${usuario}
</body>
</html>


  Ya podemos ejecutar el proyecto web, e ingresar a la url usuario.htm (en mi caso, http://localhost:8084/TestSpring/usuario.htm). Como juego de datos podemos seleccionar:
   Equipo de futbol preferido: Manya
   Nombre: dlix
   Apellido: apellDLix


  En la página de resultado, para ese juego de datos podemos ver:
    Datos Ingresados en el Formulario
    Nombre: dlix
    Apellido: apellDLix
    Equipo de Futbol: manya
    Datos en toString(): Nombre - dlix , Apellido - apellDLix, Equipo - manya


  Queda pendiente validar el formulario, y el código con el ejemplo disponible para bajar.
(en el siguiente articulo, estos dos pendientes resueltos ;-): Validar datos de formulario con Spring mvc)

4 comentarios:

Txumari dijo...

Tengo un problema con estos formularios acabo de empezar con spring y no se muy bien como arreglarlo.

He visto tu tutorial que se entiende todo muy bien y lo tengo to igual, el problema viene de que la ruta del atributo action (commandName="usuario") se convierte en la ruta de las vistas proyecto/web-inf/jsp/nombreVista.jsp y no deberia poner esa ruta. si no que deberia ser proyecto/nombreVista.jsp
Espero que se entienda mi problema.

Muchas gracias de antemano.

dlix dijo...

Hola Txumari.
Creo haber entendido ... en parte :). Dos posibles problemas:
1) En cuanto al atributo del formulario en la página 'commandName="usuario"', hace referencia a la clase donde se almacenan los datos que se ingresen en el formulario. En el ejemplo de este artículo es la clase: "test.bean.Usuario.java". Y esto es parte de la configuración dispatcher-servlet.xml

La confusión aquí puede ser que yo usé el mismo nombre lógico para la vista ( name="formView" value="usuario" que mapea con usuario.jsp) y para el commandName ( name="commandName" value="usuario" que mapea con Usuario.java), pero son cosas diferentes (mi culpa, y lo tendré presente en otros artículos).

2) Por las rutas de las vistas que indicas, puede ser que quieras tener tus páginas (vistas) en la raíz del proyecto. Esto en el ejemplo se configura en el archivo dispatcher-servlet.xml, en 'bean id="viewResolver"' en la propiedad "prefix". Mira que aquí hemos indicado que busque las páginas en "/WEB-INF/jsp/". Para que las busque en la raíz del proyecto, simplemente cambia aquí la propiedad (p:prefix="/").
Es recomendable que las páginas estén dentro del directorio "WEB-INF", ya que los usuarios no pueden acceder directamente a estas páginas, y de esta forma se mantiene el control, por ej., de la navegabilidad.

Ahora espero yo que estén claras las explicaciones ... y que alguna resuelva el problema.
Si quieres puedes contactarme directamente a mi correo (esta en el perfil), y puedes mandarme el código, si puedo busco el problema.
salu2

Unknown dijo...

Gracias por el Tutorial :D

Algun forma de contactarte ?

dlix dijo...

En el perfil está el correo de contacto (tienes que tener javascript activado). Gracias por pasar ;-)