Pengontrol Berbasis Antarmuka di Spring

1. Perkenalan

Dalam tutorial ini, kami mempertimbangkan fitur baru Spring MVC yang memungkinkan kami menentukan permintaan web menggunakan antarmuka Java biasa.

2. Ikhtisar

Biasanya, saat mendefinisikan pengontrol di Spring MVC, kami menghias metodenya dengan berbagai anotasi yang menentukan permintaan: URL titik akhir, metode permintaan HTTP, variabel jalur, dan seterusnya.

Misalnya, kita dapat memperkenalkan titik akhir / save / {id} menggunakan anotasi tersebut pada metode yang biasa:

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

Secara alami, ini sama sekali bukan masalah ketika kita hanya memiliki satu pengontrol yang menangani permintaan. Situasi berubah sedikit ketika kita memiliki berbagai pengontrol dengan tanda tangan metode yang sama.

Misalnya, kami mungkin memiliki dua versi berbeda dari pengontrol - karena migrasi atau serupa - yang memiliki tanda tangan metode yang sama. Dalam hal ini, kami akan memiliki sejumlah besar anotasi duplikat yang menyertai definisi metode. Jelas, itu akan melanggar prinsip KERING ( jangan ulangi diri sendiri ).

Jika situasi ini terjadi untuk kelas Java murni, kita cukup mendefinisikan antarmuka dan membuat kelas mengimplementasikan antarmuka ini. Dalam pengontrol, beban utama pada metode bukan karena tanda tangan metode, tetapi karena anotasi metode.

Musim semi 5.1, bagaimanapun, memperkenalkan fitur baru:

Anotasi parameter pengontrol juga terdeteksi pada antarmuka: Memungkinkan kontrak pemetaan lengkap di antarmuka pengontrol.

Mari selidiki bagaimana kita dapat menggunakan fitur ini.

3. Antarmuka Pengontrol

3.1. Pengaturan Konteks

Kami mengilustrasikan fitur baru dengan menggunakan contoh aplikasi REST yang sangat sederhana yang mengelola buku. Ini hanya akan terdiri dari satu pengontrol dengan metode yang memungkinkan kita untuk mengambil dan memodifikasi buku.

Dalam tutorial, kami hanya berkonsentrasi pada masalah yang terkait dengan fitur. Semua masalah implementasi aplikasi dapat ditemukan di repositori GitHub kami.

3.2. Antarmuka

Mari kita tentukan antarmuka Java biasa di mana kita tidak hanya mendefinisikan tanda tangan metode tetapi juga jenis permintaan web yang seharusnya mereka tangani:

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

Perhatikan bahwa kita mungkin memiliki anotasi tingkat kelas serta tingkat metode. Sekarang, kita dapat membuat pengontrol yang mengimplementasikan antarmuka ini:

@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) {...} }

Kita tetap harus menambahkan anotasi tingkat kelas @RestController atau @Controller ke pengontrol kita. Didefinisikan dengan cara ini, pengontrol mewarisi semua anotasi yang terkait dengan pemetaan yang diminta web.

Untuk memeriksa apakah controller sekarang berfungsi seperti yang diharapkan, mari jalankan aplikasi dan tekan metode getAll () dengan membuat permintaan yang sesuai:

curl //localhost:8081/book/

Meskipun pengontrol mengimplementasikan antarmuka, kami selanjutnya dapat menyempurnakannya dengan menambahkan anotasi permintaan web. Kita dapat melakukannya dengan cara seperti yang kita lakukan untuk antarmuka: baik di tingkat kelas atau di tingkat metode. Faktanya, kami telah menggunakan kemungkinan ini saat mendefinisikan pengontrol:

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

Jika kita menambahkan anotasi permintaan web ke pengontrol, anotasi tersebut akan diutamakan daripada yang antarmuka. Dengan kata lain, Spring menafsirkan antarmuka pengontrol dengan cara yang mirip dengan cara Java menangani pewarisan.

Kami mendefinisikan semua properti permintaan web umum di antarmuka, tetapi di pengontrol, kami mungkin selalu menyempurnakannya.

3.3. Catatan Perhatian

Ketika kami memiliki antarmuka dan berbagai pengontrol yang menerapkannya, kami mungkin berakhir dengan situasi ketika permintaan web dapat ditangani dengan lebih dari satu metode. Secara alami, Spring akan mengeluarkan pengecualian:

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

Jika kita mendekorasi pengontrol dengan @RequestMapping , kita dapat mengurangi risiko pemetaan yang ambigu.

4. Kesimpulan

Dalam tutorial ini, kami telah mempertimbangkan fitur baru yang diperkenalkan di Spring 5.1. Sekarang, ketika pengendali MVC Spring mengimplementasikan sebuah antarmuka, mereka melakukan ini tidak hanya dengan cara Java standar tetapi juga mewarisi semua fungsionalitas terkait permintaan web yang ditentukan dalam antarmuka.

Seperti biasa, kami mungkin menemukan cuplikan kode yang sesuai di repositori GitHub kami.