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.