स्प्रिंग एमवीसी 404 के साथ प्रतिक्रिया क्यों करता है और "डिस्पैसरसेर्वलेट में यूआरआई […] के साथ HTTP अनुरोध के लिए कोई मैपिंग नहीं मिली है?"


91

मैं टॉमकैट पर तैनात एक स्प्रिंग एमवीसी एप्लिकेशन लिख रहा हूं। निम्नलिखित न्यूनतम, पूर्ण और सत्यापित उदाहरण देखें

public class Application extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { };
    }
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { SpringServletConfig.class };
    }
    protected String[] getServletMappings() {
        return new String[] { "/*" };
    }
}

कहाँ SpringServletConfigहै

@Configuration
@ComponentScan("com.example.controllers")
@EnableWebMvc
public class SpringServletConfig {
    @Bean
    public InternalResourceViewResolver resolver() {
        InternalResourceViewResolver vr = new InternalResourceViewResolver();
        vr.setPrefix("/WEB-INF/jsps/");
        vr.setSuffix(".jsp");
        return vr;
    }
}

अंत में, मेरे पास @Controllerपैकेज में एक हैcom.example.controllers

@Controller
public class ExampleController {
    @RequestMapping(path = "/home", method = RequestMethod.GET)
    public String example() {
        return "index";
    }
}

मेरा आवेदन के संदर्भ नाम है Example। जब मैं एक अनुरोध भेजने के लिए

http://localhost:8080/Example/home

अनुप्रयोग HTTP स्थिति 404 के साथ प्रतिक्रिया करता है और निम्नलिखित को लॉग करता है

WARN  o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI `[/Example/WEB-INF/jsps/index.jsp]` in `DispatcherServlet` with name 'dispatcher'

मेरे पास जेएसपी संसाधन है, /WEB-INF/jsps/index.jspमैंने उम्मीद की थी कि स्प्रिंग एमवीसी अनुरोध और जेएसपी को आगे बढ़ाने के लिए अपने नियंत्रक का उपयोग करेगा, इसलिए यह 404 के साथ प्रतिक्रिया क्यों दे रहा है?


यह इस चेतावनी संदेश के बारे में प्रश्नों के लिए एक विहित पोस्ट होने का मतलब है।

जवाबों:


100

आपका मानक स्प्रिंग 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>या अन्य तंत्र के साथ) इस प्रकार की सेम की घोषणा कर सकते हैं या आप अंतर्निहित विकल्पों का उपयोग कर सकते हैं । य़े हैं:

  1. अपनी @Configurationकक्षा के साथ एनोटेट करें @EnableWebMvc
  2. <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) को संभालने के लिए मैप किए गए आंतरिक सर्वलेट कार्यान्वयन को चुनने की अनुमति देगा ।

यही आप अपने उदाहरण में देख रहे हैं।


@EnableWebMvc के साथ dispatcherServlet इसे पहले से पंजीकृत /। "आप पथ / WWEB-INF/jsps/example-view-name.jsp पथ पर JSP संसाधन के लिए भेजे जाने के अनुरोध की अपेक्षा कर सकते हैं। यह नहीं होगा।" आप इसे कैसे काम करते हैं ताकि यह उस रास्ते पर एक JSP संसाधन के लिए आगे बढ़े? यह मूल रूप से सवाल पूछा गया है।
टॉर

@ अपने आप @EnableWebMvcपर , एक @Configurationएनोटेट वर्ग पर ऐसा नहीं करता है। सभी यह आवेदन के संदर्भ में कई डिफ़ॉल्ट स्प्रिंग एमवीसी हैंडलर / एडेप्टर बीन्स को जोड़ते हैं। DispatcherServletसेवा करने के लिए पंजीकरण /करना एक पूरी तरह से अलग प्रक्रिया है जो कई तरीकों से की जाती है जो मैं अन्य सामान्य गलतियों वाले खंड में वर्णन करता हूं । मैं आपके द्वारा उद्धृत किए गए दो पैराग्राफ से पूछे गए प्रश्न का उत्तर देता हूं ।
सॉटिरियोस डेलिमोलिस

5

मैंने अपना मुद्दा हल किया जब पहले वर्णित के अलावा: `

@Bean
public InternalResourceViewResolver resolver() {
    InternalResourceViewResolver vr = new InternalResourceViewResolver();
    vr.setPrefix("/WEB-INF/jsps/");
    vr.setSuffix(".jsp");
    return vr;
}

added tomcat-embed-jasper:

<dependency>
       <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
       <scope>provided</scope>
</dependency>

`से: जेएसपी फ़ाइल स्प्रिंग बूट वेब अनुप्रयोग में प्रतिपादन नहीं


2

मेरे मामले में, मैं 5.1.2 संस्करण के लिए इंटरसेप्टर स्प्रिंग डॉक्यूमेंट का अनुसरण कर रहा था ( स्प्रिंग बूट v2.0.4.RELEASE का उपयोग करते हुए ) और WebConfigकक्षा में एनोटेशन था @EnableWebMvc, जो मेरे आवेदन में किसी और चीज के साथ विरोधाभासी प्रतीत हो रहा था, जो मेरे स्थैतिक को रोक रहा था संपत्तियों को सही तरीके से हल किया जा रहा है (अर्थात कोई सीएसएस या जेएस फाइलें ग्राहक को वापस नहीं की जा रही हैं)।

बहुत सारी अलग-अलग चीजों की कोशिश करने के बाद, मैंने इसे हटाने की कोशिश की @EnableWebMvcऔर यह काम कर गया!

संपादित करें: यहां संदर्भ प्रलेखन है जो कहता है कि आपको @EnableWebMvcएनोटेशन को हटा देना चाहिए

मेरे मामले में कम से कम, मैं पहले से ही अपने स्प्रिंग एप्लिकेशन को कॉन्फ़िगर कर रहा हूं (हालांकि web.xmlकिसी अन्य स्थिर फ़ाइल का उपयोग या उपयोग करके नहीं , यह निश्चित रूप से प्रोग्राम है), इसलिए यह एक संघर्ष था।


1

अपने कॉन्फिग फाइल पर निम्नलिखित बदलाव के साथ अपने कोड में संशोधन करने का प्रयास करें। जावा कॉन्फिग का उपयोग इसके बजाय किया जाता है application.propertiesconfigureDefaultServletHandlingविधि में कॉन्फ़िगरेशन को सक्षम करने के लिए मत भूलना ।

WebMvcConfigurerAdapterवर्ग को हटा दिया गया है, इसलिए हम WebMvcConfigurerइंटरफ़ेस का उपयोग करते हैं ।

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

मैं ग्रेडेल का उपयोग करता हूं, आपके पास निम्नलिखित निर्भरताएं होनी चाहिए 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'
}

0

मैं उसी त्रुटि के लिए एक और कारण भर में आया था। यह आपके कंट्रोलर.जवा फाइल के लिए उत्पन्न क्लास फाइल्स के कारण भी हो सकता है। जिसके परिणामस्वरूप डिस्पैचर सर्वलेट web.xml में उल्लिखित है, यह नियंत्रक वर्ग में उपयुक्त विधि से मैप करने में असमर्थ है।

@Controller
Class Controller{
@RequestMapping(value="/abc.html")//abc is the requesting page
public void method()
{.....}
}

प्रोजेक्ट के अंतर्गत ग्रहण में-> स्वच्छ का चयन करें -> प्रोजेक्ट बनाएँ। यदि आपके कार्यक्षेत्र में बिल्ड के तहत नियंत्रक फ़ाइल के लिए क्लास फ़ाइल उत्पन्न की गई है, तो चेक दें।


0

मेरे लिए, मैंने पाया कि मेरे लक्ष्य वर्ग स्रोत के समान फ़ोल्डर पैटर्न में उत्पन्न नहीं हुए थे। यह संभवतः ग्रहण में है मैं अपने नियंत्रकों के लिए फ़ोल्डर जोड़ता हूं और उन्हें पैकेज के रूप में नहीं जोड़ता हूं। इसलिए मैंने स्प्रिंग कॉन्फिग में गलत रास्ते को परिभाषित किया।

मेरा लक्ष्य वर्ग ऐप के तहत कक्षाएं उत्पन्न कर रहा था और मैं com.happy.app की बात कर रहा था

<context:annotation-config />
<context:component-scan
    base-package="com.happy.app"></context:component-scan> 

मैंने com.happy.app के लिए संकुल (फ़ोल्डर नहीं) जोड़े और ग्रहण में फ़ोल्डर से संकुल में फाइल को स्थानांतरित किया और इसने समस्या का समाधान किया।


0

अपने सर्वर को साफ करें। शायद सर्वर को हटा दें और परियोजना को एक बार फिर से जोड़ें और चलाएँ।

  1. टॉमकैट सर्वर बंद करो

  2. सर्वर पर राइट क्लिक करें और "क्लीन" चुनें

  3. सर्वर पर फिर से राइट क्लिक करें और "क्लीन टोमाट वर्क डायरेक्टरी" चुनें


0

मेरे मामले में, मैं मुख्य जावा कॉन्फिग फाइल में सेकेंडरी जावा कॉन्फिग फाइल के इम्पोर्ट के साथ खेल रहा था। सेकेंडरी कॉन्फिग फाइल बनाते समय, मैंने मुख्य कॉन्फिग क्लास का नाम बदल दिया था, लेकिन मैं web.xml में नाम अपडेट करने में असफल रहा। इसलिए, हर बार जब मैंने अपने टॉमकैट सर्वर को फिर से शुरू किया था, मैं ग्रहण आईडीई कंसोल में नोट किए गए मैपिंग हैंडलर नहीं देख रहा था, और जब मैंने अपने होम पेज पर नेविगेट करने की कोशिश की तो मुझे यह त्रुटि दिखाई दे रही थी:

1 नवंबर, 2019 11:00:01 PM org.springframework.web.servlet.PageNotFound noHandlerFound चेतावनी: URI के साथ HTTP अनुरोध के लिए कोई मानचित्रण नहीं मिला [/ डिस्पैसर 'नाम के साथ डिस्पैचरवर्कलेट में वेबपेज (होम / इंडेक्स)।

फिक्स को web.xml फ़ाइल को अपडेट करना था ताकि पुराने नाम "WebConfig" के बजाय "MainConfig" हो जाए, बस इसका नाम बदलकर मुख्य java config फाइल का नवीनतम नाम दर्शाया जाए (जहाँ "MainConfig" मनमाना और शब्द हो " वेब "और" मुख्य "का उपयोग यहां एक वाक्यविन्यास आवश्यकता नहीं है)। MainConfig महत्वपूर्ण था, क्योंकि यह वह फाइल थी जिसने "WebController" के लिए घटक स्कैन किया था, मेरा स्प्रिंग mvc नियंत्रक वर्ग जो मेरे वेब अनुरोधों को संभालता है।

@ComponentScan(basePackageClasses={WebController.class})

web.xml में यह था:

<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        com.lionheart.fourthed.config.WebConfig
    </param-value>
</init-param>

web.xml फाइल अब है:

<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        com.lionheart.fourthed.config.MainConfig
    </param-value>
</init-param>

अब मैं कंसोल विंडो में मैपिंग देख रहा हूँ:

जानकारी: मैप किया गया "{[/ होम / इंडेक्स], तरीके = [GET]} पर सार्वजनिक org.springframework.web.servlet.ModelAndView com.lionheart.fourthed .controller.WebController.gotoIndex ()

और मेरा वेब पेज फिर से लोड हो रहा है।


-1

मुझे भी यही समस्या थी **No mapping found for HTTP request with URI [/some/path] in DispatcherServlet with name SomeName**

2 से 4 दिनों तक विश्लेषण करने के बाद मुझे मूल कारण का पता चला। प्रोजेक्ट चलाने के बाद क्लास फाइल्स जेनरेट नहीं हुईं। मैंने प्रोजेक्ट टैब पर क्लिक किया।

प्रोजेक्ट -> क्लोज़प्रोजेक्ट -> ओपनप्रोजेक्ट -> क्लीन -> प्रोजेक्ट बनाएँ

स्रोत कोड के लिए वर्ग फाइलें उत्पन्न की गई हैं। इसने मेरी समस्या हल कर दी। यह जानने के लिए कि क्या क्लास फाइलें जेनरेट हुई हैं या नहीं, कृपया अपने प्रोजेक्ट फोल्डर में बिल्ड फोल्डर देखें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.