Si ja programes en Java, segurament has sentit a parlar de Spring com «el framework que fa servir tothom al món empresarial». I segurament també has sentit la queixa històrica que l'acompanyava: que configurar-lo era una feina llarga, repetitiva i plena de fitxers XML. Spring Boot va néixer exactament per eliminar aquest dolor. Aquesta lliçó explica quin problema concret resol Spring Boot, com el resol mitjançant quatre mecanismes molt identificables, i com encaixa dins l'ecosistema Spring. Al final coneixeràs també CicloUrbana, l'aplicació real que construiràs pas a pas durant tot el curs i que donarà sentit pràctic a cada concepte.
Contingut
- Spring Framework: el punt de partida
- L'«infern de configuració»: un exemple comparatiu real
- Els quatre pilars de Spring Boot
- Spring Boot dins l'ecosistema Spring
- Quin tipus d'aplicacions es construeixen amb Spring Boot
- El projecte del curs: CicloUrbana
- Versions de Spring Boot 3.x i requisits de Java
- Errors Habituals i Consells
- Exercicis
- Spring Framework: el punt de partida
Abans d'entendre Spring Boot cal entendre què és Spring Framework, perquè Spring Boot no el substitueix: l'embolcalla.
Spring Framework va aparèixer el 2003 amb una idea central: el contenidor d'inversió de control (IoC, Inversion of Control). En lloc que cada classe creï amb new els objectes que necessita, és el framework qui crea aquests objectes —anomenats beans— i els lliura a qui els demana. Això s'anomena injecció de dependències.
L'avantatge és immediat:
- Les classes depenen d'interfícies, no d'implementacions concretes.
- El codi és fàcil de provar, perquè en una prova pots injectar-hi una implementació falsa.
- La configuració de «què es connecta amb què» viu en un sol lloc i no repartida per tot el codi.
Damunt d'aquest nucli, Spring hi va anar afegint mòduls: accés a dades, transaccions, MVC per a web, seguretat, missatgeria... Tot excel·lent. El problema no era la potència, sinó el cost d'engegar.
- L'«infern de configuració»: un exemple comparatiu real
Fins aproximadament el 2014, posar en marxa una aplicació web Spring que exposés un endpoint HTTP i parlés amb una base de dades exigia aquesta feina prèvia:
- Crear un projecte Maven i triar a mà la versió de cada llibreria (Spring Core, Spring MVC, Spring JDBC, Jackson, un pool de connexions, el driver JDBC...), pregant que fossin compatibles entre elles.
- Escriure un
web.xmlper registrar el servlet de Spring. - Escriure un o més fitxers XML de context declarant els beans.
- Empaquetar un fitxer WAR i desplegar-lo en un servidor d'aplicacions instal·lat a part (Tomcat, JBoss, WebLogic).
Vegem com es declarava una cosa tan bàsica com un origen de dades i un gestor de transaccions a l'estil clàssic:
<!-- applicationContext.xml — configuració clàssica de Spring (estil antic) -->
<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. Cal declarar el pool de connexions a mà -->
<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="secret"/>
<property name="maxTotal" value="20"/>
</bean>
<!-- 2. Cal declarar el gestor de transaccions i enllaçar-lo al dataSource -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 3. Cal activar explícitament el suport de @Transactional -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 4. I dir-li a Spring on ha de buscar les teves classes -->
<context:component-scan base-package="com.ciclourbana"/>
</beans>I, a més, un web.xml per arrencar tot allò dins del servidor:
<!-- web.xml — necessari perquè el servidor d'aplicacions carregui 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>Són unes 40 línies de configuració que no aporten cap funcionalitat de negoci: no hi ha ni una estació de bicicletes ni un lloguer. És pur bastiment. I cal repetir-ho, amb matisos, a cada projecte nou.
El mateix amb Spring Boot
Amb Spring Boot, aquest bloc sencer es redueix a un fitxer de propietats i una classe d'arrencada:
# src/main/resources/application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/ciclourbana
spring.datasource.username=ciclo
spring.datasource.password=secretpackage 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ó del que acaba de passar:
- Spring Boot detecta que hi ha un driver de PostgreSQL al classpath i que existeix una propietat
spring.datasource.url. Amb això crea elDataSourceper tu, fent servir HikariCP com a pool de connexions. - Detecta també que hi ha un
DataSource, crea el gestor de transaccions i activa el suport de@Transactional. - El
component-scans'activa sol, prenent com a arrel el paquet on hi ha la classe anotada amb@SpringBootApplication(com.ciclourbana). - No cal cap
web.xmlperquè no hi ha servidor extern: el servidor va dins de l'aplicació.
La comparació resumida:
| Aspecte | Spring clàssic (pre-Boot) | Spring Boot |
|---|---|---|
| Versions de llibreries | Triades i quadrades a mà | Gestionades pel parent / BOM |
| Configuració d'infraestructura | XML o @Configuration extensos |
Autoconfiguració + propietats |
| Servidor web | Extern, instal·lat a part | Incrustat al JAR |
| Artefacte de desplegament | WAR desplegat en un contenidor | JAR executable (java -jar) |
| Temps fins al primer endpoint | Hores | Minuts |
| Mètriques, salut, logs | S'afegeixen a mà | Actuator, llest per a producció |
Idea clau: Spring Boot no és un framework nou que competeixi amb Spring. És una capa d'opinió i automatització damunt de Spring Framework. Tot el que saps de Spring continua sent vàlid; simplement deixes d'escriure la part avorrida.
- Els quatre pilars de Spring Boot
Gairebé tot el que fa Spring Boot s'explica amb quatre mecanismes. Val la pena tenir-los clars des del primer dia perquè els veuràs una vegada i una altra.
3.1 Autoconfiguració
Spring Boot mira què hi ha al classpath i què has configurat, i a partir d'aquí registra automàticament els beans que normalment caldrien. Si troba la llibreria de Spring MVC, configura un DispatcherServlet. Si troba un driver JDBC i una URL, configura un DataSource.
La regla d'or és que l'autoconfiguració és condicional i cedeix el pas: si tu defineixes el teu propi bean, Spring Boot s'aparta i fa servir el teu. Mai no et bloqueja. El mecanisme intern (les anotacions @Conditional...) s'estudia amb detall al mòdul 2, lliçó 02-06.
3.2 Starters
Un starter és una dependència Maven que no conté codi, sinó una llista curada de dependències que funcionen bé juntes. En lloc d'afegir vuit llibreries amb les seves versions, n'afegeixes una:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>Aquesta única línia arrossega Spring MVC, Jackson (per al JSON), la validació, el registre de logs i un Tomcat incrustat, tots en versions compatibles entre si. Fixa't que no hi ha etiqueta <version>: la versió la decideix el parent de Spring Boot. Els starters es detallen a la lliçó 01-04 i el seu funcionament intern a la 02-06.
3.3 Servidor web incrustat
Una aplicació Spring Boot web conté el seu propi servidor. En executar java -jar ciclourbana.jar s'arrenca un Tomcat (o Jetty, o Undertow) dins del mateix procés Java.
Les conseqüències són grans:
- L'artefacte és autocontingut: un sol fitxer JAR amb tot a dins.
- L'aplicació s'executa igual al teu portàtil que en producció.
- Encaixa de manera natural amb contenidors Docker i amb plataformes cloud, on el model és «un procés, un port».
- Ja no existeix aquella mena d'error de «a la meva màquina funciona, però el Tomcat del servidor té una altra versió».
3.4 Característiques llestes per a producció
Spring Boot inclou, amb una sola dependència (Actuator), allò que una aplicació necessita per viure en producció:
- Endpoints de salut (
/actuator/health) que un balancejador o Kubernetes poden consultar. - Mètriques (memòria, peticions per segon, latències) exportables a Prometheus.
- Informació de l'aplicació, bolcat de la configuració efectiva, canvi de nivell de log en calent.
Tot això es tracta als mòduls 7 i 9. Aquí només en menciono l'existència, perquè és un dels quatre pilars i explica per què Spring Boot és l'estàndard de facto a l'empresa.
- Spring Boot dins l'ecosistema Spring
«Spring» és una família de projectes. Aquesta taula situa cada peça i et diu en quin mòdul del curs apareixerà:
| Projecte | Què aporta | Quan el faràs servir a CicloUrbana? |
|---|---|---|
| Spring Framework | Nucli: contenidor IoC, injecció de dependències, AOP, transaccions, Spring MVC | Mòduls 2 i 3 |
| Spring Boot | Autoconfiguració, starters, servidor incrustat, Actuator | Tot el curs |
| Spring Data JPA | Repositoris automàtics damunt de bases de dades relacionals | Mòdul 4 |
| Spring Security | Autenticació, autorització, protecció de l'API, JWT | Mòdul 5 |
| Spring Test | Utilitats de prova integrades amb JUnit i Mockito | Mòdul 6 |
| Spring Cloud | Configuració distribuïda, descobriment de serveis, tolerància a fallades | Mòdul 7 (introducció) |
| Spring Batch / Integration | Processos per lots i integració de sistemes | Fora de l'abast del curs |
Pensa en Spring Boot com l'integrador: no reimplementa Spring Data ni Spring Security, sinó que els autoconfigura perquè funcionin tot just afegir-hi el seu starter.
- Quin tipus d'aplicacions es construeixen amb Spring Boot
Spring Boot no es limita a les API REST, encara que sigui el seu ús més habitual:
- API REST i backends d'aplicacions web o mòbils. És el cas majoritari i el que segueix aquest curs.
- Microserveis. Cada servei és un JAR autònom amb el seu port i la seva base de dades.
- Aplicacions web tradicionals amb vistes al servidor (Thymeleaf, FreeMarker).
- Aplicacions de línia d'ordres i processos per lots, sense servidor web, fent servir
CommandLineRunner(lliçó 01-05). - Consumidors de missatgeria (Kafka, RabbitMQ) o tasques programades (mòdul 7).
- API GraphQL o serveis reactius amb Spring WebFlux, per a càrregues d'altíssima concurrència.
- El projecte del curs: CicloUrbana
Durant tot el curs construiràs CicloUrbana, la plataforma de gestió de la xarxa municipal de bicicletes elèctriques de Ribalta, una ciutat fictícia de mida mitjana.
El context de negoci
L'ajuntament de Ribalta ha instal·lat estacions d'ancoratge repartides per la ciutat —«Plaça Major», «Estació Nord», «Parc del Riu» i «Universitat», entre d'altres—. Cada estació té una capacitat limitada d'ancoratges i unes coordenades geogràfiques. A dins hi ha bicicletes elèctriques identificades per matrícules del tipus RB-0142, cadascuna amb un nivell de bateria i un estat.
Un usuari registrat desbloqueja una bicicleta en una estació, circula i la retorna en una altra estació. Aquest trajecte és un lloguer, que es cobra segons una tarifa. Si alguna cosa va malament —fre trencat, bateria que no carrega—, s'obre una incidència.
Els actors
| Actor | Què fa dins del sistema |
|---|---|
| Ciutadà usuari | Consulta estacions i bicicletes disponibles, inicia i finalitza lloguers, veu el seu historial |
| Operari de manteniment | Rep incidències, canvia l'estat de les bicicletes, reequilibra estacions |
| Gestor municipal | Consulta estadístiques d'ús, gestiona tarifes, dona d'alta estacions |
| Sistema extern | L'app mòbil i els plafons informatius de les estacions consumeixen l'API |
L'API que acabarà existint
En acabar el curs, CicloUrbana exposarà una API REST versionada sota /api/v1. Un tast de la seva forma final:
| Mètode i ruta | Propòsit |
|---|---|
GET /api/v1/estacions |
Llistar estacions, amb filtres i paginació |
GET /api/v1/estacions/{id} |
Detall d'una estació |
POST /api/v1/estacions |
Alta d'estació (només gestor) |
GET /api/v1/estacions/{id}/bicicletes |
Bicicletes disponibles en una estació |
POST /api/v1/lloguers |
Iniciar un lloguer |
POST /api/v1/lloguers/{id}/finalitzar |
Retornar la bicicleta i calcular l'import |
POST /api/v1/incidencies |
Reportar una avaria |
POST /api/v1/auth/login |
Obtenir un token JWT |
L'arquitectura objectiu
flowchart TD
subgraph Clients
A["App mòbil"]
B["Plafó d'estació"]
C["Backoffice municipal"]
end
A --> API
B --> API
C --> API
subgraph "CicloUrbana (Spring Boot)"
API["Capa web<br/>Controladors REST /api/v1"]
SEC["Spring Security<br/>JWT + rols"]
SRV["Capa de servei<br/>Regles de negoci"]
REP["Spring Data JPA<br/>Repositoris"]
ACT["Actuator<br/>salut i mètriques"]
API --> SEC
SEC --> SRV
SRV --> REP
end
REP --> DB[("PostgreSQL")]
ACT --> MON["Prometheus / Grafana"]
No pateixis si algunes caixes et resulten desconegudes: cadascuna correspon a un mòdul del curs. Al mòdul 1 només construiràs la capa web amb dades fixes en memòria; la resta arribarà al seu degut temps.
Convencions del projecte
Aquestes decisions es mantindran invariables durant tot el curs:
| Element | Valor |
|---|---|
groupId |
com.ciclourbana |
artifactId |
ciclourbana |
| Paquet base | com.ciclourbana |
| Java | 21 (LTS) |
| Spring Boot | 3.x |
| Construcció | Maven, amb wrapper mvnw |
| Prefix de l'API | /api/v1 |
| Idioma del codi | Identificadors i comentaris en català |
- Versions de Spring Boot 3.x i requisits de Java
Spring Boot 3 va suposar una ruptura important respecte de la branca 2.x:
- Requereix Java 17 com a mínim. Aquest curs fa servir Java 21, la versió LTS recomanada, que aporta records, pattern matching i fils virtuals.
- Migració de
javax.*ajakarta.*. Les anotacions de persistència i validació van passar dejavax.persistenceajakarta.persistence. Si copies codi antic d'internet i veusjavax, està desactualitzat. - Es recolza en Spring Framework 6, amb suport natiu per a l'observabilitat (Micrometer) i per a la compilació nativa amb GraalVM.
| Branca | Java mínim | Espai de noms | Situació |
|---|---|---|---|
| Spring Boot 2.7 | Java 8 | javax.* |
Fi del suport gratuït |
| Spring Boot 3.0–3.2 | Java 17 | jakarta.* |
Branques antigues de la línia 3 |
| Spring Boot 3.3/3.4/3.5 | Java 17 (recomanat 21) | jakarta.* |
Branques en ús al curs |
Un detall pràctic: Spring Boot publica versions menors sovint. Quan generis el projecte a la lliçó 01-03, Spring Initializr t'oferirà l'última estable de la branca 3.x. Accepta la que et proposi; tot el que aprenguis aquí és vàlid a qualsevol 3.x.
Errors Habituals i Consells
- Creure que Spring Boot substitueix Spring Framework. No ho fa. Quan depuris un problema, recorda que a sota hi ha un
ApplicationContextde Spring Framework de tota la vida. Aprendre'n el nucli (mòdul 2) és el que et permetrà sortir dels embussos. - Pensar que l'autoconfiguració és màgia incontrolable. És codi Java normal, condicional i perfectament inspeccionable. Qualsevol bean que defineixis tu té prioritat sobre l'autoconfigurat.
- Seguir tutorials de Spring Boot 2 sense adonar-se'n. Senyals d'alerta: importacions
javax.persistence,WebSecurityConfigurerAdapter,antMatchers(). Tot això ha desaparegut o ha canviat a la branca 3. - Afegir dependències amb versió explícita. Si l'starter la gestiona, no la fixis tu: trencaràs la compatibilitat que el parent garanteix.
- Consell: acostuma't des d'avui a consultar la documentació oficial a
docs.spring.io. Està organitzada per versió i és de les millors de l'ecosistema Java.
Exercicis
Exercici 1
Enumera les quatre tasques d'infraestructura que un desenvolupador havia de fer a mà a Spring clàssic i explica, per a cadascuna, quin pilar de Spring Boot l'elimina.
Exercici 2
Un company et diu: «He afegit spring-boot-starter-web però vull fer servir Jetty en lloc de Tomcat. Amb Spring Boot això ja no es pot triar.» Raona per què aquesta afirmació és incorrecta, recolzant-te en la idea que l'autoconfiguració «cedeix el pas».
Exercici 3
Dissenya, sense escriure codi, les rutes REST que necessitaria l'operari de manteniment de CicloUrbana per fer la seva feina. Indica mètode HTTP i ruta sota /api/v1, i justifica breument cadascuna.
Solucions
Solució 1
| Tasca manual a Spring clàssic | Pilar que l'elimina | Com |
|---|---|---|
| Triar i quadrar versions de llibreries | Starters | Una sola dependència arrossega un conjunt compatible; la versió la fixa el parent |
Declarar beans d'infraestructura (DataSource, TransactionManager, DispatcherServlet) en XML |
Autoconfiguració | Spring Boot els crea en detectar llibreries i propietats |
| Instal·lar i configurar un servidor d'aplicacions extern i empaquetar un WAR | Servidor incrustat | El servidor va dins del JAR executable |
| Afegir a mà mètriques, comprovacions de salut i gestió de logs | Característiques llestes per a producció | Actuator les exposa amb una sola dependència |
Solució 2
L'afirmació és incorrecta. spring-boot-starter-web inclou Tomcat per defecte, però és una decisió reversible: n'hi ha prou d'excloure l'starter de Tomcat i afegir el de Jetty.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Traiem el servidor per defecte -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- I hi posem el que volem -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>En desaparèixer Tomcat del classpath, l'autoconfiguració que l'activava deixa de complir-se i s'activa la de Jetty. Aquest és exactament el principi d'«opinió per defecte, decisió reversible»: Spring Boot tria per tu, però mai no et lliga.
Solució 3
Una proposta raonable per a l'operari de manteniment:
| Mètode i ruta | Justificació |
|---|---|
GET /api/v1/incidencies?estat=OBERTA |
Veure la seva cua de feina pendent; el filtre per estat evita portar historial innecessari |
GET /api/v1/incidencies/{id} |
Consultar el detall d'una avaria concreta abans de desplaçar-s'hi |
PATCH /api/v1/bicicletes/{matricula} |
Canviar l'estat d'una bicicleta (per exemple a EN_MANTENIMENT); PATCH perquè és una modificació parcial |
POST /api/v1/incidencies/{id}/resoldre |
Marcar la incidència com a resolta; es modela com a acció perquè dispara lògica de negoci, no és un simple canvi de camp |
GET /api/v1/estacions?ocupacio=ALTA |
Detectar estacions saturades o buides per reequilibrar bicicletes |
Nota: POST /api/v1/incidencies/{id}/resoldre trenca deliberadament l'ortodòxia REST més purista. És un compromís molt habitual i el discutirem amb detall al mòdul 3.
Conclusió
Spring Boot és una capa d'automatització damunt de Spring Framework que elimina la configuració repetitiva mitjançant quatre pilars: autoconfiguració, starters, servidor incrustat i característiques llestes per a producció. No reemplaça Spring: el fa productiu des del primer minut, sense treure't el control, perquè qualsevol decisió automàtica es pot sobreescriure.
També coneixes ja CicloUrbana, la xarxa de bicicletes elèctriques de Ribalta que construiràs capa a capa: primer la web amb dades en memòria, després la persistència, la seguretat, les proves i finalment el desplegament i el monitoratge.
A la lliçó següent, Configuració del teu Entorn de Desenvolupament, prepararàs la màquina: instal·laràs el JDK 21, entendràs per què el curs fa servir Maven, triaràs IDE i eines de prova d'API, i ho validaràs tot amb una llista de comprovació abans d'escriure la primera línia de CicloUrbana.
Curs de Spring Boot
Mòdul 1: Introducció a Spring Boot
- Què és Spring Boot?
- Configuració del teu entorn de desenvolupament
- Creant la teva primera aplicació Spring Boot
- Entenent l'estructura del projecte
- L'arrencada i el cicle de vida de l'aplicació
Mòdul 2: Conceptes bàsics de Spring Boot
- Anotacions de Spring Boot
- Injecció de dependències a Spring Boot
- Àmbit i cicle de vida dels beans
- Configuració de Spring Boot
- Propietats de Spring Boot
- Autoconfiguració i starters per dins
Mòdul 3: Construint serveis web RESTful
- Introducció als serveis web RESTful
- Creant controladors REST
- Gestió dels mètodes HTTP
- Validació de dades d'entrada
- DTOs i mapatge entre capes
- Gestió d'excepcions a REST
- Documentar l'API amb OpenAPI
Mòdul 4: Accés a dades amb Spring Boot
- Introducció a Spring Data JPA
- Configuració de fonts de dades
- Creació d'entitats JPA
- Relacions entre entitats
- Ús de repositoris de Spring Data
- Mètodes de consulta a Spring Data JPA
- Transaccions i gestió de la persistència
- Migracions d'esquema amb Flyway
Mòdul 5: Seguretat a Spring Boot
- Introducció a Spring Security
- Configuració de Spring Security
- Autenticació i autorització d'usuaris
- Implementació d'autenticació JWT
- Seguretat a nivell de mètode i enduriment de l'API
Mòdul 6: Proves a Spring Boot
- Introducció a les proves
- Proves unitàries amb JUnit
- Simulació amb Mockito
- Proves d'integració
- Proves amb Testcontainers
Mòdul 7: Funcions avançades de Spring Boot
- Spring Boot Actuator
- Perfils de Spring Boot
- Tasques programades i execució asíncrona
- Spring Boot amb Docker
- Spring Boot i microserveis
- Comunicació entre serveis i tolerància a fallades
Mòdul 8: Desplegament d'aplicacions Spring Boot
- Introducció al desplegament
- Desplegant a Heroku
- Desplegant a AWS
- Desplegant a Kubernetes
- Integració i lliurament continus
Mòdul 9: Rendiment i monitoratge
- Ajust de rendiment
- Memòria cau amb Spring Cache
- Monitoratge amb Spring Boot Actuator
- Ús de Prometheus i Grafana
- Gestió de registres i logs
- Traçabilitat distribuïda
