आपका मानक स्प्रिंग MVC एप्लिकेशन DispatcherServletआपके द्वारा अपने सर्वलेट कंटेनर के साथ पंजीकृत किए गए सभी अनुरोधों को पूरा करेगा ।
DispatcherServletअपने दिखता है पर ApplicationContextऔर, यदि उपलब्ध है, ApplicationContextएक के साथ पंजीकृत ContextLoaderListenerविशेष सेम यह सेटअप अपने अनुरोध पेश करते तर्क की जरूरत के लिए। इन सेम को प्रलेखन में वर्णित किया गया है ।
संभवतः सबसे महत्वपूर्ण, प्रकार के HandlerMappingनक्शे की सेम
हैंडलर के लिए आने वाले अनुरोध और कुछ मानदंडों के आधार पर प्री- और पोस्ट-प्रोसेसर (हैंडलर इंटरसेप्टर) की एक सूची, जिसके विवरण HandlerMappingकार्यान्वयन के लिए अलग-अलग होते हैं । सबसे लोकप्रिय कार्यान्वयन एनोटेट नियंत्रकों का समर्थन करता है लेकिन अन्य कार्यान्वयन भी मौजूद हैं।
की जावाडोकHandlerMapping आगे बताता है कि कैसे कार्यान्वयन व्यवहार करना चाहिए।
DispatcherServlet(अनुकूलित किया जा सकता) इस प्रकार के सभी सेम पाता है और उन्हें कुछ क्रम में पंजीकृत करता है। एक अनुरोध की सेवा करते समय, DispatcherServletइन HandlerMappingवस्तुओं के माध्यम से छोरों और उनमें से प्रत्येक को getHandlerएक खोजने के लिए परीक्षण करता है जो आने वाले अनुरोध को संभाल सकता है, मानक के रूप में दर्शाया गया है HttpServletRequest। 4.3.x के रूप में, अगर यह किसी भी नहीं मिल रहा है , यह चेतावनी लॉग कि आप देख
कोई मैपिंग यूआरआई के साथ HTTP अनुरोध के लिए पाया [/some/path]में DispatcherServletनाम SomeName साथ
और या तो फेंकता है NoHandlerFoundExceptionया तुरंत 404 Not Found स्टेटस कोड के साथ प्रतिक्रिया देता है।
ऐसा क्यों नहीं DispatcherServletमिला जो HandlerMappingमेरे अनुरोध को संभाल सके?
सबसे आम HandlerMappingकार्यान्वयन है RequestMappingHandlerMapping, जो @Controllerबीन्स को हैंडलर के रूप में दर्ज करना संभालता है (वास्तव में उनके @RequestMappingएनोटेट तरीके)। आप या तो स्वयं ( @Beanया <bean>या अन्य तंत्र के साथ) इस प्रकार की सेम की घोषणा कर सकते हैं या आप अंतर्निहित विकल्पों का उपयोग कर सकते हैं । य़े हैं:
- अपनी
@Configurationकक्षा के साथ एनोटेट करें @EnableWebMvc।
<mvc:annotation-driven />अपने XML कॉन्फ़िगरेशन में एक सदस्य की घोषणा करें।
जैसा कि ऊपर दिए गए लिंक में बताया गया है, ये दोनों एक RequestMappingHandlerMappingबीन (और अन्य सामान का एक गुच्छा) पंजीकृत करेंगे । हालांकि, HandlerMappingएक हैंडलर के बिना बहुत उपयोगी नहीं है। RequestMappingHandlerMappingकुछ @Controllerबीन्स की अपेक्षा करता है, इसलिए आपको @Beanजावा कॉन्फ़िगरेशन में विधियों के माध्यम से या <bean>एक्सएमएल कॉन्फ़िगरेशन में घोषणा या @Controllerएनोटेट कक्षाओं के घटक स्कैनिंग के माध्यम से भी घोषित करने की आवश्यकता है । सुनिश्चित करें कि ये फलियाँ मौजूद हैं।
यदि आपको चेतावनी संदेश और 404 मिल रहे हैं और आपने उपरोक्त सभी को सही तरीके से कॉन्फ़िगर किया है, तो आप अपना अनुरोध गलत यूआरआई को भेज रहे हैं , जो कि एक पता लगाए @RequestMappingगए हैंडलर विधि द्वारा नियंत्रित नहीं किया गया है ।
spring-webmvcअन्य पुस्तकालय प्रदान करता है निर्मित HandlerMappingकार्यान्वयन। उदाहरण के लिए, BeanNameUrlHandlerMappingनक्शे
स्लैश ("/") से शुरू होने वाले नामों के URL से लेकर सेम तक
और आप हमेशा अपना लिख सकते हैं। जाहिर है, आपको यह सुनिश्चित करना होगा कि आप जिस अनुरोध को पंजीकृत HandlerMappingऑब्जेक्ट के हैंडलर में से कम से कम एक मैच भेज रहे हैं ।
यदि आप किसी भी HandlerMappingसेम (या यदि detectAllHandlerMappingsहै true) को स्पष्ट रूप से या स्पष्ट रूप से पंजीकृत नहीं करते हैं , तो DispatcherServletकुछ चूक रजिस्टर करता है । इन्हें कक्षा DispatcherServlet.propertiesके समान पैकेज में परिभाषित किया गया है DispatcherServlet। वे हैं BeanNameUrlHandlerMappingऔर DefaultAnnotationHandlerMapping(जो कि RequestMappingHandlerMappingपदावनत के समान है )।
डिबगिंग
स्प्रिंग एमवीसी के माध्यम से पंजीकृत हैंडलर लॉग इन करेंगे RequestMappingHandlerMapping। उदाहरण के लिए, एक @Controllerपसंद है
@Controller
public class ExampleController {
@RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
public String example() {
return "example-view-name";
}
}
INFO स्तर पर निम्न लॉग करेगा
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
यह पंजीकृत मैपिंग का वर्णन करता है। जब आप यह चेतावनी देखते हैं कि कोई हैंडलर नहीं मिला, तो संदेश में URI की तुलना यहां सूचीबद्ध मैपिंग से करें। @RequestMappingस्प्रिंग एमवीसी को हैंडलर का चयन करने के लिए निर्दिष्ट सभी प्रतिबंधों का मिलान करना चाहिए।
अन्य HandlerMappingकार्यान्वयन अपने स्वयं के बयानों को लॉग करते हैं जो उनके मैपिंग और उनके संबंधित हैंडलर को संकेत देना चाहिए।
इसी प्रकार, स्प्रिंग को डीबग स्तर पर लॉगिंग को सक्षम करने के लिए यह देखने के लिए कि कौन सी फलियां स्प्रिंग रजिस्टर करती हैं। यह रिपोर्ट करना चाहिए कि यह किस एनोटेट वर्ग को पाता है, जो इसे स्कैन करता है, और यह किन बीन्स को आरंभ करता है। यदि आप जो उम्मीद करते हैं वह मौजूद नहीं है, तो अपने ApplicationContextकॉन्फ़िगरेशन की समीक्षा करें ।
अन्य सामान्य गलतियाँ
A DispatcherServletकेवल एक विशिष्ट जावा EE है Servlet। आप इसे अपने टिपिकल <web.xml> <servlet-class>और <servlet-mapping>डिक्लेरेशन के साथ, या सीधे किसी भी माध्यम ServletContext#addServletसे WebApplicationInitializer, या स्प्रिंग मेकेनिज्म के साथ रजिस्टर कर सकते हैं । इस प्रकार, आपको सर्वलेट विनिर्देश में निर्दिष्ट url मैपिंग तर्क पर भरोसा करना चाहिए , अध्याय 12 देखें। यह भी देखें
इसे ध्यान में रखते हुए, एक सामान्य गलती DispatcherServletएक यूआरएल मैपिंग के साथ रजिस्टर करना है /*, एक @RequestMappingहैंडलर विधि से एक दृश्य नाम वापस करना , और एक जेएसपी को प्रस्तुत करने की अपेक्षा करना। उदाहरण के लिए, एक हैंडलर विधि पर विचार करें
@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
return "example-view-name";
}
एक साथ InternalResourceViewResolver
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
आप पथ पर एक JSP संसाधन को भेजे जाने के अनुरोध की अपेक्षा कर सकते हैं /WEB-INF/jsps/example-view-name.jsp। ऐसा नहीं होगा। इसके बजाय, एक संदर्भ नाम मानते हुए Example, DisaptcherServletरिपोर्ट करेगा
कोई मैपिंग यूआरआई के साथ HTTP अनुरोध के लिए पाया [/Example/WEB-INF/jsps/example-view-name.jsp]में DispatcherServletनाम 'डिस्पैचर' के साथ
क्योंकि सभी चीज़ों के DispatcherServletलिए मैप किया जाता है /*और /*मेल खाता है (सटीक मैचों को छोड़कर, जिनकी प्राथमिकता अधिक है), को (से लौटाए गए ) से DispatcherServletनिपटने के लिए चुना जाएगा । लगभग हर मामले में, इस तरह के अनुरोध को संभालने के लिए कॉन्फ़िगर नहीं किया जाएगा ।forwardJstlViewInternalResourceViewResolverDispatcherServlet
इसके बजाय, इस साधारण मामले में, आप पंजीकरण करना होगा DispatcherServletकरने के लिए /, डिफ़ॉल्ट सर्वलेट के रूप में यह अंकन। डिफ़ॉल्ट सर्वलेट अनुरोध के लिए अंतिम मैच है। यह आपके सामान्य सर्वलेट कंटेनर को डिफ़ॉल्ट सर्वलेट के साथ प्रयास करने से पहले *.jspजेएसपी संसाधन (उदाहरण के लिए, टॉमकैट है JspServlet) को संभालने के लिए मैप किए गए आंतरिक सर्वलेट कार्यान्वयन को चुनने की अनुमति देगा ।
यही आप अपने उदाहरण में देख रहे हैं।