Bisakah kita memasak Java, Kotlin RestController?

Hampir semua programmer java menulis RestController dalam hidupnya, tetapi beberapa orang bertanya-tanya apakah dia melakukannya dengan benar. Bahkan jika Anda seorang programmer yang berpengalaman, Anda mungkin memiliki pertanyaan yang akan saya coba jawab. Artikel ini akan membahas kerangka kerja seperti booting musim semi versi 1.5 dan 2.0, serta quarkus - saingan boot spring baru-baru ini dari topi merah.

gambar


Masalah


Diprogram untuk waktu yang lama di java dan spring boot 1.5. Tetapi ada kebutuhan untuk menulis proyek baru:

  1. Saya punya json untuk mengintegrasikan 1600 baris, beberapa kelas memiliki 100 bidang
  2. Saya ingin mencoba Kotlin dan Quarkus.
  3. Tulis pengendali istirahat yang akan dapat bekerja dengan kelas data kotlin tanpa penjelasan dan tanpa melibatkan sihir lombok. Saya ingin kelas data menjadi kecil

Anda mungkin menduga bahwa kelas data kotlin adalah kelas yang tidak dapat diubah, atau tidak bisa diubah. Kelas yang konstruktornya berisi semua bidang. Saya sangat percaya pada konsep ini; setelah membuat kelas, itu tidak dapat diubah, tidak ada setter di dalamnya. Karena gambar buruh pelabuhan tidak dapat diubah di dunia, kelas tanggal yang jatuh ke controller adalah sesuatu yang tidak bisa diubah.

Mari kita lihat kemungkinan cara untuk menyelesaikan masalah, lebih tepatnya bagaimana dalam proyek modern Anda dapat menulis controller:

Opsi standar. secara manual pada pegas atau pegas boot 1.5


Pengontrol sisanya muncul sejak lama, dan contoh berikut ini adalah contoh khas penggunaannya di java, yang ada di semua tutorial.

Kami baru saja membuat pengontrol paling sederhana

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

Dan buat POJO (objek java lama biasa)

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

mungkin ada variasi dengan bidang pribadi dan penjelasan getter / setter atau lombok, tapi bukan itu intinya.
Hebat, kami menciptakan pengontrol istirahat pertama yang berfungsi. Untuk 90% kasus, opsi kerja. Kamu bisa tinggal di sini

Masalahnya:

Konsep abadi berubah.
Kelas data sedikit verbose.

Bisakah kita membuat kekal?


Reaksi alami untuk masalah ini adalah keputusan untuk menghapus konstruktor default dan mencegah pengeditan bidang kelas.
 @Getter public class Fruit { private String name; private String description; // public Fruit() { // } public Fruit(String name, String description) { this.name = name; this.description = description; } } 

Tetapi sekarang masalah muncul, ternyata perpustakaan (kemungkinan besar jackson) tidak dapat membuat kelas. Kemungkinan besar Anda akan melihat kesalahan seperti Tidak ada konstruktor default ditemukan.

Jadi jackson pertama kali membuat kelas menggunakan konstruktor tanpa parameter, dan kemudian disebut pengambil / penyetel . Sungguh mengerikan. Lagi pula, apakah ada konstruktor dengan semua parameter? Namun sayangnya, ketika kelas dikompilasi, parameternya terlihat seperti ini.

gambar

Yaitu saat runtime, java tidak tahu apa-apa tentang nama parameter di konstruktor. Kompiler kehilangan mereka.

Opsi kedua adalah pegas atau pegas boot 1.5 + anotasi sebagai keselamatan


Jadi, kami menyadari bahwa kami menginginkan kelas yang tidak dapat diubah, dan kami tahu bahwa kami menggunakan jackson. Kemudian anatotika datang untuk menyelamatkan.

 @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; } } 

Saat ini, dalam proyek kami pada sping boot 1.5, penjelasan ini benar-benar penuh dengan segalanya.
Dan jika Anda menggunakan generator jsonschema2pojo yang populer, itu akan menghasilkan lebih banyak anotasi. Jujur, saya tidak suka mereka.

Coba salin di sana:

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

Pada hasil yang kami dapatkan (Anda dapat menyipitkan mata dan membolak-balik):

 @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; } } 

Cons: Anotasi sangat meningkatkan kelas. Sangat verbose, untuk seorang amatir.

Opsi ketiga pegas atau pegas boot 1,5 + bendera lombok


Terima kasih Throwable, saya akan mengutip dari komentar:

โ€œJika Anda menggunakan Lombok, maka cara terbaik adalah menulis di lombok.config:

lombok.allArgsConstructor.addConstructorProperties = true

Ini akan menghasilkan pada constructor @java.beans.ConstructorProperties , yang dipahami oleh Jackson. "

Pilihan bagus. Dia pasti akan menyelamatkan saya dari verbositas anotasi.

Cons:

Tapi saya ingin menggunakan Kotlin tanpa lombok.
Saya terlambat mempelajari opsi ini.

Versi keempat 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; } } 

Anehnya, spring boot 2.0 bekerja dengan tenang dengan kelas yang tidak dapat diubah. Dan juga dengan kelas data kotlin saudara kembarnya

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

Tampaknya java di runtime tidak tahu nama-nama parameter dalam konstruktor, tetapi karena beberapa alasan spring boot2 sudah tahu cara bekerja dengan kelas data. Jadi, lihat spring-boot-starter-parent, dukungan Kotlin telah ditambahkan di sana.

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

Saya mendekripsi. Agar nama parameter dalam konstruktor kelas tidak hilang selama runtime, kompiler harus melewati flag javac -parameters. Dan spring boot 2.0 melakukan ini.

Proyek sampel pada pegas boot 2 .

Opsi kelima. Quarkus + Kotlin


Quarkus memiliki contoh layanan istirahat , analog dari opsi pertama saya. Yaitu pengendali istirahat dengan cara kuno. Namun, jika Anda ingin menggunakannya dengan Kotlin, Anda harus menambahkan flag seperti yang dilakukan spring boot 2.

Deskripsi masalah di sini . Contoh cara menambahkan dukungan kelas data kotlin ke quarkus di sini .

Kesimpulan


Anda dapat menggunakan opsi paling sederhana pertama untuk membuat pengendali istirahat, tetapi saya akan menyarankan untuk bergerak menuju kelas yang tidak dapat diubah. Tulis di Kotlin dan Anda tidak perlu lombok. Kode harus lebih mudah dan lebih mudah. Saya yakin bahwa pembuat pegas sengaja pergi untuk menambahkan javac -parameters ke opsi kompiler dan seharusnya tidak ada kejahatan dalam hal ini. Semoga sukses untuk semua orang dalam perjalanan ke kode yang sempurna.

Terima kasih atas perhatian Anda!

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


All Articles