Pertanyaan Memahami Cara Kerja @RequestMapping POST Musim Semi MVC


Saya memiliki Kontroler sederhana yang terlihat seperti ini: -

@Controller
@RequestMapping(value = "/groups")
public class GroupsController {
    // mapping #1
    @RequestMapping(method = RequestMethod.GET)
    public String main(@ModelAttribute GroupForm groupForm, Model model) {
        ...
    }

    // mapping #2
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String changeGroup(@PathVariable Long id, @ModelAttribute GroupForm groupForm, Model model) {
        ...
    }

    // mapping #3
    @RequestMapping(method = RequestMethod.POST)
    public String save(@Valid @ModelAttribute GroupForm groupForm, BindingResult bindingResult, Model model) {
        ...
    }
}

Pada dasarnya, halaman ini memiliki fungsi sebagai berikut: -

  • Halaman utama kunjungan pengguna (/groups GET).
  • Pengguna membuat grup baru (/groups POST) atau memilih grup tertentu (/groups/1 GET).
  • Pengguna mengedit grup yang sudah ada (/groups/1 POST).

Saya memahami bagaimana keduanya MENDAPATkan pemetaan berfungsi di sini. Pemetaan # 2 didefinisikan, sebaliknya (/groups/1 GET) akan menyebabkan pengecualian "Tidak ditemukan pemetaan".

Yang saya coba pahami di sini adalah mengapa pemetaan # 3 menangani keduanya (/groups POST) dan (/groups/1 POST)? Masuk akal bahwa itu harus ditangani (/groups POST) di sini karena pemetaan permintaan sesuai dengan URI. Mengapa/groups/1 POST) tidak menyebabkan pengecualian "Tidak ditemukan pemetaan" yang dibuang di sini? Bahkan, hampir tampak seperti POST dengan URI dimulai dengan / grup (misalnya: /groups/bla/1 POST) juga akan ditangani oleh pemetaan # 3.

Bisakah seseorang memberikan penjelasan yang jelas tentang hal ini kepada saya? Terimakasih banyak.

KLARIFIKASI

Saya memahami fakta bahwa saya dapat menggunakan metode yang lebih tepat (seperti GET, POST, PUT, atau DELETE) ... atau saya dapat membuat pemetaan permintaan lain untuk menangani /groups/{id} POST.

Namun, yang ingin saya ketahui adalah ...

.... "Mengapa pemetaan # 3 ditangani /groups/1 POST terlalu?"

Alasan "pencocokan terdekat" tampaknya tidak berlaku karena jika saya menghapus pemetaan # 2, maka saya akan berpikir pemetaan # 1 akan ditangani /groups/1 GET, tetapi tidak dan itu menyebabkan pengecualian "Tidak ditemukan pemetaan".

Saya hanya sedikit bingung di sini.


32
2018-03-16 13:49


asal


Jawaban:


Ini rumit, saya pikir lebih baik membaca kode.

Di Musim Semi 3.0 Sihir dilakukan dengan metode public Method resolveHandlerMethod(HttpServletRequest request) dari kelas batin ServletHandlerMethodResolver dari org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.

Instance dari kelas ini ada untuk setiap Kelas Pengontrol Permintaan, dan memiliki bidang handlerMethods yang berisi daftar semua metode permintaan.

Tapi biarkan saya meringkas bagaimana saya memahaminya

  • Musim semi pertama memeriksa apakah setidaknya satu metode pencocokan handler (ini dapat berisi negatif palsu)
  • Kemudian ia membuat peta dari semua metode handler yang benar-benar cocok
  • Lalu mengurutkan peta berdasarkan jalur permintaan: RequestSpecificMappingInfoComparator
  • dan mengambil yang pertama

Penyortiran bekerja dengan cara ini: RequestSpecificMappingInfoComparator pertama membandingkan jalan dengan bantuan suatu AntPathMatcher, jika dua metode sama menurut ini, maka metrik lainnya (seperti jumlah parameter, jumlah header, dll.) diperhitungkan sehubungan dengan permintaan tersebut.


19
2018-03-16 14:45



Musim semi mencoba untuk menemukan pemetaan yang cocok dengan yang terdekat.
Oleh karena itu, dalam kasus Anda dari setiap permintaan POST, satu-satunya peta yang ditemukan untuk jenis permintaan adalah Pemetaan # 3. Baik Pemetaan 1 atau Pemetaan 2 tidak sesuai dengan jenis permintaan Anda, dan karenanya diabaikan. Mungkin Anda dapat mencoba menghapus Pemetaan # 3, dan melihat bahwa Spring melempar kesalahan runtime karena tidak menemukan kecocokan!


2
2018-03-16 13:57



Saya akan menambahkan pemetaan PUT untuk / grup / {id}. Saya kira POST akan bekerja juga tetapi tidak benar-benar tepat dari perspektif HTTP.

menambahkan @RequestMapping ("/ {id}", POST) harus menutupnya?


1
2018-03-16 14:25



tambahkan @PathVariable ke parameter Long id dalam pemetaan # 2


-3
2018-03-16 14:10