Spring MVC Vistas JSP

Spring MVC puede generar una gran variedad de vistas, entre ellas: HTML, PDF, XLS, RSS, JSP, JSON, XML, etc., estas son creadas usando diversas tecnologías, como: JSP, Thymeleaf, Velocity, FreeMarker, JasperReport, etc., en este tutorial veremos las vistas JSP utilizando JSTL, este no es un tutorial de ninguna de estas tecnologías, por lo que se recomienda que el lector tenga los conocimientos básicos de las mismas, lo que trataremos en este tutorial será la integración de estas tecnologías con Spring MVC.

Para utilizar una tecnología de vistas lo primero que debemos hacer es configurarla, para las vistas JSP requerimos un ViewResolver, este nos servirá para determinar el nombre y la ubicación del archivo que será usado para generar la vista.

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"carmelo.spring.controller"})
public class WebAppConfig {

    @Bean
    public ViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

Esta es nuestra configuración, ya la hemos visto en tutoriales anteriores, explicado brevemente, @Configuration indica que esta clase será usada para configuración, @EnableWebMvc habilita varios componentes Spring MVC de uso común, @ComponentScan escanea el paquete indicado en busca de nuestros controladores.

Nuestro ViewResolver es creado con la clase InternalResourceViewResolver usaremos los métodos setPrefix para indicar el directorio donde se encuentran los archivos y setSuffix indica la extensión de los mismos, se considera buena práctica guardar los archivos en la carpeta /WEB-INF/ ya que la misma no es un directorio público.

Recordemos que el controlador devuelve el nombre lógico de la vista, este será resuelto usando el ViewResolver, veamos algunos ejemplos:

Nombre lógico Archivo Físico
hello /WEB-INF/views/hello.jsp
product /WEB-INF/views/product.jsp
index /WEB-INF/views/index.jsp

JSP Standar Tag Library (JSTL) son un grupo estándar de etiquetas que nos facilitarán el trabajo a la hora de generar el contenido dinámico en las paginas .jsp, recordemos que para utilizar esta tecnología primero debemos incluir el namespace que utilizaremos, lo hacemos por medio de un directiva taglib, <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> , esta por ejemplo, añade las funcionalidades de uso común y accederemos a ellas a través del prefijo c.

Antes de comenzar a programar debemos agregar las dependencias requeridas para utilizar JSTL.

<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

Nuestro primer controlador lo llamaremos ProductController será el encargado de manejar los productos de nuestra base de datos, puedes obtener información detallada sobre la Integración Spring MVC con Spring Data JPA, la primera funcionalidad de este controlador será mostrar un listado de los productos presentes en la base de datos.

@Controller
public class ProductController {

    @Autowired
    private ProductService products;

    @RequestMapping("/product")
    public String productList(Model model) {
        model.addAttribute("productList", products.productList());
        return "product";
    }
}

El método productList obtiene la lista de productos y los almacena en el modelo, además retorna el nombre lógico de la vista, los controladores los vimos en el tutorial Spring MVC Controladores allí podrás la explicación pertinente, los detalles de la capa de datos los verás en el tutorial Acceso a datos con Spring MVC, este controlador invoca la vista /WEB-INF/views/product.jsp.

Este es el archivo .jsp utilizado para generar la vista, crearemos una tabla HTML en donde colocaremos todos los productos, usaremos JSTL para esta tarea.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Productos</title>
    </head>
    <body>
        <h1>Listado de Productos</h1>  
        <table border="1">
            <tr>
                <th style="width:  50px;">No</th>
                <th style="width: 250px;">Nombre</th>
                <th style="width: 150px;">Precio</th>
            </tr>
            <c:forEach var="product" 
                       items="${productList}"
                       varStatus="status">
                <tr>
                    <td><b>${status.index + 1}</b></td>
                    <td>${product.name}</td>
                    <td>${product.price}</td>
                </tr>
            </c:forEach>
        </table>
    </body>
</html>

Usando la etiqueta <c:forEach var="product" items="${productList}"> podemos recorrer cada uno de los elementos de una lista, en este caso la lista de productos que pasamos del controlador a la vista por medio del modelo, para acceder a ella usamos items="${productList}", var="product" crea una variable llamada product que hace referencia al producto actual en la iteración, podemos usar, por ejemplo, ${product.price} para obtener el precio de ese producto.

image

En una aplicación real el usuario no solo ve los datos, también, por lo general, debe poder manipularlos, de aquí en adelante le daremos a nuestro controlador la capacidad de realizar las operaciones CRUD sobre la tabla productos.

La primera operación será eliminar un producto, para ello usaremos @PathVariable para establecer el ID del producto que deseamos borrar, la URL: /webapp/product/delete/{id} donde {id} es el identificador numérico del producto, nos permitirá borrar dicho producto.

@RequestMapping("/product/delete/{id}")
public String productDelete(@PathVariable("id") Long id, Model model) {
    products.productDelete(id);
    return "redirect:/product";
}

Modificamos el archivo .jsp para agregar un enlace que nos lleve a la URL indicada para poder eliminar cada producto, ${pageContext.request.contextPath} obtiene la URL principal, en nuestro ejemplo, http://localhost:8084/webapp, a esta URL le concatenamos /product/delete/ seguido del ID de producto, obtenido con ${product.id}, esto da como resultado, por ejemplo, para un producto con ID = 111 la URL será: http://localhost:8084/webapp/delete/111.

<tr>
    <td><b>${status.index + 1}</b></td>
    <td>${product.name}</td>
    <td>${product.price}</td>
    <td><a href="${pageContext.request.contextPath}/product/delete/${product.id}">Borrar</a></td>
</tr>

El resultado en el navegador será el siguiente:

image

Si vemos el controlador, el mismo retorna la cadena redirect:/product de este modo luego de presionar sobre el enlace se elimina el producto y luego regresamos a la vista que muestra lista de productos.

Para agregar un producto tenemos los siguiente métodos, primero:

@RequestMapping("/product/form")
public String productForm(Model model) {
    model.addAttribute("product", new Product());
    return "productform";
}

Agregamos un producto con los datos por defecto al modelo, si deseamos podemos darle valores iniciales a las propiedades del objeto producto estos valores se reflejarán en la vista, para generar la vista usaremos el archivo productform.jsp, este contiene el formulario que nos permite ingresar los datos del nuevo producto.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Add Product</title>
    </head>
    <body>
        <h1>Agregar nuevo producto:</h1>
        <mvc:form modelAttribute="product" action="create">
            <table>
                <tr>
                    <td><mvc:label path="id">ID</mvc:label></td>
                    <td><mvc:input path="id"/></td>
                </tr>
                <tr>
                    <td><mvc:label path="name">Nombre</mvc:label></td>
                    <td><mvc:input path="name"/></td>
                </tr>
                <tr>
                    <td><mvc:label path="price">Precio</mvc:label></td>
                    <td><mvc:input path="price"/></td>
                </tr>
                <tr>
                    <td colspan="2">
                        <input type="submit" value="Enviar producto..."/>
                    </td>
                </tr>
            </table>
        </mvc:form>
    </body>
</html>

Usar formularios en  Spring MVC es fácil, el objeto Product que enviamos desde el controlador estará enlazado al formulario, de este modo cuando cambiamos los datos en los respectivos controles del formulario y presionemos el botón enviar, nuestro controlador recibirá el objeto actualizado con los datos ingresados por el usuario mediante el formulario.

<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>, con este taglib podemos utilizar los controles para formularios, en nuestro ejemplo solo usaremos mvc:input (crea un campo de entrada) y mvc:label (crea una etiqueta), para crear un formularios usamos <mvc:form modelAttribute="product" action="create"> donde modelAttibute vincula el objeto Product enviado a través del modelo a este formulario y action establece la URL a la que iremos al presionar el botón enviar, usando path, por ejemplo: <mvc:input path="price"/> vinculamos una propiedad del objeto al control input, de modo que el valor que introduzca el usuario en este campo será usado para establecer dicha propiedad.

@RequestMapping(value = "/product/create", method = RequestMethod.POST)
public String productCreate(@ModelAttribute("product") Product product) {
    products.productAdd(product);
    return "redirect:/product";
}

Este es el método requerido para recibir el objeto Product actualizado mediante el formulario, usaremos la anotación @ModelAttribute indicando el nombre de este objeto.

image

image

Para ir a la página que nos permite agregar un producto añadimos un enlace, este a sido creado así:

<a href="${pageContext.request.contextPath}/product/form">Agregar Producto</a>

Los formularios Spring MVC puede hacer muchas cosas interesantes, validar los datos de entrada, por ejemplo, por ello en el futuro dedicaremos uno o varios tutoriales a este tema.

Comentarios

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Acceso a la webcam con OpenCV

JavaFx 8 Administrar ventanas

Analizador Léxico