java - Servlets कैसे काम करते हैं? इंस्टेंटेशन, सत्र, साझा चर और मल्टीथ्रेडिंग




multithreading session-variables (5)

मान लीजिए, मेरे पास एक वेबसर्वर है जिसमें कई सर्लेट हैं। उन servlets के बीच गुजरने वाली जानकारी के लिए मैं सत्र और आवृत्ति चर सेट कर रहा हूं।

अब, यदि 2 या अधिक उपयोगकर्ता इस सर्वर से अनुरोध भेजते हैं तो सत्र चर के साथ क्या होता है? क्या वे सभी उपयोगकर्ताओं के लिए आम होंगे या वे प्रत्येक उपयोगकर्ता के लिए अलग होंगे। यदि वे अलग हैं, तो सर्वर अलग-अलग उपयोगकर्ताओं के बीच अंतर करने में सक्षम कैसे था?

एक और समान सवाल, यदि कोई उपयोगकर्ता किसी विशेष सर्वलेट तक पहुंचने वाले उपयोगकर्ता हैं, तो यह सर्वलेट केवल पहली बार तुरंत पहुंचने वाले पहले उपयोगकर्ता को तत्काल प्राप्त करता है या क्या यह सभी उपयोगकर्ताओं के लिए तत्काल तत्काल हो जाता है? दूसरे शब्दों में, आवृत्ति चर के साथ क्या होता है?


ServletContext

जब सर्वलेट कंटेनर (जैसे अपाचे टॉमकैट ) शुरू होता है, तो यह अपने सभी वेब अनुप्रयोगों को तैनात और लोड कर देगा। जब कोई वेब एप्लिकेशन लोड होता है, तो सर्वलेट कंटेनर एक बार ServletContext बनाता है और इसे सर्वर की मेमोरी में रखता है। वेब ऐप की web.xml फ़ाइल को पार्स किया गया है, और प्रत्येक <servlet> , <filter> और <listener> पाया गया है (या क्रमशः @WebServlet , @WebFilter और @WebListener साथ एनोटेटेड प्रत्येक वर्ग) को तुरंत चालू किया जाता है और सर्वर की स्मृति में रखा जाता है कुंआ। प्रत्येक तत्काल फ़िल्टर के लिए, इसकी init() विधि को एक नए FilterConfig साथ बुलाया जाता है।

जब सर्वलेट कंटेनर बंद हो जाता है, तो यह सभी वेब अनुप्रयोगों को अनलोड करता है, इसके प्रारंभिक सर्लेट और फ़िल्टर के destroy() विधि destroy() आमंत्रित करता है, और सभी ServletContext , Servlet , Filter और Listener उदाहरण ट्रैश किए जाते हैं।

जब एक Servlet में <servlet><load-on-startup> या @WebServlet(loadOnStartup) मान 0 से अधिक मान होता है, तो इसकी init() विधि को एक नए ServletConfig साथ स्टार्टअप के दौरान भी बुलाया जाता है। उन सर्वलेटों को उस मान द्वारा निर्दिष्ट उसी क्रम में प्रारंभ किया जाता है (1 -> पहला, 2 -> दूसरा, आदि)। यदि एक ही मान एक से अधिक सर्वलेट के लिए निर्दिष्ट किया गया है, तो उन सभी servlets को @WebServlet . @WebServlet , या @WebServlet में दिखाई देने वाले क्रम में लोड किया जाता है। यदि "लोड-ऑन-स्टार्टअप" मान अनुपस्थित है, तो जब भी HTTP अनुरोध पहली बार उस सर्वलेट को हिट करता है तो init() विधि लागू की जाएगी।

HttpServletRequest और HttpServletResponse

सर्वलेट कंटेनर एक वेब सर्वर से जुड़ा हुआ है जो किसी निश्चित पोर्ट नंबर पर HTTP अनुरोधों के लिए सुनता है (पोर्ट 8080 आमतौर पर उत्पादन के दौरान उपयोग और पोर्ट 80 के दौरान उपयोग किया जाता है)। जब कोई ग्राहक (वेब ​​ब्राउज़र वाला उपयोगकर्ता) HTTP अनुरोध भेजता है, तो सर्वलेट कंटेनर नई HttpServletRequest और HttpServletResponse ऑब्जेक्ट बनाता है और उन्हें किसी भी परिभाषित Filter श्रृंखला और अंत में, Servlet उदाहरण के माध्यम से गुजरता है।

filters के मामले में, doFilter() विधि लागू की जाती है। जब उसका कोड chain.doFilter(request, response) कहता है, तो अनुरोध और प्रतिक्रिया अगले फ़िल्टर पर जारी रहती है, या कोई शेष फ़िल्टर नहीं होने पर सर्वलेट को दबाएं।

servlets के मामले में, service() विधि लागू की जाती है। डिफ़ॉल्ट रूप से, यह विधि निर्धारित करता है कि doXxx() विधियों में से कौन सा request.getMethod() आधार पर आमंत्रित किया doXxx() request.getMethod() । यदि निर्धारित विधि सर्वलेट से अनुपस्थित है, तो प्रतिक्रिया में HTTP 405 त्रुटि लौटा दी जाती है।

अनुरोध ऑब्जेक्ट HTTP अनुरोध, जैसे उसके शीर्षलेख और शरीर के बारे में सारी जानकारी तक पहुंच प्रदान करता है। प्रतिक्रिया ऑब्जेक्ट HTTP प्रतिक्रिया को जिस तरह से आप चाहते हैं उसे नियंत्रित करने और भेजने की क्षमता प्रदान करता है, उदाहरण के लिए, आपको हेडर और बॉडी सेट करने की अनुमति देता है (आमतौर पर जेएसपी फ़ाइल से जेनरेट की गई HTML सामग्री के साथ)। जब HTTP प्रतिक्रिया प्रतिबद्ध और समाप्त हो जाती है, तो अनुरोध और प्रतिक्रिया ऑब्जेक्ट दोनों पुनर्नवीनीकरण और पुन: उपयोग के लिए किए जाते हैं।

HttpSession

जब कोई ग्राहक पहली बार HttpSession जाता है और / या HttpSession को request.getSession() माध्यम से पहली बार प्राप्त किया जाता है, तो सर्वलेट कंटेनर एक नया HttpSession ऑब्जेक्ट बनाता है, जो एक लंबी और अद्वितीय आईडी उत्पन्न करता है (जिसे आप session.getId() द्वारा प्राप्त कर सकते हैं session.getId() ), और इसे सर्वर की स्मृति में संग्रहीत करें। सर्वलेट कंटेनर भी JSESSIONID साथ HTTP प्रतिक्रिया के Set-Cookie शीर्षलेख में एक Cookie Set-Cookie करता है, जिसका नाम और अद्वितीय सत्र आईडी इसके मान के रूप में होता है।

HTTP कुकी विनिर्देश के अनुसार (एक अनुबंध एक सभ्य वेब ब्राउज़र और वेब सर्वर का पालन करना पड़ता है), क्लाइंट (वेब ​​ब्राउज़र) को Cookie हेडर में Cookie शीर्षलेख में बाद में अनुरोधों में वापस भेजने की आवश्यकता होती है मान्य (यानी अद्वितीय आईडी को एक अप्रत्याशित सत्र का संदर्भ लेना चाहिए और डोमेन और पथ सही हैं)। अपने ब्राउज़र के अंतर्निहित HTTP ट्रैफ़िक मॉनीटर का उपयोग करके, आप यह सत्यापित कर सकते हैं कि कुकी वैध है (क्रोम / फ़ायरफ़ॉक्स 23+ / IE9 + में F12 दबाएं, और नेट / नेटवर्क टैब को चेक करें)। सर्वलेट कंटेनर Cookie के उपस्थिति के लिए JSESSIONID नाम के साथ प्रत्येक आने वाले HTTP अनुरोध के Cookie हेडर की जांच करेगा और सर्वर की स्मृति से संबंधित HttpSession प्राप्त करने के लिए इसके मान (सत्र आईडी) का उपयोग करेगा।

HttpSession तब तक जीवित रहता है जब तक कि <session-timeout> में निर्दिष्ट टाइमआउट मान से अधिक के लिए इसका उपयोग नहीं किया गया है, web.xml में एक सेटिंग। टाइमआउट मान 30 मिनट तक डिफ़ॉल्ट हो जाता है। इसलिए, जब क्लाइंट निर्दिष्ट समय से अधिक समय तक वेब ऐप पर नहीं जाता है, तो सर्वलेट कंटेनर सत्र को ट्रैश करता है। प्रत्येक अनुवर्ती अनुरोध, यहां निर्दिष्ट कुकी के साथ भी, उसी सत्र तक पहुंच नहीं होगी; सर्वलेट कंटेनर एक नया सत्र तैयार करेगा।

क्लाइंट साइड पर, सत्र कुकी तब तक जीवित रहती है जब तक कि ब्राउज़र इंस्टेंस चल रहा हो। इसलिए, यदि क्लाइंट ब्राउज़र इंस्टेंस (सभी टैब / विंडोज़) बंद कर देता है, तो क्लाइंट के पक्ष में सत्र ट्रैश हो जाता है। एक नए ब्राउज़र उदाहरण में, सत्र से जुड़ी कुकी मौजूद नहीं होगी, इसलिए यह अब नहीं भेजा जाएगा। यह एक पूरी तरह से नया HTTPSession का कारण बनता है, पूरी तरह से नई सत्र कुकी का उपयोग शुरू होता है।

संक्षेप में

  • ServletContext रहता है जब तक कि वेब ऐप रहता है। यह सभी सत्रों में सभी अनुरोधों के बीच साझा किया जाता है।
  • HttpSession रहता है जब तक क्लाइंट एक ही ब्राउज़र इंस्टेंस के साथ वेब ऐप के साथ सहभागिता कर रहा है, और सर्वर के पक्ष में सत्र का समय समाप्त नहीं हुआ है। यह एक ही सत्र में सभी अनुरोधों के बीच साझा किया जाता है।
  • HttpServletRequest और HttpServletResponse उस समय से रहता है जब सर्वलेट क्लाइंट से HTTP अनुरोध प्राप्त करता है, जब तक कि पूर्ण प्रतिक्रिया (वेब ​​पेज) नहीं आती। यह कहीं और साझा नहीं किया जाता है।
  • जब तक वेब ऐप रहता है तब तक सभी Servlet , Filter और Listener उदाहरण रहते हैं। वे सभी सत्रों में सभी अनुरोधों के बीच साझा किए जाते हैं।
  • HttpSession , HttpServletRequest और HttpSession में परिभाषित कोई भी attribute तब तक जीवित रहेगी जब तक कि प्रश्न में ऑब्जेक्ट रहता है। ऑब्जेक्ट स्वयं जेएसएफ, सीडीआई, स्प्रिंग इत्यादि जैसे बीन प्रबंधन ढांचे में "गुंजाइश" का प्रतिनिधित्व करता है। ये ढांचे अपने स्कॉप्ड बीन्स को अपने निकटतम मिलान क्षेत्र के attribute के रूप में स्टोर करते हैं।

थ्रेड सुरक्षा

उस ने कहा, आपकी प्रमुख चिंता संभवतः थ्रेड सुरक्षा है । अब आपको पता होना चाहिए कि सर्वलेट और फ़िल्टर सभी अनुरोधों के बीच साझा किए जाते हैं। जावा की यह अच्छी बात है, यह बहुप्रचारित और अलग-अलग धागे हैं (पढ़ें: HTTP अनुरोध) एक ही उदाहरण का उपयोग कर सकते हैं। यह अन्यथा अनुरोध के लिए अन्यथा पुनर्निर्मित, init() और destroy() को बहुत महंगा होगा।

आपको यह भी महसूस करना चाहिए कि आपको किसी अनुरोध या सत्र स्कोप्ड डेटा को सर्वलेट या फ़िल्टर के आवृत्ति चर के रूप में कभी भी असाइन नहीं करना चाहिए। इसे अन्य सत्रों में अन्य सभी अनुरोधों के बीच साझा किया जाएगा। यह थ्रेड-सुरक्षित नहीं है! नीचे दिया गया उदाहरण यह दिखाता है:

public class ExampleServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

यह भी देखें:


सत्र

संक्षेप में: वेब सर्वर प्रत्येक विज़िटर को अपनी पहली यात्रा पर एक अद्वितीय पहचानकर्ता जारी करता है। आगंतुक को अगली बार पहचानने के लिए उस आईडी को वापस लाया जाना चाहिए। यह पहचानकर्ता सर्वर को एक सत्र के स्वामित्व वाले ऑब्जेक्ट्स को उचित रूप से अलग करने की अनुमति देता है।

सर्वलेट इंस्टेंटेशन

यदि लोड-ऑन-स्टार्टअप गलत है :

यदि लोड-ऑन-स्टार्टअप सत्य है :

एक बार जब वह सेवा मोड और नाली पर है, तो वही सर्वलेट अन्य सभी ग्राहकों के अनुरोधों पर काम करेगा।

प्रति क्लाइंट एक उदाहरण रखने का अच्छा विचार क्यों नहीं है? इसके बारे में सोचें: क्या आप आने वाले हर आदेश के लिए एक पिज्जा लड़का किराए पर लेंगे? ऐसा करें और आप किसी भी समय व्यवसाय से बाहर होंगे।

हालांकि यह एक छोटे से जोखिम के साथ आता है। याद रखें: इस एकल व्यक्ति को अपनी जेब में सभी ऑर्डर जानकारी होती है: इसलिए यदि आप सर्वलेट्स पर थ्रेड सुरक्षा के बारे में सतर्क नहीं हैं, तो वह किसी निश्चित ग्राहक को गलत ऑर्डर दे सकता है।


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

संपादित करें servlets के अंदर सत्र के साथ काम करने के तरीके पर here एक उत्कृष्ट ट्यूटोरियल here । और here जावा सर्वलेट्स के बारे में सूर्य का एक अध्याय है, वे क्या हैं और उनका उपयोग कैसे करें। उन दो लेखों के बीच, आप अपने सभी सवालों के जवाब देने में सक्षम होना चाहिए।


सर्वलेट विशिष्टता JSR-315 स्पष्ट रूप से सेवा (और डॉगेट, डूपोस्ट, डूपूट इत्यादि) में वेब कंटेनर व्यवहार को परिभाषित करता है (2.3.3.1 मल्टीथ्रेडिंग समस्याएं, पृष्ठ 9):

एक सर्वलेट कंटेनर सर्वलेट की सेवा विधि के माध्यम से समवर्ती अनुरोध भेज सकता है। अनुरोधों को संभालने के लिए, सर्वलेट डेवलपर को सेवा विधि में एकाधिक धागे के साथ समवर्ती प्रसंस्करण के लिए पर्याप्त प्रावधान करना होगा।

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

Servlets के लिए सिंगल थ्रेड मॉडेल इंटरफ़ेस को कार्यान्वित नहीं किया जा रहा है, यदि सेवा विधि (या डॉटगेट या डूपोस्ट जैसे विधियों को HttpServlet अमूर्त वर्ग की सेवा विधि में प्रेषित किया गया है) को सिंक्रनाइज़ किए गए कीवर्ड के साथ परिभाषित किया गया है, तो सर्वलेट कंटेनर उदाहरण पूल दृष्टिकोण का उपयोग नहीं कर सकता , लेकिन इसके माध्यम से अनुरोध serialize करना चाहिए। यह दृढ़ता से अनुशंसा की जाती है कि डेवलपर्स प्रदर्शन पर हानिकारक प्रभावों के कारण इन परिस्थितियों में सेवा विधि (या इसे प्रेषित विधियों) को सिंक्रनाइज़ नहीं करते हैं


सत्र - क्रिस थॉम्पसन ने क्या कहा।

Instantiation - एक सर्वलेट तत्काल होता है जब कंटेनर को सर्वलेट में मैप किए गए पहले अनुरोध प्राप्त होते हैं (जब तक सर्वलेट को web.xml में <load-on-startup> तत्व के साथ स्टार्टअप पर लोड करने के लिए कॉन्फ़िगर नहीं किया जाता है)। उसी उदाहरण का उपयोग बाद के अनुरोधों को पूरा करने के लिए किया जाता है।





instance-variables