Panduan untuk Pemetaan Penangan Musim Semi

1. Perkenalan

Di Spring MVC, DispatcherServlet bertindak sebagai pengontrol depan - menerima semua permintaan HTTP yang masuk dan memprosesnya.

Sederhananya, pemrosesan terjadi dengan meneruskan permintaan ke komponen yang relevan dengan bantuan pemetaan handler .

HandlerMapping adalah antarmuka yang mendefinisikan pemetaan antara request dan objek handler. Sementara kerangka MVC Spring menyediakan beberapa implementasi yang sudah jadi, antarmuka dapat diterapkan oleh pengembang untuk menyediakan strategi pemetaan yang disesuaikan.

Artikel ini membahas beberapa implementasi yang disediakan oleh Spring MVC yaitu BeanNameUrlHandlerMapping , SimpleUrlHandlerMapping , ControllerClassNameHandlerMapping , konfigurasinya, dan perbedaan di antara keduanya.

2. BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping adalah implementasi HandlerMapping default . BeanNameUrlHandlerMapping memetakan meminta URL ke kacang dengan nama yang sama.

Pemetaan khusus ini memiliki dukungan untuk pencocokan nama langsung dan juga untuk pencocokan pola menggunakan pola "*".

Misalnya, URL masuk "/ foo" dipetakan ke kacang yang disebut "/ foo" . Contoh pemetaan pola adalah memetakan permintaan ke "/ foo *" ke kacang dengan nama yang dimulai dengan "/ foo" seperti "/ foo2 /" atau "/ fooOne /" .

Mari konfigurasikan contoh ini di sini dan daftarkan pengontrol kacang yang menangani permintaan ke "/ beanNameUrl" :

@Configuration public class BeanNameUrlHandlerMappingConfig { @Bean BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() { return new BeanNameUrlHandlerMapping(); } @Bean("/beanNameUrl") public WelcomeController welcome() { return new WelcomeController(); } }

Ini adalah XML yang setara dengan konfigurasi berbasis Java di atas:

Penting untuk dicatat bahwa dalam kedua konfigurasi ini, mendefinisikan bean untuk BeanNameUrlHandlerMapping tidak diperlukan karena disediakan oleh Spring MVC. Menghapus definisi kacang ini tidak akan menimbulkan masalah dan permintaan akan tetap dipetakan ke kacang pengendali terdaftar mereka.

Sekarang semua permintaan ke "/ beanNameUrl" akan diteruskan oleh DispatcherServlet ke " WelcomeController ". WelcomeController mengembalikan nama tampilan yang disebut " welcome ".

Kode berikut menguji konfigurasi ini dan memastikan bahwa nama tampilan yang benar dikembalikan:

public class BeanNameMappingConfigTest { // ... @Test public void whenBeanNameMapping_thenMappedOK() { mockMvc.perform(get("/beanNameUrl")) .andExpect(status().isOk()) .andExpect(view().name("welcome")); } }

3. SimpleUrlHandlerMapping

Selanjutnya, SimpleUrlHandlerMapping adalah implementasi HandlerMapping yang paling fleksibel . Ini memungkinkan pemetaan langsung dan deklaratif antara instance kacang dan URL atau antara nama kacang dan URL.

Mari petakan permintaan “/ simpleUrlWelcome” dan “/ * / simpleUrlWelcome” ke bean “welcome” :

@Configuration public class SimpleUrlHandlerMappingConfig { @Bean public SimpleUrlHandlerMapping simpleUrlHandlerMapping() { SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping(); Map urlMap = new HashMap(); urlMap.put("/simpleUrlWelcome", welcome()); simpleUrlHandlerMapping.setUrlMap(urlMap); return simpleUrlHandlerMapping; } @Bean public WelcomeController welcome() { return new WelcomeController(); } }

Atau, berikut konfigurasi XML yang setara:

   /simpleUrlWelcome=welcome /*/simpleUrlWelcome=welcome    

Penting untuk diperhatikan bahwa dalam konfigurasi XML, pemetaan antara tag "" harus dilakukan dalam bentuk yang diterima oleh kelas java.util.Properties dan harus mengikuti sintaks: path = Handler_Bean_Name .

URL biasanya harus dengan garis miring di depan, namun, jika jalur tidak dimulai dengan satu, Spring MVC menambahkannya secara otomatis.

Cara lain untuk mengonfigurasi contoh di atas dalam XML adalah dengan menggunakan properti "props" , bukan "value" . Alat peraga memiliki daftar tag "prop" di mana masing-masing mendefinisikan pemetaan di mana "kunci" merujuk ke URL yang dipetakan dan nilai tagnya adalah nama kacang.

   welcome welcome   

Kasus uji berikut memastikan bahwa permintaan ke "/ simpleUrlWelcome " ditangani oleh " WelcomeController" yang mengembalikan nama tampilan yang disebut "welcome" :

public class SimpleUrlMappingConfigTest { // ... @Test public void whenSimpleUrlMapping_thenMappedOK() { mockMvc.perform(get("/simpleUrlWelcome")) .andExpect(status().isOk()) .andExpect(view().name("welcome")); } }

4. ControllerClassNameHandlerMapping (dihapus di Spring 5)

The ControllerClassNameHandlerMapping peta URL ke controller kacang terdaftar (atau controller dijelaskan dengan @Controller penjelasan) yang memiliki, atau dimulai dengan, nama yang sama.

Ini bisa lebih mudah dalam banyak skenario terutama untuk implementasi pengontrol sederhana yang menangani satu jenis permintaan. Konvensi yang digunakan oleh Spring MVC adalah menggunakan nama kelas dan menghapus sufiks “Controller” , kemudian mengubah nama menjadi huruf kecil dan mengembalikannya sebagai pemetaan dengan awalan “/” .

Misalnya "WelcomeController" akan kembali sebagai pemetaan ke "/ welcome *" , yaitu ke URL apa pun yang dimulai dengan "welcome" .

Mari kita konfigurasikan ControllerClassNameHandlerMapping :

@Configuration public class ControllerClassNameHandlerMappingConfig { @Bean public ControllerClassNameHandlerMapping controllerClassNameHandlerMapping() { return new ControllerClassNameHandlerMapping(); } @Bean public WelcomeController welcome() { return new WelcomeController(); } }

Perhatikan bahwa ControllerClassNameHandlerMapping tidak digunakan lagi dari Spring 4.3 karena mendukung metode penangan yang didorong anotasi.

Catatan penting lainnya adalah bahwa nama pengontrol akan selalu dikembalikan dalam huruf kecil (tanpa akhiran "Pengontrol"). Jadi jika kita memiliki pengontrol bernama " WelcomeBaeldungController ", itu hanya akan menangani permintaan ke "/ welcomebaeldung" dan bukan ke "/ welcomeBaeldung" .

Dalam konfigurasi Java dan konfigurasi XML di bawah ini, kita mendefinisikan bean ControllerClassNameHandlerMapping dan meregistrasi bean untuk pengontrol yang akan kita gunakan untuk menangani permintaan. Kami juga mendaftarkan kacang jenis "WelcomeController" dan kacang itu akan menangani semua permintaan yang dimulai dengan "/ welcome" .

Berikut konfigurasi XML yang setara:

Saat menggunakan konfigurasi di atas, permintaan ke "/ welcome " akan ditangani oleh " WelcomeController ".

Kode berikut akan memastikan bahwa permintaan ke "/ welcome *" seperti "/ welcometest " ditangani oleh "WelcomeController" yang mengembalikan nama tampilan yang disebut " welcome ":

public class ControllerClassNameHandlerMappingTest { // ... @Test public void whenControllerClassNameMapping_thenMappedOK() { mockMvc.perform(get("/welcometest")) .andExpect(status().isOk()) .andExpect(view().name("welcome")); } }

5. Konfigurasi Prioritas

Kerangka MVC Spring memungkinkan lebih dari satu implementasi antarmuka HandlerMapping pada saat yang bersamaan.

Mari kita membuat konfigurasi dan mendaftarkan dua pengontrol, keduanya dipetakan ke URL "/ welcome", hanya menggunakan pemetaan yang berbeda dan menampilkan nama tampilan yang berbeda:

@Configuration public class HandlerMappingDefaultConfig { @Bean("/welcome") public BeanNameHandlerMappingController beanNameHandlerMapping() { return new BeanNameHandlerMappingController(); } @Bean public WelcomeController welcome() { return new WelcomeController(); } }

Tanpa mapper penangan eksplisit yang terdaftar, BeanNameHandlerMapping default akan digunakan. Mari kita tegaskan perilaku ini dengan tes:

@Test public void whenConfiguringPriorities_thenMappedOK() { mockMvc.perform(get("/welcome")) .andExpect(status().isOk()) .andExpect(view().name("bean-name-handler-mapping")); } 

Jika kita secara eksplisit mendaftarkan mapper penangan yang berbeda, mapper default akan diganti. Namun, menarik untuk melihat apa yang terjadi ketika dua pembuat peta terdaftar secara eksplisit:

@Configuration public class HandlerMappingPrioritiesConfig { @Bean BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() { BeanNameUrlHandlerMapping beanNameUrlHandlerMapping = new BeanNameUrlHandlerMapping(); return beanNameUrlHandlerMapping; } @Bean public SimpleUrlHandlerMapping simpleUrlHandlerMapping() { SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping(); Map urlMap = new HashMap(); urlMap.put("/welcome", simpleUrlMapping()); simpleUrlHandlerMapping.setUrlMap(urlMap); return simpleUrlHandlerMapping; } @Bean public SimpleUrlMappingController simpleUrlMapping() { return new SimpleUrlMappingController(); } @Bean("/welcome") public BeanNameHandlerMappingController beanNameHandlerMapping() { return new BeanNameHandlerMappingController(); } }

Untuk mendapatkan kontrol atas pemetaan mana yang digunakan, prioritas ditetapkan menggunakan metode setOrder (int order) . Metode ini mengambil satu parameter int dimana nilai yang lebih rendah berarti prioritas yang lebih tinggi.

Dalam konfigurasi XML Anda dapat mengonfigurasi prioritas dengan menggunakan properti yang disebut "order" :

Mari kita tambahkan properti order ke kacang pemetaan handler, melalui beanNameUrlHandlerMapping.setOrder (1) dan simpleUrlHandlerMapping.setOrder (0) berikut. Nilai yang lebih rendah dari properti pesanan mencerminkan prioritas yang lebih tinggi. Mari kita tegaskan perilaku baru dengan tes:

@Test public void whenConfiguringPriorities_thenMappedOK() { mockMvc.perform(get("/welcome")) .andExpect(status().isOk()) .andExpect(view().name("simple-url-handler-mapping")); }

Saat menguji konfigurasi di atas, Anda melihat bahwa permintaan untuk "/ welcome" akan ditangani oleh kacang SimpleUrlHandlerMapping yang memanggil SimpleUrlHandlerController dan mengembalikan tampilan pemetaan-url-handler-sederhana . Kita dapat dengan mudah mengkonfigurasi BeanNameHandlerMapping agar lebih diutamakan dengan menyesuaikan nilai properti order .

6. Kesimpulan

Dalam artikel ini kita membahas bagaimana pemetaan URL ditangani dalam kerangka MVC Spring dengan menjelajahi implementasi yang berbeda dalam kerangka kerja.

Kode yang menyertai artikel ini dapat ditemukan di GitHub.