1. Sanfte MVC-Anpassung
Nachdem Sie Ihren ersten funktionierenden Controller haben, tritt meist ein sehr verständlicher Moment ein: „Oh, es funktioniert! Kann man… etwas bequemer?“. Und das ist normal. Im echten Leben ist ein Web-Service selten vollständig „default-only“: Man muss sich auf ein Datumsformat einigen, Enum nicht streng JAVA_BACKEND, sondern etwa java-backend akzeptieren, oder eine praktische Startseite erstellen. Das ist gesunder Ingenieursverstand – nicht „kaputt machen“, sondern „verbessern“.
Das Problem ist, dass das Gehirn eines Anfängers oft einen scharfen Sprung von „Ich brauche eine kleine Änderung“ zu „Also muss ich das gesamte MVC überschreiben“ macht. Und dann beginnt Spring Boot, Sie so anzusehen, wie eine Katze schaut, wenn Sie ohne Grund in den Systemblock mit einem Schraubendreher klettern: Es geht wohl, aber… warum?
Es ist wichtig, zwei Arten von Wünschen zu unterscheiden:
Die erste Art – „eine Regel zum bestehenden Verhalten hinzufügen“. Zum Beispiel „alle Daten in Query-Parametern als ISO lesen“. Oder „den Wert java-backend in JAVA_BACKEND umwandeln“. Das ist sanfte Anpassung, sie fügt sich gut in Spring Boot ein.
Die zweite Art – „Ich möchte die MVC-Konfiguration vollständig selbst verwalten“. Das ist bereits Framework-Übernahme: Boot hört auf zu helfen, und Sie werden zu der Person, die sagt „Ich stelle alles selbst ein“… und nach zwei Stunden feststellt, dass statische Ressourcen nicht geladen werden, JSON sich seltsam verhält und einige Request-Handler überhaupt nicht registriert werden. Springs Geduld ist zwar groß, aber nicht unendlich.
2. Boot-Standardwerte im Web-Layer
Spring Boot im Web-Modus ist nicht einfach „wir haben einen @GetMapping“. Es ist eine ganze Infrastruktur, die hochgezogen wurde, weil die notwendigen Abhängigkeiten auf dem Classpath sind und Boot entschieden hat: „Aha, eine Servlet-basierte Web-Anwendung, ich baue die Basisplattform“. Am Ende erhalten Sie eine funktionierende HTTP-Runtime, bei der Anfragen zu den Controllern gelangen, Parameter gebunden werden können, Antworten in JSON serialisiert werden und statische Dateien vom Classpath ausgeliefert werden können.
Einfacher gesagt, Boot spielt hier die Rolle eines sehr nützlichen Automechanikers: Er hat bereits die Zündung eingestellt, Öl eingefüllt, den Vergaser eingestellt (ja, ich bin alt), und das Auto startet. Dann kommen Sie und sagen: „Ich möchte den Sitz ein wenig verschieben“. Super – das ist WebMvcConfigurer. Aber wenn Sie stattdessen die Hälfte der Kabel aus dem Armaturenbrett ziehen, um zu verstehen, wie es funktioniert, werden Sie es wirklich verstehen … aber schon im Format „warum es aufgehört hat zu funktionieren“.
Um die Grenze zu spüren, ist es hilfreich, die MVC-Schicht in zwei Teile zu unterteilen:
1) Infrastruktur, ohne die eine Anfrage überhaupt nicht zu einer „Spring-MVC-Anfrage“ wird (Routing, Handler, Message Converter, viele interne Einstellungen).
2) projektspezifische Regeln, die als Ergänzung hinzugefügt werden können (Formatierung, kleine Konverter, Handhabung statischer Ressourcen, einige CORS-Einstellungen usw., aber wir beschränken uns heute auf das, was für catalog-service wichtig ist).
Spring Boot erwartet, dass Sie als Junior die Infrastruktur nicht manuell neu zusammenbauen. Nicht, weil „Sie es nicht dürfen“, sondern weil es in dieser Phase keinen Mehrwert bringt – und sehr leicht alles andere kaputt macht. Wir lernen hier, einen Service zu bauen, und nicht, Archäologie aller inneren MVC-Schichten zu betreiben.
3. WebMvcConfigurer: MVC-Erweiterung
WebMvcConfigurer ist ein Interface in Spring MVC, das speziell für die sanfte Anpassung des MVC-Verhaltens entwickelt wurde. Die Kernidee klingt fast philosophisch: „Schreibe nicht die gesamte Konfiguration neu – füge das hinzu, was fehlt.“ Das Interface enthält viele Hook-Methoden (Erweiterungspunkte), und jede von ihnen tut standardmäßig nichts. Sie überschreiben nur das, was wirklich benötigt wird, und überlassen den Rest Boot.
Es ist wichtig, den „psychologischen“ Unterschied zwischen „erweitern“ und „unter Kontrolle nehmen“ zu verstehen. Im Erweiterungsmodus sagen Sie: „Boot, du machst das gut, ich füge nur eine kleine Sache hinzu“. Im Kontrollmodus sagen Sie: „Boot, geh weg, ich bin jetzt der Chef“. Und Boot, als wohlerzogenes Framework, tritt tatsächlich zurück. Danach stellen Sie überrascht fest, dass „Chef über MVC“ zu sein ein Vollzeitjob ist (und manchmal auch ein Nachtjob).
Im catalog-service wird WebMvcConfigurer in erster Linie als Punkt verwendet, an dem wir sorgfältig die Konvertierung von Eingabewerten (Query-Parametern) registrieren und bei Bedarf die Arbeit mit statischen Ressourcen anpassen. Wir werden diese Klasse nicht zum „Mittelpunkt des Universums“ machen. Ihre Aufgabe ist es, MVC ein paar klare Regeln zu geben, nicht MVC neu zu schreiben.
Damit das funktioniert, muss WebMvcConfigurer ein Spring-Bean sein. Der einfachste Weg ist, eine kleine Konfigurationsklasse zu erstellen und sie in com.example.catalogservice.config zu platzieren, damit der Component Scan sie findet.
Hier ist es hilfreich, sofort zu sehen, wo dieser Erweiterungspunkt überhaupt benötigt wird. Die Web-Schicht hat zwei ruhige Anpassungsoberflächen. Die erste sind die Eingabewerte der Anfrage: Strings aus der URL, die in LocalDate, CourseTrack und andere Typen umgewandelt werden sollen. Die zweite sind einfache statische Ressourcen und die Welcome-Seite. Daher brauchen wir jetzt nur einen sauberen Erweiterungspunkt: ohne manuellen MVC-Modus, aber mit einem Ort, an dem genau die Regeln hinzugefügt werden können, die tatsächlich fehlen.
4. Praxis: WebConfiguration und addFormatters(...)
Jetzt machen wir den „bescheidensten“ und richtigsten Schritt: Wir fügen eine leere MVC-Konfiguration hinzu. Das ist so, als würden Sie eine Box mit der Aufschrift „Werkzeuge“ auf den Tisch stellen, aber noch keinen Schraubendreher und keinen Hammer hineinlegen. Die Box wird bereits jetzt benötigt, denn genau an einem solchen Ort leben saubere Web-Einstellungen, wenn das Standardverhalten nicht mehr ausreicht.
Erstellen Sie die Datei: src/main/java/com/example/catalogservice/config/WebConfiguration.java
Und fügen Sie den minimalen Code hinzu:
package com.example.catalogservice.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration // Deklariert eine Konfigurationsklasse: Spring wird sie als Bean übernehmen
public class WebConfiguration implements WebMvcConfigurer {
// Überschreiben noch nichts: dies ist ein Erweiterungspunkt für MVC,
// an dem Regeln hinzugefügt werden, wenn das Standardverhalten nicht mehr ausreicht
}
In dieser Phase ändert die Klasse nichts, und das ist gut. Wichtig ist etwas anderes: Wir haben einen architektonisch korrekten Punkt festgelegt, an dem die Web-Einstellungen leben. Eine solche separate Config-Klasse ist einfacher zu warten: Jeder im Projekt versteht sofort, wo MVC-Regeln zu finden sind, und CatalogServiceApplication wird nicht zu einem Lager für zufällige Konfiguration.
Wenn Sie die Anwendung neu starten, sollte sie genauso starten wie zuvor. Auch das ist ein gutes Zeichen: Das Hinzufügen von WebMvcConfigurer ist kein Akt der Zerstörung, sondern ein Akt der Vorbereitung auf punktuelle Verbesserungen.
Als Nächstes skizzieren wir den zentralen Erweiterungspunkt dieses Tages – addFormatters(...). Nicht, weil er der einzige ist, sondern weil er für unsere Katalog-Endpoints sehr praktisch ist. In einer echten API nehmen Sie fast immer Filterparameter über Query-Parameter entgegen, und Query-Parameter sind Strings. Also muss irgendwo die Magie der Umwandlung von "java-backend" in CourseTrack.JAVA_BACKEND und "2026-04-01" in LocalDate stattfinden.
Nur wollen wir diese „Magie“ heute nicht in jedem Controller manuell durchführen. Wir wollen eine Regel für die gesamte Web-Schicht. Genau dafür wird addFormatters(...) benötigt: Es ermöglicht die zentrale Registrierung von Konvertern und Formattern.
Zunächst fügen wir nur den „Hook“ hinzu:
package com.example.catalogservice.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// Hier werden die Regeln zur Umwandlung von Strings aus HTTP-Anfragen in die benötigten Typen registriert
// (z.B.: "java-backend" -> CourseTrack.JAVA_BACKEND, "2026-04-01" -> LocalDate)
// Converter und Formatter werden hier hinzugefügt, wenn die Standardregeln nicht mehr ausreichen.
}
}
Beachten Sie den Stil: Die Methode ist kurz, der Kommentar erklärt die Absicht und schafft kein „Rätsel für die Zukunft“. Wir versuchen nicht, sofort alle Umwandlungen zu implementieren, wir schleppen keine Services in Konverter und schreiben keinen „Universalparser für alles“. Der heutige Kurs handelt nicht von „Universalparsern für alles“. Es geht um eine vorhersagbare Anwendung.
5. @EnableWebMvc: Manueller MVC-Modus
Lassen Sie uns nun den wichtigsten „roten Knopf“ des heutigen Tages analysieren: @EnableWebMvc. Es existiert, es ist in einigen Szenarien nützlich, aber in einem Boot-Projekt kann es sehr leicht falsch verwendet werden. Anfänger denken oft: „Wir haben doch MVC! Also müssen wir MVC einschalten! Also setzen wir @EnableWebMvc“. Die Logik klingt vernünftig, aber das ist ein klassisches Beispiel dafür, dass „intuitiv“ und „richtig“ zwei verschiedene Dinge sind.
In Spring Boot ist MVC bereits aktiviert, weil Sie spring-boot-starter-webmvc hinzugefügt haben. @EnableWebMvc in einem solchen Projekt bedeutet normalerweise: „Ich möchte die MVC-Konfiguration manuell verwalten, ich brauche Ihre Defaults nicht.“ Und die Defaults, zur Erinnerung, sind keine „Kleinigkeit“, sie sind die Hälfte des Komforts von Boot.
Anti-Beispiel (das, was wir NICHT tun):
package com.example.catalogservice.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc // Anti-Beispiel: In Boot versetzt dies MVC in den manuellen Modus und deaktiviert einige Defaults
public class WebConfiguration {
}
Von außen sieht es aus wie harmlose zwei Zeilen. In der Praxis führt das oft zu dem Effekt: „Gestern hat alles funktioniert, und heute ist es wie eine andere Anwendung“. Das Verhalten der Message Converter kann sich ändern, die Auslieferung statischer Ressourcen kann brechen, und die Art, wie einige MVC-Einstellungen angewendet werden, kann sich ändern. Und das Unangenehmste: Sie verstehen nicht immer sofort, dass diese Annotation schuld ist, weil „sie schaltet doch nur MVC ein“.
Um den Unterschied festzuhalten, vergleichen wir die Ansätze in einer Tabelle. Das ist nicht die „ultimative Wahrheit“, aber ein sehr nützlicher Spickzettel für das Junior-Level.
| Was Sie tun | Was bedeutet das im Boot-Projekt | Typisches Ergebnis |
|---|---|---|
| Fügen Sie eine Klasse implements WebMvcConfigurer hinzu | „Ich füge ein paar Regeln zu den Boot-Defaults hinzu“ | Alles funktioniert weiter, und Sie ändern das Verhalten punktuell |
| Fügen Sie @EnableWebMvc hinzu | „Ich nehme die MVC-Konfiguration unter manuelle Kontrolle“ | Boot-Defaults können nicht mehr angewendet werden; Sie müssen mehr manuell verstehen und einstellen |
| Beginnen Sie, MVC-Infrastruktur-Beans zu deklarieren/ersetzen (handler mappings, converters usw.) | „Ich baue eine eigene MVC-Runtime“ | Sehr schnell beginnt: „Warum ist es nicht so wie im Beispiel aus dem Internet?“ |
Im Rahmen dieses Kurses ist die Regel einfach und ziemlich strikt: @EnableWebMvc ist nicht unser Weg. Wenn Sie das Gefühl haben, dass „es ohne @EnableWebMvc unmöglich ist“, ist das fast immer ein Symptom dafür, dass Sie entweder den richtigen Erweiterungspunkt nicht gefunden haben oder versuchen, eine zu große Aufgabe zu lösen (die eigentlich zu einem separaten Kurs oder einer späteren Stufe gehört).
6. Defaults und punktuelle Änderungen
Wenn wir sagen „brechen Sie die Boot-Defaults nicht“, bedeutet das nicht „ändern Sie nie etwas“. Es bedeutet eine reifere Denkweise: Verstehen Sie zuerst, was bereits passiert, und ändern Sie dann genau ein Stück, das wirklich geändert werden muss. In der Programmierung ist das ein universelles Prinzip: Kleine, lokale Änderungen sind fast immer zuverlässiger als eine vollständige Neukonfiguration der gesamten Anwendung.
In der Praxis sieht das so aus. Sie bemerken ein Problem (z.B. ein Datum in einem Query-Parameter wird nicht wie erwartet geparst). Anstatt LocalDate.parse(...) direkt im Controller zu schreiben oder eine globale Annotation „für alle Fälle“ zu setzen, fragen Sie sich: „Gibt es einen Standardmechanismus in MVC dafür?“. Wenn ja, konfigurieren Sie ihn zentral. Wenn nicht, fügen Sie einen kleinen Konverter/Formatter hinzu. Und nur wenn Sie genau verstehen, dass der Standardmechanismus stört, beginnen Sie, über ernsthaftere Eingriffe nachzudenken (aber das ist nicht mehr das Niveau dieses Tages).
Und ja, das ist etwas langweiliger, als „@EnableWebMvc zu drücken und sich wie der Herrscher über Spring zu fühlen“. Dafür wird Ihr Projekt später nicht zu einem Museum unerklärlicher Entscheidungen.
7. Typische Fehler bei der Verwendung von WebMvcConfigurer
Fehler Nr. 1: Sie setzen @EnableWebMvc „für alle Fälle“.
Das ist das häufigste Szenario: Derjenige versteht nicht vollständig, wo MVC konfiguriert wird, und beschließt, „alles richtig einzuschalten“. In Boot bedeutet das meistens, „nützliche Defaults auszuschalten“. Wenn Sie diese Annotation setzen möchten, halten Sie inne und versuchen Sie zuerst, die Aufgabe mit WebMvcConfigurer oder den Eigenschaften spring.mvc.* zu lösen.
Fehler Nr. 2: Sie legen Web-Einstellungen in CatalogServiceApplication ab.
Technisch können Sie alles in der main-Klasse schreiben (sie ist auch eine Spring-Konfiguration), aber dann sieht Ihr Projekt aus wie „eine Datei, in der alles lebt“. Das beeinträchtigt die Lesbarkeit und erschwert die Entwicklung. Es ist viel gesünder, eine separate WebConfiguration im Paket config zu haben, damit jeder im Team sofort den Ort findet, an dem die MVC-Einstellungen leben.
Fehler Nr. 3: Sie verwandeln WebConfiguration in eine „God-Config“ für das gesamte Projekt.
Sobald die erste Konfigurationsklasse auftaucht, entsteht die Versuchung: „Oh, lass uns hier noch ein bisschen hinzufügen … und noch … und hier auch …“. Nach ein paar Wochen haben Sie eine Datei mit 600 Zeilen, in der MVC-Einstellungen, einige Beans für Services, zufällige Konstanten und „temporäre“ Hacks durcheinander stehen. Halten Sie WebConfiguration thematisch: nur Web-Schicht, nur MVC.
Fehler Nr. 4: Sie versuchen, Geschäftslogik über MVC-Konverter zu lösen.
Konverter und Formatierer dienen der Typumwandlung, nicht dem „Holen einer Entität aus der Datenbank“ oder „Prüfen von Zugriffsrechten“. Selbst ohne Datenbank kann diese Versuchung auftreten: z.B. einen Konverter zu erstellen, der einen Service aufruft und einen Kurs per Slug sucht. Das ist eine schlechte Idee: Ein Konverter sollte klein, deterministisch sein und sich nicht in eine versteckte Geschäftslogik-Schicht verwandeln.
Fehler Nr. 5: Sie beginnen zu früh mit dem „Optimieren“ und schreiben das um, was Boot bereits macht.
Manchmal möchte man „alles explizit konfigurieren“: Message Converter, Handler Mappings, View Resolver, Resource Handler … einfach weil „das zuverlässiger ist“. In der Praxis macht das das Projekt oft zerbrechlicher. Boot-Defaults sind gerade deshalb gut, weil sie bereits zusammengestellt, getestet und erwartet sind. In unserem Kurs passen wir nur das an, was wirklich für catalog-service benötigt wird, und genau so viel, wie nötig.
GO TO FULL VERSION