Spring BOOT: integración con JSP

logo spring

Jakarta Server Pages (JSP), antes conocida como Java Server Pages, es la tecnología de generación dinámica de páginas web que Java propone como estándar o especificación. A día de hoy se puede considerar un vestigio del pasado, pues hace años que contamos con motores de plantillas tales como Thymeleaf que ofrecen mejores capacidades. Además, la tendencia actual es la creación de clientes JavaScript, con Angular, React y similares, que interactúan con APIs REST.

>> Read this post in English here <<

No obstante, puesto que le tengo cierto cariño —recuerdos de juventud— en este tutorial exprés voy a crear una aplicación Spring Boot que muestra una página web generada con JSP.

Si recién empiezas con Spring Boot, te recomiendo que antes eches un vistazo a este tutorial.

Comencemos añadiendo al fichero pom el iniciador (starter) spring-boot-starter-web:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>   
</dependency>

JSP requiere la dependencia del lenguaje JSTL, basado en etiquetas (Jakarta Standard Tag Library):

<dependency>
	<groupId>org.glassfish.web</groupId>
	<artifactId>jakarta.servlet.jsp.jstl</artifactId>
</dependency>

También precisa un motor de compilación porque cada fichero JSP se transforma en un servlet (*) que será compilado.

<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
  <scope>provided</scope>
</dependency>

(*) Los servlets son clases Java que procesan peticiones y respuestas HTTP.

En el fichero de configuración application.properties definimos el prefijo y sufijo de los ficheros .jsp. El primero es la ruta en la que se ubican dentro de la carpeta /src/main/webapp y el segundo la extensión.

spring.mvc.view.prefix= /WEB-INF/jsp/
spring.mvc.view.suffix= .jsp

La siguiente clase representa a la aplicación. Está anotada con @SpringBootApplication y contiene un método main que arranca Spring:

@SpringBootApplication
public class SpringBootJspApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootJspApplication.class, args);
	}

}

Ya está lista la infraestructura. Ahora vamos a escribir una clase especial denominada «controlador» con métodos que serán invocados cuando llamemos a ciertas direcciones vía HTTP:

@Controller
public class CountriesController {

    @RequestMapping("/")
    public String list(Model model) {
        model.addAttribute("countriesList", buildCountriesList());
        return "countriesList";
    }

    private List<Country> buildCountriesList() {
        List<Country> countries = new ArrayList<>();

        countries.add(new Country("Mexico", 130497248));
        countries.add(new Country("Spain", 49067981));
        countries.add(new Country("Colombia", 46070146));

        return countries;
    }

Hay mucho que explicar. Anotamos nuestra clase controladora con @Controller. @RequestMapping indica la url a la que atenderá el método marcado con ella. Al ser la raíz de la aplicación («/»), podríamos omitirla. Opcionalmente, podemos restringir el verbo HTTP (GET, POST, PUT…) que maneja el método. Si no se especifica, se atenderán todos. Varios métodos pueden atender la misma url siempre y cuando cada uno procese un verbo distinto.

@RequestMapping(method = RequestMethod.GET)
public String list(Model model) {

Aún más sucinto: usa una anotación con la misma función de @RequestMapping, pero ya predefinida para un método HTTP concreto. Estas anotaciones son @GetMapping, @PostMapping, @PutMapping, @DeleteMapping y @PatchMapping.

@GetMapping
public String list(Model model) {

En el método list obtenemos la lista de países y la hacemos accesible a la página JSP añadiéndola al modelo (Model) de Spring MVC, un objeto que recibimos como un parámetro. La clase Model es un contenedor con los datos que el controlador envía a la vista.

Por último, se retorna el nombre de la vista. Spring lo completa con los valores que pusimos en spring.mvc.view.prefix y spring.mvc.view.suffix para obtener la ruta relativa del fichero dentro de la aplicación. En nuestro ejemplo esa ruta será /WEB-INF/jsp/countriesList.jsp.

En /src/main/webapp/WEB-INF/jsp/countriesList.jsp escribimos la página web.

<%@ page contentType="text/html; charset=UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="shortcut icon" type="image/png" href="/favicon.png">

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
          crossorigin="anonymous">

    <link rel="stylesheet" href="/styles.css">
    <title>Spring Boot + JSP</title>

</head>

<body>

   <div class="container">

      <div class="title">
        <h1>Countries</h1>
      </div>

      <c:choose>

            <c:when test="${not empty countriesList}">
    
                <ul>
                    <c:forEach var="item" items="${countriesList}">
                        <li>${item.name}:<fmt:formatNumber
                                value="${item.population}" /></li>
                    </c:forEach>
                </ul>
    
            </c:when>
            
            <c:otherwise>
                <b>NO DATA</b>
            </c:otherwise>
            
        </c:choose>
    </div>

    <footer class="footer">
      <div class="container">
        <p class="text-muted"><a href="https://danielme.com/spring/">danielme.com</a></p>
      </div>
    </footer>

</body>

</html>

Se trata de una página web bastante típica, «maquillada» con Bootstrap 5. Lo más interesante es el fragmento resaltado: genera HTML cada vez que se ejecuta la JSP y está programado con etiquetas JSTL. El código es autoexplicativo y te resultará familiar si conoces PHP. Si countriesList, dato contenido en el Model, tiene elementos, se itera para mostrarlos en un listado; si no, se muestra un mensaje.

Nótese que tenemos ficheros enlazados (CSS y favicon). Los recursos estáticos, como imágenes, CSS, JavaScript, etcétera, se sitúan en la carpeta /src/main/resources/static. Se accede a ellos a partir de la url raíz de la aplicación. Por ejemplo, /src/main/resources/static/favicon.png estará en /favicon.ico.

Ya estamos en condiciones de ejecutar el proyecto mediante su método main usando, por ejemplo, un entorno de desarrollo como Eclipse o IntelliJ. Que sea una aplicación web no es problema: Spring Boot arranca un servidor Tomcat embebido con nuestra aplicación desplegada en él.

Accedemos a la aplicación en la url raíz del Tomcat en el puerto 8080.

Puedes cambiar la configuración con las siguientes propiedades.

server.servlet.context-path=/spring-boot-jsp-demo
server.port=9090

Código de ejemplo

El código de ejemplo se encuentra en GitHub. Para más información sobre cómo utilizar GitHub, consultar este artículo.

Otros tutoriales relacionados

Spring Security \ Spring Boot: Segurización API REST con BASIC y base de datos (SQL y Spring Data). Testing.

Spring y Spring Boot: Gestión de errores en aplicaciones web y REST

Testing en Spring Boot con JUnit 4\5. Mockito, MockMvc, REST Assured, bases de datos en memoria.

Spring BOOT: integración con JSP

Spring JDBC Template: simplificando el uso de SQL

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.