Aplikasi Spring MVC standar Anda akan melayani semua permintaan melalui DispatcherServlet
yang telah Anda daftarkan dengan container Servlet Anda.
The DispatcherServlet
terlihat di perusahaan ApplicationContext
dan, jika tersedia, ApplicationContext
terdaftar dengan ContextLoaderListener
biji khusus perlu untuk setup permintaannya melayani logika. Kacang ini dijelaskan dalam dokumentasi .
Bisa dibilang yang paling penting, kacang HandlerMapping
peta tipe
permintaan masuk ke penangan dan daftar pemroses sebelum dan sesudah (penangan penangan) berdasarkan beberapa kriteria yang rinciannya berbeda-beda menurut HandlerMapping
penerapan. Implementasi yang paling populer mendukung pengontrol beranotasi, tetapi implementasi lain juga ada.
The javadoc dariHandlerMapping
lebih lanjut menjelaskan bagaimana implementasi harus berperilaku.
The DispatcherServlet
menemukan semua kacang jenis ini dan register mereka dalam beberapa urutan (dapat disesuaikan). Saat melayani permintaan, DispatcherServlet
loop melalui HandlerMapping
objek - objek ini dan menguji masing-masing objek dengan getHandler
untuk menemukan satu yang dapat menangani permintaan masuk, direpresentasikan sebagai standar HttpServletRequest
. Pada 4.3.x, jika tidak menemukannya , ia mencatat peringatan yang Anda lihat
Tidak ada pemetaan ditemukan untuk permintaan HTTP dengan URI [/some/path]
di DispatcherServlet
dengan nama somename
dan baik melemparkan NoHandlerFoundException
atau segera melakukan respon dengan kode status 404 Not Found.
Mengapa tidak DispatcherServlet
menemukan HandlerMapping
yang bisa menangani permintaan saya?
HandlerMapping
Implementasi yang paling umum adalah RequestMappingHandlerMapping
, yang menangani pendaftaran @Controller
kacang sebagai penangan (sebenarnya @RequestMapping
metode beranotasi mereka ). Anda dapat mendeklarasikan kacang jenis ini sendiri (dengan @Bean
atau <bean>
atau mekanisme lain) atau Anda dapat menggunakan opsi bawaan . Ini adalah:
- Beri anotasi pada
@Configuration
kelas Anda dengan @EnableWebMvc
.
- Deklarasikan
<mvc:annotation-driven />
anggota dalam konfigurasi XML Anda.
Seperti yang dijelaskan tautan di atas, keduanya akan mendaftarkan RequestMappingHandlerMapping
kacang (dan banyak hal lainnya). Namun, a HandlerMapping
tidak terlalu berguna tanpa pawang. RequestMappingHandlerMapping
mengharapkan beberapa @Controller
bean sehingga Anda perlu mendeklarasikannya juga, melalui @Bean
metode dalam konfigurasi Java atau <bean>
deklarasi dalam konfigurasi XML atau melalui pemindaian komponen @Controller
kelas beranotasi di keduanya. Pastikan kacang ini ada.
Jika Anda mendapatkan pesan peringatan dan 404 dan telah mengonfigurasi semua hal di atas dengan benar, maka Anda mengirimkan permintaan Anda ke URI yang salah , yang tidak ditangani oleh @RequestMapping
metode penangan beranotasi yang terdeteksi .
The spring-webmvc
penawaran perpustakaan lain built-in HandlerMapping
implementasi. Misalnya, BeanNameUrlHandlerMapping
peta
dari URL ke kacang dengan nama yang dimulai dengan garis miring ("/")
dan Anda selalu bisa menulis sendiri. Jelas, Anda harus memastikan permintaan yang Anda kirim cocok dengan setidaknya salah satu HandlerMapping
penangan objek terdaftar .
Jika Anda tidak secara implisit atau eksplisit mendaftarkan HandlerMapping
kacang apa pun (atau jika detectAllHandlerMappings
ada true
), DispatcherServlet
register beberapa default . Ini didefinisikan dalam DispatcherServlet.properties
paket yang sama dengan DispatcherServlet
kelas. Mereka adalah BeanNameUrlHandlerMapping
dan DefaultAnnotationHandlerMapping
(yang serupa RequestMappingHandlerMapping
tetapi tidak digunakan lagi).
Debugging
MVC Spring akan mencatat penangan yang terdaftar melalui RequestMappingHandlerMapping
. Misalnya, @Controller
suka
@Controller
public class ExampleController {
@RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
public String example() {
return "example-view-name";
}
}
akan mencatat berikut ini di tingkat INFO
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
Ini menggambarkan pemetaan yang terdaftar. Jika Anda melihat peringatan bahwa tidak ada penangan yang ditemukan, bandingkan URI dalam pesan dengan pemetaan yang tercantum di sini. Semua batasan yang ditentukan dalam @RequestMapping
harus cocok untuk Spring MVC untuk memilih penangan.
HandlerMapping
Implementasi lain mencatat pernyataan mereka sendiri yang seharusnya mengisyaratkan pemetaan mereka dan penangannya yang sesuai.
Demikian pula, aktifkan pencatatan Musim Semi pada tingkat DEBUG untuk melihat kacang mana yang didaftarkan Spring. Itu harus melaporkan kelas beranotasi mana yang ditemukannya, paket mana yang dipindai, dan kacang mana yang diinisialisasi. Jika yang Anda harapkan tidak ada, tinjau ApplicationContext
konfigurasi Anda .
Kesalahan umum lainnya
A DispatcherServlet
hanyalah Java EE tipikal Servlet
. Anda mendaftar dengan khas <web.xml>
<servlet-class>
dan <servlet-mapping>
deklarasi, atau langsung melalui ServletContext#addServlet
dalam WebApplicationInitializer
, atau dengan mekanisme apapun yang menggunakan Musim Semi booting. Karena itu, Anda harus mengandalkan pemetaan url logika ditentukan dalam spesifikasi Servlet , lihat Bab 12. Lihat juga
Dengan mengingat hal tersebut, kesalahan umum adalah mendaftarkan DispatcherServlet
dengan pemetaan url /*
, mengembalikan nama tampilan dari a@RequestMapping
metode penangan, dan mengharapkan JSP untuk dirender. Misalnya, pertimbangkan metode penangan seperti
@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
return "example-view-name";
}
dengan sebuah InternalResourceViewResolver
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
Anda mungkin mengharapkan permintaan diteruskan ke sumber daya JSP di jalur /WEB-INF/jsps/example-view-name.jsp
. Ini tidak akan terjadi. Sebaliknya, dengan asumsi nama konteksExample
, DisaptcherServlet
akan melaporkan
Tidak ada pemetaan yang ditemukan untuk permintaan HTTP dengan URI [/Example/WEB-INF/jsps/example-view-name.jsp]
diDispatcherServlet
dengan nama 'operator'
Karena DispatcherServlet
dipetakan ke /*
dan /*
cocok dengan semuanya (kecuali kecocokan persis, yang memiliki prioritas lebih tinggi), DispatcherServlet
akan dipilih untuk menangani forward
dari JstlView
(dikembalikan oleh InternalResourceViewResolver
). Di hampir setiap kasus, DispatcherServlet
tidak akan dikonfigurasi untuk menangani permintaan seperti itu .
Sebaliknya, dalam kasus sederhana ini, Anda harus mendaftarkan DispatcherServlet
ke /
, menandainya sebagai servlet default. Servlet default adalah kecocokan terakhir untuk permintaan. Ini akan memungkinkan wadah servlet khas Anda untuk memilih implementasi Servlet internal, yang dipetakan ke*.jsp
, untuk menangani sumber daya JSP (misalnya, Tomcat memiliki JspServlet
), sebelum mencoba dengan servlet default.
Itulah yang Anda lihat dalam contoh Anda.
@EnableWebMvc
pada@Configuration
kelas yang dianotasi tidak melakukan itu. Yang dilakukannya hanyalah menambahkan sejumlah kacang penangan / adaptor MVC Spring default ke konteks aplikasi. MendaftarkanDispatcherServlet
untuk melayani/
adalah proses yang sepenuhnya terpisah yang dilakukan dengan beberapa cara yang saya jelaskan di bagian Kesalahan umum lainnya . Saya menjawab pertanyaan yang diajukan dua paragraf di bawah ini apa yang Anda kutip.Saya menyelesaikan masalah saya saat selain dijelaskan sebelumnya: `
@Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; }
added tomcat-embed-jasper:
`from: File JSP tidak dirender dalam aplikasi web Spring Boot
sumber
Dalam kasus saya, saya mengikuti dokumentasi Interceptors Spring untuk versi 5.1.2 (saat menggunakan Spring Boot v2.0.4.RELEASE ) dan
WebConfig
kelas memiliki anotasi@EnableWebMvc
, yang tampaknya bertentangan dengan hal lain dalam aplikasi saya yang mencegah statis saya. aset agar tidak diselesaikan dengan benar (yaitu tidak ada file CSS atau JS yang dikembalikan ke klien).Setelah mencoba banyak hal yang berbeda, saya mencoba menghapus yang
@EnableWebMvc
dan bekerja!Edit: Berikut dokumentasi referensi yang mengatakan Anda harus menghapus
@EnableWebMvc
anotasiRupanya dalam kasus saya setidaknya, saya sudah mengkonfigurasi aplikasi Spring saya (walaupun tidak dengan menggunakan
web.xml
atau file statis lainnya, itu pasti secara terprogram), jadi ada konflik di sana.sumber
Cobalah untuk mengubah kode Anda dengan perubahan berikut pada file konfigurasi Anda. Konfigurasi Java digunakan sebagai pengganti
application.properties
. Jangan lupa untuk mengaktifkan konfigurasi diconfigureDefaultServletHandling
metode.@Configuration @EnableWebMvc @ComponentScan public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/views/", ".jsp"); } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
Saya menggunakan gradle, Anda harus memiliki dependensi berikut di
pom.xml
:dependencies { compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.3.0.RELEASE' compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.35' }
sumber
Saya menemukan alasan lain untuk kesalahan yang sama. Ini juga bisa terjadi karena file kelas tidak dibuat untuk file controller.java Anda. Akibatnya servlet operator yang disebutkan di web.xml tidak dapat memetakannya ke metode yang sesuai di kelas pengontrol.
@Controller Class Controller{ @RequestMapping(value="/abc.html")//abc is the requesting page public void method() {.....} }
Dalam gerhana di bawah Proyek-> pilih bersih -> Bangun Proyek. Lakukan centang apakah file kelas telah dibuat untuk file pengontrol di bawah membangun di ruang kerja Anda.
sumber
Bagi saya, saya menemukan bahwa kelas target saya dibuat dalam pola folder yang tidak sama dengan sumber. Ini mungkin di gerhana saya menambahkan folder untuk menampung pengontrol saya dan tidak menambahkannya sebagai paket. Jadi saya akhirnya menentukan jalur yang salah dalam konfigurasi musim semi.
Kelas target saya menghasilkan kelas di bawah aplikasi dan saya mengacu pada com.happy.app
<context:annotation-config /> <context:component-scan base-package="com.happy.app"></context:component-scan>
Saya menambahkan paket (bukan folder) untuk com.happy.app dan memindahkan file dari folder ke paket di eclipse dan itu menyelesaikan masalah.
sumber
Bersihkan server Anda. Mungkin hapus server dan tambahkan proyek sekali lagi dan Jalankan.
Hentikan server Tomcat
Klik kanan server dan pilih "Bersihkan"
Klik kanan server lagi dan pilih "Clean Tomcat Work Directory"
sumber
Dalam kasus saya, saya bermain-main dengan mengimpor file konfigurasi java sekunder ke file konfigurasi java utama. Saat membuat file konfigurasi sekunder, saya telah mengubah nama kelas konfigurasi utama, tetapi saya gagal memperbarui nama di web.xml. Jadi, setiap kali saya me-restart server kucing jantan saya, saya tidak melihat penangan pemetaan dicatat di konsol Eclipse IDE, dan ketika saya mencoba menavigasi ke halaman beranda saya, saya melihat kesalahan ini:
Perbaikannya adalah memperbarui file web.xml sehingga nama lama "WebConfig" akan menjadi "MainConfig", cukup ganti namanya untuk mencerminkan nama terbaru dari file konfigurasi java utama (di mana "MainConfig" berubah-ubah dan kata-kata " Web "dan" Main "yang digunakan di sini bukan merupakan persyaratan sintaks). MainConfig penting, karena itu adalah file yang melakukan pemindaian komponen untuk "WebController", kelas pengontrol mvc pegas saya yang menangani permintaan web saya.
@ComponentScan(basePackageClasses={WebController.class})
web.xml memiliki ini:
file web.xml sekarang memiliki:
Sekarang saya melihat pemetaan di jendela konsol:
Dan halaman web saya dimuat lagi.
sumber
Saya memiliki masalah yang sama seperti
**No mapping found for HTTP request with URI [/some/path] in DispatcherServlet with name SomeName**
Setelah saya menganalisa selama 2 sampai 4 hari saya menemukan akar penyebabnya. File kelas tidak dibuat setelah saya menjalankan proyek. Saya mengklik tab proyek.
File kelas untuk kode sumber telah dibuat. Itu memecahkan masalah saya. Untuk memeriksa apakah file kelas telah dibuat atau tidak, Silakan periksa folder Build di folder proyek Anda.
sumber