Schnittstellengesteuerte Steuerungen im Frühjahr

1. Einleitung

In diesem Tutorial betrachten wir eine neue Funktion von Spring MVC, mit der wir die Webanforderungen mithilfe der üblichen Java-Schnittstellen angeben können.

2. Übersicht

Wenn wir einen Controller in Spring MVC definieren, dekorieren wir seine Methoden normalerweise mit verschiedenen Anmerkungen, die die Anforderung angeben: der URL des Endpunkts, der HTTP-Anforderungsmethode, den Pfadvariablen usw.

Wir können zum Beispiel den Endpunkt / save / {id} mithilfe dieser Anmerkungen auf einer ansonsten einfachen Methode einführen :

@PostMapping("/save/{id}") @ResponseBody public Book save(@RequestBody Book book, @PathVariable int id) { // implementation }

Dies ist natürlich überhaupt kein Problem, wenn wir nur einen Controller haben, der die Anforderungen bearbeitet. Die Situation ändert sich ein wenig, wenn wir verschiedene Controller mit denselben Methodensignaturen haben.

Beispielsweise haben wir möglicherweise zwei verschiedene Versionen des Controllers - aufgrund von Migration oder ähnlichem - mit denselben Methodensignaturen. In diesem Fall hätten wir eine beträchtliche Anzahl doppelter Anmerkungen, die den Methodendefinitionen beiliegen. Offensichtlich würde dies gegen das DRY- Prinzip ( wiederholen Sie sich nicht ) verstoßen.

Wenn diese Situation für reine Java-Klassen eintreten würde, würden wir einfach eine Schnittstelle definieren und die Klassen diese Schnittstelle implementieren lassen. In den Controllern liegt die Hauptlast für die Methoden nicht in den Methodensignaturen, sondern in den Methodenanmerkungen.

In Spring 5.1 wurde jedoch eine neue Funktion eingeführt:

Anmerkungen zu Controller-Parametern werden auch auf Schnittstellen erkannt: Ermöglichen vollständige Zuordnungsverträge in Controller-Schnittstellen.

Lassen Sie uns untersuchen, wie wir diese Funktion verwenden können.

3. Controller-Schnittstelle

3.1. Kontext-Setup

Wir veranschaulichen die neue Funktion anhand eines Beispiels einer sehr einfachen REST-Anwendung, die Bücher verwaltet. Es besteht aus nur einem Controller mit Methoden, mit denen wir die Bücher abrufen und ändern können.

Im Tutorial konzentrieren wir uns nur auf die Probleme im Zusammenhang mit der Funktion. Alle Implementierungsprobleme der Anwendung finden Sie in unserem GitHub-Repository.

3.2. Schnittstelle

Definieren wir eine übliche Java-Schnittstelle, in der wir nicht nur die Signaturen der Methoden definieren, sondern auch die Art der Webanforderungen, die sie verarbeiten sollen:

@RequestMapping("/default") public interface BookOperations { @GetMapping("/") List getAll(); @GetMapping("/{id}") Optional getById(@PathVariable int id); @PostMapping("/save/{id}") public void save(@RequestBody Book book, @PathVariable int id); }

Beachten Sie, dass wir möglicherweise sowohl Annotationen auf Klassenebene als auch Annotationen auf Methodenebene haben. Jetzt können wir einen Controller erstellen, der diese Schnittstelle implementiert:

@RestController @RequestMapping("/book") public class BookController implements BookOperations { @Override public List getAll() {...} @Override public Optional getById(int id) {...} @Override public void save(Book book, int id) {...} }

Wir sollten unserem Controller weiterhin die Annotation @RestController oder @Controller auf Klassenebene hinzufügen . Auf diese Weise definiert, erbt der Controller alle Anmerkungen, die sich auf die Zuordnung der Webanforderungen beziehen.

Um zu überprüfen, ob der Controller jetzt wie erwartet funktioniert, führen Sie die Anwendung aus und klicken Sie auf die Methode getAll () , indem Sie die entsprechende Anforderung stellen:

curl //localhost:8081/book/

Obwohl der Controller die Schnittstelle implementiert, können wir sie durch Hinzufügen von Webanforderungsanmerkungen weiter optimieren. Wir können dies auf eine Weise tun, wie wir es für die Schnittstelle getan haben: entweder auf Klassenebene oder auf Methodenebene. Tatsächlich haben wir diese Möglichkeit bei der Definition des Controllers verwendet:

@RequestMapping("/book") public class BookController implements BookOperations {...}

Wenn wir dem Controller Webanforderungsanmerkungen hinzufügen, haben diese Vorrang vor den Anmerkungen der Schnittstelle. Mit anderen Worten, Spring interpretiert die Controller-Schnittstellen ähnlich wie Java mit Vererbung umgeht.

Wir definieren alle gängigen Webanforderungseigenschaften in der Benutzeroberfläche, aber im Controller können wir sie jederzeit optimieren.

3.3. Achtung Hinweis

Wenn wir eine Schnittstelle und verschiedene Controller haben, die sie implementieren, kann es vorkommen, dass eine Webanforderung von mehr als einer Methode verarbeitet wird. Natürlich wird der Frühling eine Ausnahme werfen:

Caused by: java.lang.IllegalStateException: Ambiguous mapping.

Wenn wir den Controller mit @RequestMapping dekorieren , können wir das Risiko mehrdeutiger Zuordnungen verringern.

4. Fazit

In diesem Tutorial haben wir eine neue Funktion betrachtet, die in Spring 5.1 eingeführt wurde. Wenn Spring MVC-Controller eine Schnittstelle implementieren, tun sie dies nicht nur auf die Standard-Java-Weise, sondern erben auch alle in der Schnittstelle definierten Funktionen für Webanfragen.

Wie immer finden wir möglicherweise die entsprechenden Codefragmente in unserem GitHub-Repository.