Si ya programas en Java, probablemente hayas oído hablar de Spring como "el framework que usa todo el mundo en el mundo empresarial". Y probablemente también hayas oído la queja histórica que lo acompañaba: que configurarlo era una tarea larga, repetitiva y llena de ficheros XML. Spring Boot nació exactamente para eliminar ese dolor. Esta lección explica qué problema concreto resuelve Spring Boot, cómo lo resuelve mediante cuatro mecanismos muy identificables, y cómo encaja dentro del ecosistema Spring. Al final conocerás también CicloUrbana, la aplicación real que construirás paso a paso durante todo el curso y que dará sentido práctico a cada concepto.

Contenido

  1. Spring Framework: el punto de partida
  2. El "infierno de configuración": un ejemplo comparativo real
  3. Los cuatro pilares de Spring Boot
  4. Spring Boot dentro del ecosistema Spring
  5. Qué tipo de aplicaciones se construyen con Spring Boot
  6. El proyecto del curso: CicloUrbana
  7. Versiones de Spring Boot 3.x y requisitos de Java
  8. Errores Comunes y Consejos
  9. Ejercicios

  1. Spring Framework: el punto de partida

Antes de entender Spring Boot hay que entender qué es Spring Framework, porque Spring Boot no lo sustituye: lo envuelve.

Spring Framework apareció en 2003 con una idea central: el contenedor de inversión de control (IoC, Inversion of Control). En lugar de que cada clase cree con new los objetos que necesita, es el framework quien crea esos objetos —llamados beans— y se los entrega a quien los pide. A eso se le llama inyección de dependencias.

La ventaja es inmediata:

  • Las clases dependen de interfaces, no de implementaciones concretas.
  • El código es fácil de probar, porque en una prueba puedes inyectar una implementación falsa.
  • La configuración de "qué se conecta con qué" vive en un solo sitio y no repartida por todo el código.

Sobre ese núcleo, Spring fue añadiendo módulos: acceso a datos, transacciones, MVC para web, seguridad, mensajería... Todo excelente. El problema no era la potencia, sino el coste de arrancar.

  1. El "infierno de configuración": un ejemplo comparativo real

Hasta aproximadamente 2014, poner en marcha una aplicación web Spring que expusiera un endpoint HTTP y hablara con una base de datos exigía este trabajo previo:

  1. Crear un proyecto Maven y elegir a mano la versión de cada librería (Spring Core, Spring MVC, Spring JDBC, Jackson, un pool de conexiones, el driver JDBC...), rezando para que fueran compatibles entre sí.
  2. Escribir un web.xml para registrar el servlet de Spring.
  3. Escribir uno o varios ficheros XML de contexto declarando los beans.
  4. Empaquetar un fichero WAR y desplegarlo en un servidor de aplicaciones instalado aparte (Tomcat, JBoss, WebLogic).

Veamos cómo se declaraba algo tan básico como un origen de datos y un gestor de transacciones en el estilo clásico:

<!-- applicationContext.xml — configuración clásica de Spring (estilo antiguo) -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="...">

    <!-- 1. Hay que declarar el pool de conexiones a mano -->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="jdbc:postgresql://localhost:5432/ciclourbana"/>
        <property name="username" value="ciclo"/>
        <property name="password" value="secreto"/>
        <property name="maxTotal" value="20"/>
    </bean>

    <!-- 2. Hay que declarar el gestor de transacciones y enlazarlo al dataSource -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 3. Hay que activar explícitamente el soporte de @Transactional -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- 4. Y decirle a Spring dónde buscar tus clases -->
    <context:component-scan base-package="com.ciclourbana"/>
</beans>

Y además un web.xml para arrancar todo eso dentro del servidor:

<!-- web.xml — necesario para que el servidor de aplicaciones cargue Spring -->
<web-app>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Son unas 40 líneas de configuración que no aportan ninguna funcionalidad de negocio: no hay ni una estación de bicicletas ni un alquiler. Es puro andamiaje. Y hay que repetirlo, con matices, en cada proyecto nuevo.

Lo mismo con Spring Boot

Con Spring Boot, ese bloque entero se reduce a un fichero de propiedades y una clase de arranque:

# src/main/resources/application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/ciclourbana
spring.datasource.username=ciclo
spring.datasource.password=secreto
package com.ciclourbana;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CicloUrbanaApplication {

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

Explicación de lo que acaba de ocurrir:

  • Spring Boot detecta que hay un driver de PostgreSQL en el classpath y que existe una propiedad spring.datasource.url. Con eso crea el DataSource por ti, usando HikariCP como pool de conexiones.
  • Detecta también que hay un DataSource y crea el gestor de transacciones, y activa el soporte de @Transactional.
  • El component-scan se activa solo, tomando como raíz el paquete donde está la clase anotada con @SpringBootApplication (com.ciclourbana).
  • No hace falta web.xml porque no hay servidor externo: el servidor viene dentro de la aplicación.

La comparación resumida:

Aspecto Spring clásico (pre-Boot) Spring Boot
Versiones de librerías Elegidas y cuadradas a mano Gestionadas por el parent / BOM
Configuración de infraestructura XML o @Configuration extensos Autoconfiguración + propiedades
Servidor web Externo, instalado aparte Embebido en el JAR
Artefacto de despliegue WAR desplegado en un contenedor JAR ejecutable (java -jar)
Tiempo hasta el primer endpoint Horas Minutos
Métricas, salud, logs Se añaden a mano Actuator, listo para producción

Idea clave: Spring Boot no es un framework nuevo que compita con Spring. Es una capa de opinión y automatización sobre Spring Framework. Todo lo que sabes de Spring sigue siendo válido; simplemente dejas de escribir la parte aburrida.

  1. Los cuatro pilares de Spring Boot

Casi todo lo que hace Spring Boot se explica con cuatro mecanismos. Conviene tenerlos claros desde el primer día porque los verás una y otra vez.

3.1 Autoconfiguración

Spring Boot mira qué hay en el classpath y qué has configurado, y a partir de ahí registra automáticamente los beans que normalmente harían falta. Si encuentra la librería de Spring MVC, configura un DispatcherServlet. Si encuentra un driver JDBC y una URL, configura un DataSource.

La regla de oro es que la autoconfiguración es condicional y cede el paso: si tú defines tu propio bean, Spring Boot se aparta y usa el tuyo. Nunca te bloquea. El mecanismo interno (las anotaciones @Conditional...) se estudia en detalle en el módulo 2, lección 02-06.

3.2 Starters

Un starter es una dependencia Maven que no contiene código, sino una lista curada de dependencias que funcionan bien juntas. En lugar de añadir ocho librerías con sus versiones, añades una:

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

Esa única línea arrastra Spring MVC, Jackson (para JSON), la validación, el registro de logs y un Tomcat embebido, todos en versiones compatibles entre sí. Observa que no hay etiqueta <version>: la versión la decide el parent de Spring Boot. Los starters se detallan en la lección 01-04 y su funcionamiento interno en la 02-06.

3.3 Servidor web embebido

Una aplicación Spring Boot web contiene su propio servidor. Al ejecutar java -jar ciclourbana.jar se arranca un Tomcat (o Jetty, o Undertow) dentro del mismo proceso Java.

Las consecuencias son grandes:

  • El artefacto es autocontenido: un solo fichero JAR con todo dentro.
  • La aplicación se ejecuta igual en tu portátil que en producción.
  • Encaja de forma natural con contenedores Docker y con plataformas cloud, donde el modelo es "un proceso, un puerto".
  • Ya no existe la clase de error "en mi máquina funciona, pero el Tomcat del servidor tiene otra versión".

3.4 Características listas para producción

Spring Boot incluye, con una sola dependencia (Actuator), lo que una aplicación necesita para vivir en producción:

  • Endpoints de salud (/actuator/health) que un balanceador o Kubernetes pueden consultar.
  • Métricas (memoria, peticiones por segundo, latencias) exportables a Prometheus.
  • Información de la aplicación, volcado de la configuración efectiva, cambio de nivel de log en caliente.

Todo esto se trata en los módulos 7 y 9. Menciono aquí solo que existe, porque es uno de los cuatro pilares y explica por qué Spring Boot es el estándar de facto en empresa.

  1. Spring Boot dentro del ecosistema Spring

"Spring" es una familia de proyectos. Esta tabla sitúa cada pieza y te dice en qué módulo del curso aparecerá:

Proyecto Qué aporta ¿Cuándo lo usarás en CicloUrbana?
Spring Framework Núcleo: contenedor IoC, inyección de dependencias, AOP, transacciones, Spring MVC Módulos 2 y 3
Spring Boot Autoconfiguración, starters, servidor embebido, Actuator Todo el curso
Spring Data JPA Repositorios automáticos sobre bases de datos relacionales Módulo 4
Spring Security Autenticación, autorización, protección de la API, JWT Módulo 5
Spring Test Utilidades de prueba integradas con JUnit y Mockito Módulo 6
Spring Cloud Configuración distribuida, descubrimiento de servicios, tolerancia a fallos Módulo 7 (introducción)
Spring Batch / Integration Procesos por lotes e integración de sistemas Fuera del alcance del curso

Piensa en Spring Boot como el integrador: no reimplementa Spring Data ni Spring Security, sino que los autoconfigura para que funcionen nada más añadir su starter.

  1. Qué tipo de aplicaciones se construyen con Spring Boot

Spring Boot no está limitado a APIs REST, aunque sea su uso más habitual:

  • APIs REST y backends de aplicaciones web o móviles. Es el caso mayoritario y el que sigue este curso.
  • Microservicios. Cada servicio es un JAR autónomo con su puerto y su base de datos.
  • Aplicaciones web tradicionales con vistas en servidor (Thymeleaf, FreeMarker).
  • Aplicaciones de línea de comandos y procesos por lotes, sin servidor web, usando CommandLineRunner (lección 01-05).
  • Consumidores de mensajería (Kafka, RabbitMQ) o tareas programadas (módulo 7).
  • APIs GraphQL o servicios reactivos con Spring WebFlux, para cargas de altísima concurrencia.

  1. El proyecto del curso: CicloUrbana

Durante todo el curso construirás CicloUrbana, la plataforma de gestión de la red municipal de bicicletas eléctricas de Ribalta, una ciudad ficticia de tamaño medio.

El contexto de negocio

El ayuntamiento de Ribalta ha instalado estaciones de anclaje repartidas por la ciudad —"Plaza Mayor", "Estación Norte", "Parque del Río" y "Universidad", entre otras—. Cada estación tiene una capacidad limitada de anclajes y unas coordenadas geográficas. En ellas hay bicicletas eléctricas identificadas por matrículas del tipo RB-0142, cada una con un nivel de batería y un estado.

Un usuario registrado desbloquea una bicicleta en una estación, circula y la devuelve en otra estación. Ese trayecto es un alquiler, que se cobra según una tarifa. Si algo va mal —freno roto, batería que no carga—, se abre una incidencia.

Los actores

Actor Qué hace en el sistema
Ciudadano usuario Consulta estaciones y bicicletas disponibles, inicia y finaliza alquileres, ve su historial
Operario de mantenimiento Recibe incidencias, cambia el estado de las bicicletas, reequilibra estaciones
Gestor municipal Consulta estadísticas de uso, gestiona tarifas, da de alta estaciones
Sistema externo La app móvil y los paneles informativos de las estaciones consumen la API

La API que acabará existiendo

Al terminar el curso, CicloUrbana expondrá una API REST versionada bajo /api/v1. Un adelanto de su forma final:

Método y ruta Propósito
GET /api/v1/estaciones Listar estaciones, con filtros y paginación
GET /api/v1/estaciones/{id} Detalle de una estación
POST /api/v1/estaciones Alta de estación (solo gestor)
GET /api/v1/estaciones/{id}/bicicletas Bicicletas disponibles en una estación
POST /api/v1/alquileres Iniciar un alquiler
POST /api/v1/alquileres/{id}/finalizar Devolver la bicicleta y calcular el importe
POST /api/v1/incidencias Reportar una avería
POST /api/v1/auth/login Obtener un token JWT

La arquitectura objetivo

flowchart TD
    subgraph Clientes
        A["App móvil"]
        B["Panel de estación"]
        C["Backoffice municipal"]
    end

    A --> API
    B --> API
    C --> API

    subgraph "CicloUrbana (Spring Boot)"
        API["Capa web<br/>Controladores REST /api/v1"]
        SEC["Spring Security<br/>JWT + roles"]
        SRV["Capa de servicio<br/>Reglas de negocio"]
        REP["Spring Data JPA<br/>Repositorios"]
        ACT["Actuator<br/>salud y métricas"]

        API --> SEC
        SEC --> SRV
        SRV --> REP
    end

    REP --> DB[("PostgreSQL")]
    ACT --> MON["Prometheus / Grafana"]

No te preocupes si algunas cajas te resultan desconocidas: cada una corresponde a un módulo del curso. En el módulo 1 solo construirás la capa web con datos fijos en memoria; el resto llegará a su debido tiempo.

Convenciones del proyecto

Estas decisiones se mantendrán invariables durante todo el curso:

Elemento Valor
groupId com.ciclourbana
artifactId ciclourbana
Paquete base com.ciclourbana
Java 21 (LTS)
Spring Boot 3.x
Construcción Maven, con wrapper mvnw
Prefijo de la API /api/v1
Idioma del código Identificadores y comentarios en español

  1. Versiones de Spring Boot 3.x y requisitos de Java

Spring Boot 3 supuso una ruptura importante respecto a la rama 2.x:

  • Requiere Java 17 como mínimo. Este curso usa Java 21, la versión LTS recomendada, que aporta records, pattern matching y hilos virtuales.
  • Migración de javax.* a jakarta.*. Las anotaciones de persistencia y validación pasaron de javax.persistence a jakarta.persistence. Si copias código antiguo de internet y ves javax, está desactualizado.
  • Se apoya en Spring Framework 6, con soporte nativo para observabilidad (Micrometer) y para compilación nativa con GraalVM.
Rama Java mínimo Espacio de nombres Situación
Spring Boot 2.7 Java 8 javax.* Fin de soporte gratuito
Spring Boot 3.0–3.2 Java 17 jakarta.* Ramas antiguas de la línea 3
Spring Boot 3.3/3.4/3.5 Java 17 (recomendado 21) jakarta.* Ramas en uso en el curso

Un detalle práctico: Spring Boot publica versiones menores con frecuencia. Cuando generes el proyecto en la lección 01-03, Spring Initializr te ofrecerá la última estable de la rama 3.x. Acepta la que te proponga; todo lo que aprendas aquí es válido en cualquier 3.x.

Errores Comunes y Consejos

  • Creer que Spring Boot sustituye a Spring Framework. No lo hace. Cuando depures un problema, recuerda que por debajo hay un ApplicationContext de Spring Framework de toda la vida. Aprender el núcleo (módulo 2) es lo que te permitirá salir de los atascos.
  • Pensar que la autoconfiguración es magia incontrolable. Es código Java normal, condicional y perfectamente inspeccionable. Cualquier bean que definas tú tiene prioridad sobre el autoconfigurado.
  • Seguir tutoriales de Spring Boot 2 sin darse cuenta. Señales de alerta: importaciones javax.persistence, WebSecurityConfigurerAdapter, antMatchers(). Todo eso ha desaparecido o cambiado en la rama 3.
  • Añadir dependencias con versión explícita. Si el starter la gestiona, no la fijes tú: romperás la compatibilidad que el parent garantiza.
  • Consejo: acostúmbrate desde hoy a consultar la documentación oficial en docs.spring.io. Está organizada por versión y es de las mejores del ecosistema Java.

Ejercicios

Ejercicio 1

Enumera las cuatro tareas de infraestructura que un desarrollador debía hacer a mano en Spring clásico y explica, para cada una, qué pilar de Spring Boot la elimina.

Ejercicio 2

Un compañero te dice: "He añadido spring-boot-starter-web pero quiero usar Jetty en lugar de Tomcat. Con Spring Boot eso ya no se puede elegir." Razona por qué esa afirmación es incorrecta, apoyándote en la idea de que la autoconfiguración "cede el paso".

Ejercicio 3

Diseña, sin escribir código, las rutas REST que necesitaría el operario de mantenimiento de CicloUrbana para hacer su trabajo. Indica método HTTP y ruta bajo /api/v1, y justifica brevemente cada una.

Soluciones

Solución 1

Tarea manual en Spring clásico Pilar que la elimina Cómo
Elegir y cuadrar versiones de librerías Starters Una sola dependencia arrastra un conjunto compatible; la versión la fija el parent
Declarar beans de infraestructura (DataSource, TransactionManager, DispatcherServlet) en XML Autoconfiguración Spring Boot los crea al detectar librerías y propiedades
Instalar y configurar un servidor de aplicaciones externo y empaquetar un WAR Servidor embebido El servidor va dentro del JAR ejecutable
Añadir a mano métricas, comprobaciones de salud y gestión de logs Características listas para producción Actuator las expone con una sola dependencia

Solución 2

La afirmación es incorrecta. spring-boot-starter-web incluye Tomcat por defecto, pero es una decisión reversible: basta con excluir el starter de Tomcat y añadir el de Jetty.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <!-- Quitamos el servidor por defecto -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- Y ponemos el que queremos -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

Al desaparecer Tomcat del classpath, la autoconfiguración que lo activaba deja de cumplirse y se activa la de Jetty. Este es exactamente el principio de "opinión por defecto, decisión reversible": Spring Boot elige por ti, pero nunca te ata.

Solución 3

Una propuesta razonable para el operario de mantenimiento:

Método y ruta Justificación
GET /api/v1/incidencias?estado=ABIERTA Ver su cola de trabajo pendiente; el filtro por estado evita traer histórico innecesario
GET /api/v1/incidencias/{id} Consultar el detalle de una avería concreta antes de desplazarse
PATCH /api/v1/bicicletas/{matricula} Cambiar el estado de una bicicleta (por ejemplo a MANTENIMIENTO); PATCH porque es una modificación parcial
POST /api/v1/incidencias/{id}/resolver Marcar la incidencia como resuelta; se modela como acción porque dispara lógica de negocio, no es un simple cambio de campo
GET /api/v1/estaciones?ocupacion=ALTA Detectar estaciones saturadas o vacías para reequilibrar bicicletas

Nota: POST /api/v1/incidencias/{id}/resolver rompe deliberadamente la ortodoxia REST más purista. Es un compromiso muy habitual y lo discutiremos con detalle en el módulo 3.

Conclusión

Spring Boot es una capa de automatización sobre Spring Framework que elimina la configuración repetitiva mediante cuatro pilares: autoconfiguración, starters, servidor embebido y características listas para producción. No reemplaza a Spring: lo hace productivo desde el minuto uno, sin quitarte el control, porque cualquier decisión automática puede sobrescribirse.

También conoces ya CicloUrbana, la red de bicicletas eléctricas de Ribalta que construirás capa a capa: primero la web con datos en memoria, después la persistencia, la seguridad, las pruebas y finalmente el despliegue y la monitorización.

En la siguiente lección, Configuración de tu Entorno de Desarrollo, prepararás la máquina: instalarás el JDK 21, entenderás por qué el curso usa Maven, elegirás IDE y herramientas de prueba de APIs, y validarás todo con un checklist antes de escribir la primera línea de CicloUrbana.

Curso de Spring Boot

Módulo 1: Introducción a Spring Boot

Módulo 2: Conceptos Básicos de Spring Boot

Módulo 3: Construyendo Servicios Web RESTful

Módulo 4: Acceso a Datos con Spring Boot

Módulo 5: Seguridad en Spring Boot

Módulo 6: Pruebas en Spring Boot

Módulo 7: Funciones Avanzadas de Spring Boot

Módulo 8: Despliegue de Aplicaciones Spring Boot

Módulo 9: Rendimiento y Monitoreo

Módulo 10: Mejores Prácticas y Consejos

© Copyright 2026. Todos los derechos reservados