Können wir Java, Kotlin RestController kochen?

Fast jeder Java-Programmierer hat RestController in seinem Leben geschrieben, aber nur wenige Leute fragen sich, ob er es richtig macht. Selbst wenn Sie ein erfahrener Programmierer sind, haben Sie möglicherweise Fragen, die ich zu beantworten versuchen werde. Der Artikel befasst sich mit Frameworks wie den Springboot-Versionen 1.5 und 2.0 sowie mit Quarkus, dem kürzlich erschienenen Rivalen von Springboot von Red Hat.

Bild


Das problem


Lange programmiert in java und spring boot 1.5. Es bestand jedoch die Notwendigkeit, ein neues Projekt zu schreiben:

  1. Ich habe JSON für die Integration von 1600 Zeilen, einige Klassen haben 100 Felder
  2. Ich wollte es mit Kotlin und Quarkus versuchen.
  3. Schreiben Sie einen Rest-Controller, der in der Lage ist, mit der Kotlin-Datenklasse ohne Anmerkungen und ohne Lombok-Magie zu arbeiten. Ich möchte, dass die Datenklasse klein ist

Sie haben wahrscheinlich vermutet, dass die Kotlin-Datenklasse eine unveränderliche Klasse oder unveränderlich ist. Eine Klasse, deren Konstruktor alle Felder enthält. Ich glaube fest an ein solches Konzept. Nach dem Erstellen einer Klasse kann sie nicht geändert werden, sie hat keine Setter. Da das Docker-Image in der Welt nicht geändert werden kann, kann die Datumsklasse, die in den Controller fällt, nicht geändert werden.

Schauen wir uns mögliche Lösungswege an, genauer gesagt, wie Sie in modernen Projekten einen Controller schreiben können:

Die Standardoption. manuell an Feder oder Federbein 1.5


Rest-Controller sind vor langer Zeit aufgetaucht, und das folgende Beispiel ist ein typisches Beispiel für ihre Verwendung in Java, das in allen Tutorials enthalten ist.

Wir erstellen nur die einfachste Steuerung

@RestController public class FruitController { @PostMapping("/fruit") public void greeting(@RequestBody Fruit request) { System.out.println(request); } } 

Und erstelle ein POJO (einfaches altes Java Objekt)

 public class Fruit { public String name; public String description; public Fruit() { } public Fruit(String name, String description) { this.name = name; this.description = description; } } 

Es kann Variationen mit privaten Feldern und Get / Setter- oder Lombok-Annotationen geben, aber nicht den Punkt.
Toll, wir haben den ersten Restcontroller erstellt, der funktioniert. Für 90% der Fälle die Arbeitsoption. Du kannst hier bleiben.

Die Probleme:

Das unveränderliche Konzept ist gebrochen.
Ein bisschen ausführliche Datenklasse.

Können wir unveränderlich machen?


Eine natürliche Reaktion auf dieses Problem ist die Entscheidung, den Standardkonstruktor zu entfernen und das Bearbeiten der Klassenfelder zu verhindern.
 @Getter public class Fruit { private String name; private String description; // public Fruit() { // } public Fruit(String name, String description) { this.name = name; this.description = description; } } 

Aber jetzt tritt ein Problem auf, und es stellt sich heraus, dass die Bibliothek (höchstwahrscheinlich Jackson) die Klasse nicht erstellen kann. Höchstwahrscheinlich wird ein Fehler wie Kein Standardkonstruktor gefunden angezeigt.

Jackson hat die klasse also zuerst mit dem konstruktor ohne parameter erstellt und dann getter / setter genannt . Was für ein Schrecken. Gibt es denn einen Konstruktor mit allen Parametern? Aber leider sehen die Parameter beim Kompilieren der Klasse ungefähr so ​​aus.

Bild

Das heißt Zur Laufzeit weiß Java nichts über Parameternamen im Konstruktor. Der Compiler verliert sie.

Die zweite Option ist Frühling oder Spring Boot 1.5 + Anmerkungen als Erlösung


Wir haben erkannt, dass wir eine unveränderliche Klasse wollen und wissen, dass wir Jackson verwenden. Dann kommt Anatotation zur Rettung.

 @Getter public class Fruit { private String name; private String description; @JsonCreator public Fruit(@JsonProperty("name") String name, @JsonProperty("description")String description) { this.name = name; this.description = description; } } 

Momentan sind diese Annotationen in unserem Projekt zu sping boot 1.5 buchstäblich voll von allem.
Und wenn Sie den beliebten jsonschema2pojo- Generator verwenden, werden noch mehr Anmerkungen generiert. Ehrlich gesagt mag ich sie nicht.

Versuchen Sie es dort zu kopieren:

 { "description": "description", "name": "name" } 

Am Ausgang erhalten wir (Sie können blinzeln und durchblättern):

 @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "description", "name" }) public class Example { @JsonProperty("description") private String description; @JsonProperty("name") private String name; @JsonProperty("description") public String getDescription() { return description; } @JsonProperty("description") public void setDescription(String description) { this.description = description; } @JsonProperty("name") public String getName() { return name; } @JsonProperty("name") public void setName(String name) { this.name = name; } } 

Nachteile: Anmerkungen erhöhen die Klasse erheblich. Sehr ausführlich für einen Amateur.

Dritte Option Feder oder Spring Boot 1.5 + Lombok Flagge


Dank Throwable zitiere ich aus dem Kommentar:

„Wenn Sie Lombok verwenden, schreiben Sie am besten in die Datei lombok.config:

lombok.allArgsConstructor.addConstructorProperties = true

Dies wird auf dem Konstruktor @java.beans.ConstructorProperties , von dem Jackson weiß, wie man es versteht. “

Gute Wahl. Er würde mich sicher vor der Fülle von Anmerkungen retten.

Nachteile:

Aber ich möchte Kotlin ohne Lombok benutzen.
Ich habe diese Option zu spät gelernt.

Die vierte Version von Spring Boot 2.0


 @Getter public class Fruit { private String name; private String description; public Fruit( String name, String description) { this.name = name; this.description = description; } } 

Überraschenderweise arbeitet Spring Boot 2.0 leise mit einer solchen unveränderlichen Klasse. Und auch mit seinem Zwillingsbruder Kotlin Data Class

 data class Fruit( val name : String, val description : String) 

Es scheint, dass Java in Runtime die Parameternamen im Konstruktor nicht kennt, aber aus irgendeinem Grund weiß spring boot2 bereits, wie man mit der Datenklasse arbeitet. Schauen Sie sich also Spring-Boot-Starter-Eltern an, dort wurde Kotlin-Unterstützung hinzugefügt.

 <plugin> <groupId>org.jetbrains.kotlin</groupId> ... <configuration> <javaParameters>true</javaParameters> </configuration> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <parameters>true</parameters> </configuration> </plugin> 

Ich entschlüssle. Damit die Parameternamen im Klassenkonstruktor zur Laufzeit nicht verloren gehen, muss der Compiler das javac -parameters- Flag übergeben und spring boot 2.0 tut dies.

Beispielprojekt am Spring Boot 2 .

Die fünfte Option. Quarkus + Kotlin


Quarkus hat ein Beispiel für einen Erholungsservice , ein Analogon zu meiner ersten Option. Das heißt Restcontroller auf die altmodische Art und Weise. Wenn Sie es jedoch mit Kotlin verwenden möchten, müssen Sie Flags hinzufügen, wie dies bei Spring Boot 2 der Fall war.

Beschreibung des Problems hier . Ein Beispiel für das Hinzufügen von Kotlin-Datenklassenunterstützung zu Quarkus hier .

Schlussfolgerungen


Sie können die erste einfachste Option zum Erstellen von Ruhecontrollern verwenden, aber ich würde raten, zu unveränderlichen Klassen überzugehen. Schreiben Sie auf Kotlin und Sie brauchen kein Lombok. Code sollte immer einfacher sein. Ich bin sicher, dass die Schöpfer des Frühlings absichtlich Javac-Parameter zu den Compiler-Optionen hinzugefügt haben und dass dies kein Verbrechen sein sollte. Viel Glück auf dem Weg zum perfekten Code.

Vielen Dank für Ihre Aufmerksamkeit!

Source: https://habr.com/ru/post/de480158/


All Articles