Start / Cheat Sheets

Cheat Sheet

Spring Boot 4 — Cheat Sheet

Stand: · Spring Boot 4 Grundlagen

Spring BootJavaRESTSpring DataActuator

Der Spickzettel zu Spring Boot 4 Grundlagen — Annotationen, Rangfolgen und Kurzformen zum Nachschlagen, wenn man weiß, dass es geht, aber nicht mehr genau wie. Maßgeblich und immer aktuell ist die Spring-Boot-Referenzdokumentation; hier steht die Auswahl, die im Alltag tatsächlich gebraucht wird.

Starter und Autokonfiguration

Vier Ebenen, die oft in einen Topf geworfen werden. Wer sie trennt, weiß jederzeit, an welcher Stelle einzugreifen ist.

EbeneLiefertÜberlässt Ihnen
Spring FrameworkBausteine und ProgrammiermodellAuswahl und Konfiguration
Spring BootVorauswahl und StartlogikDie fachlichen Entscheidungen
StarterPassende Abhängigkeiten im BündelWelche Fähigkeit Sie brauchen
AutokonfigurationFertig verdrahtete KomponentenDas bewusste Abweichen davon

Eine Vorgabe ändert man, indem man Abhängigkeiten tauscht — nicht, indem man gegen sie konfiguriert. Tomcat-Starter ausschließen, Jetty-Starter ergänzen, und der Servlet-Container ist gewechselt; Code braucht es dafür nicht.

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

Keine Versionsnummern zu verwalteten Abhängigkeiten schreiben — das Eltern-Projekt legt für jede eine erprobte Version fest.

Modul: Einführung in Spring Boot

Die Startklasse

@SpringBootApplication ist eine Meta-Annotation und wirkt wie drei einzelne:

AnnotationWirkung
@SpringBootConfigurationErlaubt der Klasse, Bean-Methoden zu enthalten
@ComponentScanSucht annotierte Klassen und registriert sie als Beans
@EnableAutoConfigurationStartet die Autokonfiguration

Die Komponentensuche beginnt beim Paket der Startklasse. Beans außerhalb dieses Paketbaums werden nicht gefunden — die häufigste Ursache für fehlende Abhängigkeiten beim Start.

Modul: Einführung in Spring Boot

Konfiguration: Rangfolge der Quellen

Je spezifischer eine Quelle, desto stärker wiegt sie. Bei einem unerwarteten Wert nicht im Code suchen, sondern diese Liste von oben durchgehen.

QuelleTypische Verwendung
KommandozeilenargumentEinmaliger Lauf, schnelle Gegenprobe
UmgebungsvariableBetrieb im Container
Datei im DateisystemUmgebungsspezifische Einstellungen
application.properties im JarVorgaben für alle Umgebungen
@Value("${radwerk.begruessung:Kein Text gesetzt}")
private String begruessung;

Ohne Vorgabewert nach dem Doppelpunkt startet die Anwendung nicht. Umgebungsvariablen stehen groß mit Unterstrichen (RADWERK_BEGRUESSUNG); Spring Boot übersetzt in Kleinschreibung mit Punkten.

Externe Dateien einbinden:

EigenschaftWirkung
spring.config.locationErsetzt die Datei im Jar vollständig
spring.config.additional-locationErgänzt sie, externe Werte haben Vorrang

Modul: Konfigurationsverwaltung und Profile

Profile

Ein Profil ist nur ein Etikett — es gibt keine vordefinierten Namen mit eingebauter Bedeutung.

application.properties          gemeinsam
application-dev.properties      lokal
application-prod.properties     produktiv
java -jar werkstatt.jar --spring.profiles.active=prod,metriken

Die Profildatei wird zusätzlich geladen und hat Vorrang: Gemeinsames einmal in die schlichte Datei, nur Abweichendes in die Profildatei. @Profile schaltet auch einzelne Beans profilabhängig.

Modul: Konfigurationsverwaltung und Profile

Parameterbindung im Controller

AnnotationQuelle in der AnfrageBeispiel
@RequestParamAbfrageparameter/termine?filialeId=101
@PathVariablePlatzhalter im Pfad/termine/501
@RequestBodyRumpf der AnfragePOST mit JSON

Faustregel für den Entwurf: Zugriff über den Schlüssel gehört in den Pfad (er benennt eine Ressource), Suche nach anderen Kriterien in Abfrageparameter.

@RestController ist @Controller plus @ResponseBody — ohne den zweiten Teil sucht Spring eine View, statt den Rückgabewert als Antwortrumpf zu schreiben. Steht @RequestMapping an der Klasse, gilt sein Pfad als Basis aller Methoden.

Modul: RESTful APIs mit Spring Boot

Fehlerbehandlung

WegWirkungGrenze
ResponseEntity je MethodeVolle KontrolleWiederholt sich überall
@ExceptionHandler in der KlasseEine Stelle je ControllerGilt nur dort
@ControllerAdviceEine Stelle für alleBraucht klare Regeln
@ExceptionHandler(NoSuchElementException.class)
public ErrorResponse nichtGefunden(NoSuchElementException e) {
    return ErrorResponse.create(e, HttpStatus.NOT_FOUND, e.getMessage());
}

Modul: RESTful APIs mit Spring Boot

Validierung

Drei Bausteine, und alle drei müssen sitzen — fehlt einer, wird stillschweigend nicht geprüft:

  1. Abhängigkeit spring-boot-starter-validation
  2. @Valid am Methodenparameter
  3. Prüfannotationen am Record
public record AnmeldungAnfrage(
    @NotNull(message = "Leistung ist erforderlich") Long leistungId,
    @NotBlank(message = "Name darf nicht leer sein") String kundenname) {}

@NotNull verlangt einen Wert, @NotBlank zusätzlich einen nicht leeren Text. Prüfdetails erscheinen ohne weiteres Zutun nicht in der Antwort.

Modul: RESTful APIs mit Spring Boot

API-Versionierung

Neu in Spring Boot 4: Die Version wird Teil der Zuordnung statt der Methodenlogik — mehrere Methoden dürfen denselben Pfad in verschiedenen Versionen bedienen.

WegBeispielBemerkung
Im Pfad/v2/termineSofort sichtbar
Als Abfrageparameter/termine?version=2Leicht zu setzen
Eigener KopfX-API-Version: 2Pfad bleibt sauber
Im Accept-Kopfapplication/json;version=2Standardnah

Modul: RESTful APIs mit Spring Boot

Spring Data: Schichten und Repositories

EbeneWas sie leistetBeispiel
JDBCRoher Zugriff auf die DatenbankTreiber, SQL
JPAAbbildung Objekt zu TabelleHibernate
Spring Data JPARepositories ohne ImplementierungJpaRepository
Boot-StarterDatenquelle und Transaktionenstarter-data-jpa
public interface TerminRepository extends JpaRepository<Termin, Long> {
    List<Termin> findByFilialeId(Long filialeId);
}

Erster Typparameter ist die Entität, zweiter der Typ ihres Schlüssels. findAll und findById stammen aus den geerbten Schnittstellen; eigene Methoden leitet Spring Data aus dem Namen ab — Namen sind hier Abfragen. Die Implementierung entsteht beim Start und liegt nicht als Datei im Projekt.

Entitäten müssen veränderlich sein: @Entity, @Table, @Id, @GeneratedValue, @Column, Beziehungen über @ManyToOne und @JoinColumn. Records scheiden für JPA damit aus — für MongoDB nicht:

@Document
public record Anmeldung(@Id String id, Long leistungId, String kundenname) {}

public interface AnmeldungRepository extends MongoRepository<Anmeldung, String> {}

@Document stammt aus dem MongoDB-Paket, @Id hier aus org.springframework.data.annotationnicht aus JPA; ein falscher Import sieht identisch aus und wirkt nicht.

Schema und Daten kommen aus schema.sql und data.sql in src/main/resources, dazu spring.jpa.hibernate.ddl-auto=none — sonst legen Hibernate und Skript dieselben Tabellen an. In Produktion gehört stattdessen ein Migrationswerkzeug wie Flyway oder Liquibase davor.

Modul: Datenzugriff und Persistenz

Testzuschnitte

Der Zuschnitt entscheidet über Aussagekraft und Laufzeit — je schmaler, desto schneller.

AnnotationLädtWerkzeug
@WebMvcTest(X.class)Einen Controller, kein Tomcat, keine DatenbankMockMvc
@DataJpaTestH2 im Speicher plus DatenquelleTestEntityManager
@DataMongoTestDasselbe Muster für MongoDBRepository
@SpringBootTestDie volle Anwendungje nach Webumgebung
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)

Ohne RANDOM_PORT läuft auch @SpringBootTest gegen eine nachgebildete Webumgebung. @DirtiesContext erzwingt einen frischen Kontext nach jeder Testklasse — sonst bleibt die H2-Datenbank bestehen und die zweite Klasse scheitert an bereits existierenden Tabellen.

@MockitoBean legt eine Attrappe an und registriert sie im Testkontext. Für externe Systeme startet Testcontainers einen Container für die Dauer des Tests; das Feld braucht @Container (meldet es JUnit) und @ServiceConnection (übergibt die Verbindungsdaten an Spring Boot).

Modul: Spring-Boot-Anwendungen testen

Actuator-Endpunkte

EndpunktAuskunft
healthLäuft die Anwendung ordnungsgemäß
metricsVerbrauchs- und Durchsatzwerte
loggersProtokollierung ansehen und im Lauf ändern
beansWelche Beans im Kontext registriert sind
envWelche Konfigurationswerte tatsächlich gelten
conditionsWelche Entscheidungen die Autokonfiguration traf
mappingsWelche Anfrage zu welcher Methode führt

Ohne Zutun ist nur health über HTTP erreichbar. Freischalten sparsam und mit Zugriffsschutz davor — env verrät Konfigurationswerte:

management.endpoints.web.exposure.include=health,metrics,loggers

Metriken lassen sich über Etiketten aufschlüsseln: /actuator/metrics/http.server.requests?tag=status:404. Sie zeigen den Verlauf und brauchen dafür ein Ziel außerhalb der Anwendung.

Modul: Observability mit Actuator, Metriken und Logging

Auslieferung

./mvnw spring-boot:build-image

Baut ein Abbild ohne Dockerfile über Buildpacks, die es sinnvoll schichten. Vorher die Java-Version des Plugins in der pom.xml setzen.

Unter Docker Compose finden Container einander über ihren Dienstnamen; feste Adressen hebeln das aus. Eine Abhängigkeit auf den Gesundheitscheck des anderen Dienstes verhindert sporadische Verbindungsfehler beim Start. Für Ausrollvorgänge ohne abgebrochene Anfragen:

server.shutdown=graceful

Modul: Deployment und Betrieb

Native Abbilder: Gewinn und Preis

AspektGewinnPreis
StartzeitDeutlich kürzerLängerer Bau
SpeicherSpürbar geringerWeniger Spielraum
ReflectionNicht ohne Weiteres
KonfigurationTeils anderes Verhalten
ReifeNach Einschätzung noch experimentell

Lohnt bei vielen kurzlebigen Instanzen oder wenn Speicher unmittelbar Kosten verursacht — nicht als Gewohnheit für jede Anwendung.

Modul: Deployment und Betrieb

Web MVC oder WebFlux

FrageSpring Web MVCSpring WebFlux
ProgrammierstilImperativ, vertrautReaktive Ströme, funktional
Ein- und AusgabeBlockierendNicht blockierend
EinarbeitungFlachSteil
FehlersucheGewohntDeutlich mühsamer
EmpfehlungDer RegelfallNur bei belegtem Nutzen

Modul: RESTful APIs mit Spring Boot

Typische Fallen

  • Beans außerhalb des Paketbaums der Startklasse — die Komponentensuche findet sie nicht, und die Fehlermeldung nennt selten die Ursache.
  • Versionsnummern zu verwalteten Abhängigkeiten hebeln die Abstimmung des Eltern-Projekts aus.
  • Gegen eine Vorgabe konfigurieren, statt den Starter zu tauschen.
  • spring.config.location statt additional-location — alle Vorgaben aus dem Jar sind damit weg.
  • Umgebungsvariablen kleingeschrieben setzen und sich über die Wirkungslosigkeit wundern.
  • Das aktive Profil fest ins Jar schreiben und die Auslieferung wieder umgebungsabhängig machen.
  • @Controller statt @RestController — der Endpunkt antwortet, aber mit leerem Rumpf.
  • @Valid am Parameter vergessen — die Prüfannotationen am Record bleiben wirkungslos, ohne Warnung.
  • get() auf einem leeren Optional — ergibt Status 500, wo 404 richtig wäre.
  • Records als JPA-Entitäten scheitern an der geforderten Veränderlichkeit.
  • @Id aus dem falschen Paket bei MongoDB — sieht identisch aus, wirkt nicht.
  • data.sql ohne schema.sql — das Datenskript läuft, bevor die Tabellen existieren.
  • Hibernates Schemaerzeugung in Produktion aktiv lassen.
  • Alles als Integrationstest schreiben und die Rückmeldung so verlangsamen, dass niemand die Tests mehr laufen lässt.
  • @ServiceConnection vergessen — der Container läuft, die Anwendung weiß nichts davon.
  • Alle Actuator-Endpunkte freigeben oder die Freigabeliste aus der Entwicklung mit ausliefern.
  • Passwörter in eine ConfigMap statt in ein Secret schreiben.
  • Die Java-Version im Build-Image-Plugin vergessen.
  • Ohne Gesundheitscheck starten — sporadische Verbindungsfehler, die sich schlecht reproduzieren lassen.

Zum Seminar Spring Boot 4 Grundlagen