प्रसंगवशलाकेंद्रक या नहीं?


122

एक मानक स्प्रिंग वेब एप्लीकेशन (रूओ या "स्प्रिंग एमवीसी प्रोजेक्ट" टेम्पलेट द्वारा बनाया गया) ContextLoaderListenerऔर के साथ एक web.xml बनाते हैं DispatcherServletवे DispatcherServletपूर्ण कॉन्फ़िगरेशन को लोड करने के लिए केवल इसका उपयोग क्यों नहीं करते और इसे बनाते हैं?

मैं समझता हूं कि ContextLoaderListener का उपयोग उस सामान को लोड करने के लिए किया जाना चाहिए जो वेब प्रासंगिक नहीं है और DispatcherServlet का उपयोग वेब प्रासंगिक सामग्री (नियंत्रकों, ...) को लोड करने के लिए किया जाता है। और इसका परिणाम दो संदर्भों में होता है: एक अभिभावक और एक बच्चा संदर्भ।

पृष्ठभूमि:

मैं इसे कई वर्षों से इस मानक तरीके से कर रहा था।

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Handles Spring requests -->
<servlet>
    <servlet-name>roo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/webmvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

इससे अक्सर दोनों संदर्भों और उनके बीच निर्भरता के साथ समस्याएं पैदा हुईं। अतीत में मैं हमेशा एक समाधान खोजने में सक्षम था, और मुझे इस बात का पक्का एहसास है कि इससे सॉफ्टवेयर संरचना / वास्तुकला हमेशा बेहतर होती है। लेकिन अब मैं दोनों संदर्भों की घटनाओं के साथ एक समस्या का सामना कर रहा हूं ।

- हालांकि यह मेरे दो संदर्भ पैटर्न को पुनर्विचार करता है, और मैं खुद से पूछ रहा हूं: मुझे अपने आप को इस परेशानी में क्यों लाना चाहिए, क्यों न सभी स्प्रिंग कॉन्फ़िगरेशन फ़ाइलों को एक के साथ लोड किया जाए DispatcherServletऔर ContextLoaderListenerपूरी तरह से हटा दिया जाए। (मेरे पास अभी भी अलग-अलग कॉन्फ़िगरेशन फ़ाइलें होंगी, लेकिन केवल एक संदर्भ।)

वहाँ किसी भी कारण को दूर करने के लिए नहीं है ContextLoaderListener?


"इससे अक्सर दोनों संदर्भों और उनके बीच निर्भरता के साथ समस्याएं पैदा हुईं।" यह इस बात का एक बड़ा उदाहरण है कि कैसे मुझे लगता है कि निर्भरता इंजेक्शन ढांचे सिर्फ हमारे जीवन को अपने आप को निर्भरता इंजेक्शन की तुलना में कठिन बनाते हैं।
एंडी

1
@Andy - जबकि मेरे पास इस दृष्टिकोण के साथ कुछ सहानुभूति है, मैं यह नोटिस करने में मदद नहीं कर सकता कि उपयोग के मामले जिनके लिए आपको दोनों संदर्भों की आवश्यकता है (सुरक्षा फ़िल्टर और सर्वलेट के बीच ऑब्जेक्ट साझा करना, स्वचालित रूप से लेनदेन का प्रबंधन करना ताकि वे दृश्य के बाद बंद हो जाएं। आप प्रतिपादन को पूरा करने के लिए पुनर्निर्देशित करते हैं) फ्रेमवर्क की सहायता के बिना प्राप्त करना काफी कठिन है। यह ज्यादातर इसलिए है क्योंकि सर्वलेट एपीआई को स्पष्ट रूप से कभी भी निर्भरता इंजेक्शन के साथ काम करने के लिए डिज़ाइन नहीं किया गया था, और यदि आप स्वयं करने की कोशिश करते हैं तो सक्रिय रूप से आपके खिलाफ काम करता है।
पेरियाटा ब्रीटा

@PeriataBreatta मैं देख रहा हूँ! ठीक है, क्या आपको लगता है कि अगर इसे अलग तरह से डिजाइन किया गया होता तो स्प्रिंग एमवीसी के बेहतर विकल्प होते? हालांकि लोग सर्वलेट एपीआई के लिए पूरी तरह से विकल्प तैयार कर सकते थे ...
एंडी

@PeriataBreatta यह ध्यान रखना दिलचस्प है कि JS की दुनिया में, जहाँ मैं लगभग एक साल से HTTP रिक्वेस्ट को रूट करने के लिए एक्सप्रेस का उपयोग कर रहा हूं, मुझे शायद ही कभी "निर्भरता इंजेक्शन" का कोई उल्लेख मिलता है और स्प्रिंग फ्रेमवर्क जैसा कुछ भी नहीं दिखता है।
एंडी

जवाबों:


86

आपके मामले में, नहीं, ContextLoaderListenerऔर रखने का कोई कारण नहीं है applicationContext.xml। यदि आपका ऐप बस सर्वलेट के संदर्भ के साथ ठीक काम करता है, तो इसके साथ रहना, यह सरल है।

हां, आम तौर पर प्रोत्साहित पैटर्न गैर-वेब सामान को वेब-स्तरीय संदर्भ में रखने के लिए है, लेकिन यह एक कमजोर सम्मेलन से ज्यादा कुछ नहीं है।

वेब-स्तरीय संदर्भ का उपयोग करने के लिए केवल सम्मोहक कारण हैं:

  • यदि आपके पास कई हैं DispatcherServletजिन्हें सेवाओं को साझा करने की आवश्यकता है
  • यदि आपके पास विरासत / गैर-स्प्रिंग सर्वलेट्स हैं जिन्हें स्प्रिंग-वायर्ड सेवाओं तक पहुंच की आवश्यकता है
  • आप सर्वलेट फिल्टर है कि webapp स्तर के संदर्भ में हुक (जैसे वसंत सुरक्षा के DelegatingFilterProxy, OpenEntityManagerInViewFilter, आदि)

इनमें से कोई भी आप पर लागू नहीं होता है, इसलिए अतिरिक्त जटिलता अनुचित है।

सर्वलेट के संदर्भ में पृष्ठभूमि कार्यों को जोड़ते समय बस सावधान रहें, जैसे अनुसूचित कार्य, जेएमएस कनेक्शन, आदि। यदि आप <load-on-startup>अपने को जोड़ना भूल जाते हैं web.xml, तो इन कार्यों को सर्वलेट की पहली पहुंच तक शुरू नहीं किया जाएगा।


2
श्रोताओं के बारे में क्या है, यह सीमेक्स लोडर श्रोता (इललीगलस्टेटटेक्स्टैप्ट, नो वेबएप्लीकेशन कॉन्टेक्स्ट, मल्टीपार्टफिल्टर, कैरेक्टरकोडिंगफिल्टर, हिडनहेट्रैपमैथोडिफिल्टर, स्प्रिंग सिक्योरिटी डीलीगेटिफ़ाइटर पॉलीक्सटरप्रेगर्स द्वारा ट्रिगर किया गया है) के संदर्भ में उनकी ज़रूरत है। क्या यह एक अच्छा विचार है कि इसे दूसरे तरीके से किया जाए (प्रत्येक चीज़ को ContextLoaderListener द्वारा लोड करें, और एक कॉन्फ़िगरेशन के बिना DispatcherServlet छोड़ दें)?
राल्फ

@ राल्फ: अच्छी पकड़, मैंने उस उपयोग मामले को सूची में जोड़ दिया है। DispatcherServletकॉन्फ़िगरेशन के बिना छोड़ने के लिए - यदि आपने ऐसा किया है, तो आपके पास कोई वेब इंटरफ़ेस नहीं होगा। सभी एमवीसी सामान को वहां जाना है।
स्केफमैन

2
@skaffman DelegatingFilterProxy के साथ वसंत-सुरक्षा का उपयोग करते समय मुझे दो संदर्भों का उपयोग क्यों करना चाहिए? मेरे मामले में वसंत-सुरक्षा सेम और डिफ़ॉल्ट वसंत संदर्भ कुछ सेम साझा करते हैं। इसलिए उन्हें भी उसी संदर्भ को साझा करना चाहिए। या वसंत सुरक्षा सेम को डिफ़ॉल्ट वसंत संदर्भ से बाहर रखा जाना चाहिए?
मथायस एम

10

आप अनुप्रयोग संदर्भ को अन्य तरीके से भी कॉन्फ़िगर कर सकते हैं। उदाहरण के लिए OpenEntityManagerInViewFilter काम करने के लिए। ContextLoaderListener को सेटअप करें और उसके बाद अपने DispatcherServlet को कॉन्फ़िगर करें:

<servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value></param-value>
    </init-param>
</servlet>

बस यह सुनिश्चित करें कि ReferenceConfigLocation पैरामीटर मान रिक्त है।


1
लेकिन इस विन्यास का क्या फायदा है? और "दूसरे तरीके से" का क्या मतलब है?
राल्फ

"स्कैफ़मैन" द्वारा समाधान केवल एक वेब एप्लिकेशन संदर्भ (सर्वलेट) को कॉन्फ़िगर किया गया है। हालाँकि, उस दृष्टिकोण के साथ आप समाधान में विस्तृत रूप में मुद्दों पर चलते हैं: "वेबएप-स्तरीय संदर्भ का उपयोग करने के लिए केवल सम्मोहक कारण हैं:" ... "यदि आपके पास वेबलेट-स्तरीय संदर्भ में हुक हैं (जैसे कि स्प्रिंग सिक्योरिटीज डेलिगेटिंगफिल्टरप्रॉक्सी, ओपनएंटमैनटैगरइन व्यूफिल्टर, आदि) "यदि आप केवल 1 एप्लिकेशन संदर्भ XML फ़ाइल का उपयोग करना पसंद करते हैं, तो मुझे लगता है कि मेरा समाधान (ContextLoadListener के माध्यम से XML निर्दिष्ट करना) बेहतर होगा।
गुन्नर हिलर्ट

क्या आप प्रसंग श्रोता द्वारा बनाए गए संदर्भ में MVC वेब नियंत्रक का उपयोग करने में सक्षम हैं?
राल्फ

1
हाँ। आप प्रसंगवश श्रोता द्वारा निर्दिष्ट संदर्भ.xml फ़ाइल में अपने नियंत्रकों को आसानी से स्थापित करेंगे। जिस तरह से यह काम करता है वह यह है कि डिस्पैचरसर्वलेट केवल "मूल एप्लिकेशन संदर्भ" (संदर्भ सूची) में शामिल हो जाएगा। जैसा कि आप "ReferenceConfigLocation" मान छोड़ते हैं। संदर्भ प्रसंग। प्रसंग श्रोता द्वारा निर्दिष्ट फ़ाइल विशेष रूप से उपयोग की जाएगी।
गुन्नार हिलर्ट

1
मुझे लगता है कि आप अपने संदर्भ में <mvc: एनोटेशन-चालित /> चूक गए। @GunnarHillert समाधान मेरे लिए काम करता है।
मील डे्रस

10

मैं अपने स्प्रिंग-एमवीसी एप्लिकेशन पर जो कुछ भी कर रहा हूं उसे साझा करना चाहता हूं:

  1. पर we-mvc-config.xmlमैं तो बस @Controller साथ एनोटेट कक्षाओं कहा:

    <context:component-scan base-package="com.shunra.vcat">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
  2. पर applicationContext.xmlफ़ाइलें मैं सभी बाकी कहा:

    <context:component-scan base-package="com.shunra.vcat">
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>

हां, यह एक उपयोगी पैटर्न है। एक अन्य उपयोगी पैटर्न बस आपके डेटाबेस को बीन्स को एप्लिकेशन के संदर्भ में डाल रहा है (ये एक OpenSessionInViewFilter या समान के लिए आवश्यक है) विशेष रूप से फ़िल्टर या श्रोताओं द्वारा आवश्यक कुछ भी (जैसे कि वसंत सुरक्षा का उपयोग करने के लिए आवश्यक परिभाषा)।
पेरियाटा ब्रीटाटा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.