2009-12-04 16 views
12

से HttpServletRequest (अनुरोध) ऑब्जेक्ट प्राप्त करें मुझे जावा कोड में अनुरोध ऑब्जेक्ट को पकड़ने की आवश्यकता है। मैं कुछ कारणों से इस ऑब्जेक्ट को अपने कोड पर नहीं भेज सकता। क्या कोई तरीका है कि मैं कुछ कह सकता हूं: getCurrentHTTPServletRequest?जावा कोड

मेरे लिए यह मानना ​​सुरक्षित है कि मैं सर्वलेट संदर्भ में हूं।

+0

कृपया विस्तार से बताएं * जहां *, * क्यों * और * जब * यदि आप इस की जरूरत है, तो हम ज्यादा बेहतर सुझावों के साथ यह करने के लिए कैसे पॉप हो सकता है: यदि नहीं, तो आप इस JVM पैरामीटर जोड़कर इसे सक्षम करना सही रास्ता। अर्द्ध छद्म कोड/एसएससीई पोस्ट करने से आप जो भी हासिल करने की कोशिश कर रहे हैं उसकी तस्वीर प्राप्त करने में भी मदद कर सकते हैं। – BalusC

+0

मुझे सोलर क्वेरी कॉम्पोनेंट का विस्तार करने की आवश्यकता है जो SolrRequest स्वीकार करता है। दुर्भाग्यवश SolrRequest सर्वलेट अनुरोध के चारों ओर एक रैपर नहीं है। SolrDispatchFilter (अनुरोध को संभालने के लिए प्रयोग किया जाता है, केवल फिल्टर नहीं) HttpServletRequest को SolrRequest अनुवाद करता है। इसलिए मेरे कस्टम क्वेरी कॉम्पोनेंट पर अनुरोध से अतिरिक्त जानकारी पास करने का एकमात्र तरीका SolrDispatchFilter को संशोधित करना है, जिसे मैं नहीं करना चाहता हूं। आपकी मदद के लिए बहुत से लोग धन्यवाद। ThreadLocal चर मेरे लिए नौकरी करना चाहिए। – aseem

उत्तर

17

अच्छी तरह से आपको इसकी आवश्यकता होने पर इसे पास कर देना चाहिए। आप जो कुछ भी करते हैं वह मूल रूप से बदसूरत होने जा रहा है।

आप एक ThreadLocal चर इस्तेमाल कर सकते हैं - मूल रूप से है कि विशेष रूप थ्रेड के लिए संदर्भ निर्धारित जब आप अनुरोध मिलता है, और फिर इसे लाने पर बाद में। यह तब तक काम करेगा जब आपको केवल उस थ्रेड के भीतर अनुरोध प्राप्त करने की आवश्यकता होगी जो इसे संसाधित कर रहा है - और जब तक आप कोई फंकी असीमित अनुरोध हैंडलिंग नहीं करते हैं। हालांकि, यह उन कारणों से भंगुर है।

हालांकि, मैं दृढ़ता से आपको इसके बजाय अपनी निर्भरताओं के बारे में स्पष्ट होने की सलाह देता हूं। या तो सर्वलेट अनुरोध को पास करें, या केवल बिट्स जो आपको चाहिए।

+4

+1: * इसे * पास करना चाहिए *। बदसूरत थ्रेडलोकल हैक्स की तुलना में अधिक अनुशंसा की जाती है जिसे मैं वास्तव में अनुरोध थ्रेड के रूप में उपयोग नहीं करता हूं, वेबकैंटेनर द्वारा पूल किया जा सकता है, या आपको वास्तव में यह सुनिश्चित करना होगा कि आप समाप्त होने पर इसे थ्रेड से निकाल दें। बहुत अधिक काम और बुरा साइड इफेक्ट्स/ – BalusC

+3

ऑब्जेक्ट्स को पास करना हमेशा संभव नहीं होता है। आपको कुछ एपीआई पार करना पड़ सकता है जिन पर आपका कोई नियंत्रण नहीं है। यहां तक ​​कि यदि आप किसी भी एपीआई को बदल सकते हैं, तो यह आपके सभी तरीकों से अनुरोध तर्क घोषित करने के लिए मूर्ख और असुविधाजनक होगा, और जब भी आप किसी भी विधि को कॉल करते हैं तो अनुरोध ऑब्जेक्ट पास करें। जब तक आप जानते हैं कि आप क्या कर रहे हैं, तब तक थ्रेडलोकल ठीक है। – irreputable

+1

फिर या तो एपीआई प्रैक्टिकल उद्देश्य के लिए इरादा नहीं है, या आप गलत दिशा में समाधान की तलाश में हैं। उदाहरण के लिए * दूसरी तरफ * इसे एक्सेस करने के बारे में क्या? मैंने जेएसपी/सर्वलेट को यह पुष्टि करने के लिए बहुत लंबा किया है कि पर्याप्त बेहतर तरीके हैं और आपको इसके लिए थ्रेडलोकल सामान की आवश्यकता नहीं है। – BalusC

0

मानते हैं कि शीर्ष-स्तरीय सर्वलेट वास्तव में कुछ पागल व्यवसाय से संबंधित कारणों के लिए वर्जित है, अनुरोध को पूर्व-देखने और इसे थ्रेडलोकल में रखने के लिए अभी भी ServletFilter को परिभाषित करने का विकल्प है। यह मानते हुए कि web.xml भी पवित्र नहीं है।

लेकिन मैं जॉन स्कीट से सहमत हूं कि यह बहुत बदसूरत होगा। मैं इसे कोड दूंगा और फिर एक अलग नौकरी खोजने की कोशिश करूंगा। :)

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

4

जॉन स्कीट कहा व्यावहारिक रूप से सब कुछ है, लेकिन उनकी सलाह "बस बिट्स है कि आप की जरूरत है" के लिए एक स्पष्टीकरण - आप अपने अनुरोध पैरामीटर नीचे पारित कर दिया है, लेकिन आप HttpServletRequest पर निर्भरता की जरूरत नहीं है, request.getParameterMap() पारित की जरूरत है।

और ThreadLocal विकल्प पर थोड़ा विस्तार - यदि आप एक Filter जो आने वाले सभी अनुरोधों को प्रबंधित, और एक

public final static ThreadLocal<HttpServletRequest> httpServletRequestTL = 
     new ThreadLocal<HttpServletRequest>(); 

में अनुरोध क्योंकि आप प्रत्येक अनुरोध पर यह तय कर रहे हैं (फिल्टर के साथ सावधान सेट कर सकते हैं मानचित्रण), आपको सर्वलेट-कंटेनर थ्रेड पूल के बारे में चिंता करने की आवश्यकता नहीं होगी - आपके पास हमेशा वर्तमान अनुरोध होगा।

पीएस स्काफमैन द्वारा प्रस्तावित वसंत उपयोगिता के पीछे यह तर्क है - मैं स्वयं को बनाने के बजाए स्थिर घटक की सिफारिश करने में शामिल हूं।

9

मान लें कि आप कॉल स्टैक के नीचे अनुरोध ऑब्जेक्ट को पारित करने में सक्षम नहीं हैं, तो किसी प्रकार की साझाकरण तंत्र आवश्यक हो जाती है, जो आदर्श नहीं है, लेकिन कभी-कभी आवश्यक होती है।

Spring इस उद्देश्य के लिए RequestContextFilter प्रदान करता है। यह ThreadLocal का उपयोग करता है, और कोड को वर्तमान अनुरोध को RequestContextHolder के माध्यम से प्राप्त करने की अनुमति देता है।ध्यान दें कि इस फिल्टर नहीं आप वसंत के किसी अन्य भाग का उपयोग करने की आवश्यकता होती है कि:

Servlet 2.3 Filter that exposes the request to the current thread, through both LocaleContextHolder and RequestContextHolder. To be registered as filter in web.xml.

This filter is mainly for use with third-party servlets, e.g. the JSF FacesServlet. Within Spring's own web support, DispatcherServlet's processing is perfectly sufficient.

आप ThreadLocal उपयोग करने के लिए जा रहे हैं, तो बेहतर एक मौजूदा, काम कर समाधान के बजाय जोखिम कीड़े में धीरे-धीरे उपयोग करने के लिए , जो ThreadLocal कोड प्रवण है।

4

ऐसा करने के लिए कोई सर्वलेट एपीआई नहीं है। हालांकि, बिलाव यह करने के लिए एक API कॉल प्रदान करता है,

HttpServletRequest request = (HttpServletRequest)org.apache.catalina.core.ApplicationFilterChain.getLastServicedRequest(); 

यह पिछले अनुरोध वर्तमान धागे से सेवा के लिए एक सर्वलेट के लिए पारित हो जाएगा।

इसके लिए काम करने के लिए, टोमकैट "सख्त सर्वलेट अनुपालन" मोड में होना चाहिए।

org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true 
+0

यह एक ऐसी स्थिति का सबसे नज़दीकी उत्तर है जिसका सामना मैं कर रहा हूं। यदि आप रुचि रखते हैं तो मैंने इसके लिए एक बक्षीस बनाया है। असल में मेरे पास एक फ़िल्टर है जो सर्वलेट संदर्भ से स्प्रिंग सेवा फैक्ट्री ऑब्जेक्ट प्राप्त करता है, यह फ़ैक्टरी एक बीन का एक उदाहरण आवंटित करता है जब फ़िल्टर कॉल करता है सेवा प्राप्त करता है लेकिन मुझे अनुरोध के सत्र या वास्तविक httpServletRequest ऑब्जेक्ट को पास करने की आवश्यकता होती है। लेकिन मुझे ऐसा नहीं करना चाहिए क्योंकि यह फ़िल्टर के मालिक रिमोट सर्विस ब्रिज के अमूर्तता को तोड़ देगा। आपका उत्तर सही दिखता है लेकिन समस्या यह है कि वेब ऐप बहु-उपयोगकर्ता है और मैं गलत अनुरोध के साथ समाप्त हो सकता हूं, है ना? – Jigzat

+0

मुझे जो चाहिए वह लगता है, लेकिन मुझे कॉल करते समय "java.lang.IllegalAccessError: org/apache/catalina/core/applicationFilterChain" मिलता है। – Laloutre