servlets ทำงานอย่างไร การเริ่มต้นเซสชันตัวแปรที่แชร์และมัลติเธรด


1144

สมมติว่าฉันมีเว็บเซิร์ฟเวอร์ที่เก็บ servlets ไว้มากมาย สำหรับการส่งข้อมูลระหว่าง servlets เหล่านั้นฉันกำลังตั้งค่าเซสชันและตัวแปรอินสแตนซ์

ตอนนี้ถ้าผู้ใช้ 2 คนหรือมากกว่าส่งคำขอไปยังเซิร์ฟเวอร์นี้จะเกิดอะไรขึ้นกับตัวแปรเซสชัน
พวกเขาจะเป็นเรื่องธรรมดาสำหรับผู้ใช้ทุกคนหรือพวกเขาจะแตกต่างกันสำหรับผู้ใช้แต่ละคน?
หากพวกเขาแตกต่างกันเซิร์ฟเวอร์จะสามารถแยกความแตกต่างระหว่างผู้ใช้ที่แตกต่างกันอย่างไร

คำถามที่คล้ายกันอีกข้อหนึ่งหากมีnผู้ใช้ที่เข้าถึงเซิร์ฟเล็ตเฉพาะเจาะจงเซิร์ฟเล็ตนี้จะถูกสร้างอินสแตนซ์เฉพาะในครั้งแรกที่ผู้ใช้คนแรกเข้าถึงหรือได้รับอินสแตนซ์สำหรับผู้ใช้ทั้งหมดแยกกันหรือไม่
กล่าวอีกนัยหนึ่งจะเกิดอะไรขึ้นกับตัวแปรอินสแตนซ์

คำตอบ:


1821

ServletContext

เมื่อ servlet container (เช่นApache Tomcat ) เริ่มทำงานมันจะปรับใช้และโหลดเว็บแอปพลิเคชันทั้งหมด เมื่อโหลดแอปพลิเคชันเว็บ servlet container จะสร้างServletContextหนึ่งครั้งและเก็บไว้ในหน่วยความจำของเซิร์ฟเวอร์ เว็บแอปฯweb.xmlและทั้งหมดของรวมweb-fragment.xmlไฟล์จะแยกกันและแต่ละคน<servlet>, <filter>และ<listener>พบ (หรือแต่ละชั้นข้อเขียนด้วย@WebServlet, @WebFilterและ@WebListenerตามลำดับ) ถูกสร้างครั้งเดียวและเก็บไว้ในหน่วยความจำของเซิร์ฟเวอร์ได้เป็นอย่างดี สำหรับแต่ละตัวกรอง instantiated มันวิธีการถูกเรียกด้วยใหม่init()FilterConfig

เมื่อServletมี<servlet><load-on-startup>หรือ@WebServlet(loadOnStartup)มากขึ้นกว่าค่า0แล้วของวิธีการที่จะเรียกยังระหว่างการเริ่มต้นกับใหม่init() ServletConfigเซิร์ฟเล็ตเหล่านั้นถูกเตรียมข้อมูลเบื้องต้นตามลำดับที่ระบุโดยค่านั้น ( 1คือที่ 1 2คือที่ 2 และอื่น ๆ ) หากค่าเดียวกันที่ระบุไว้มากกว่าหนึ่งเซิร์ฟเล็ตแล้วแต่ละ Servlets ผู้ที่มีการโหลดในลำดับเดียวกันตามที่ปรากฏในweb.xml, web-fragment.xmlหรือ@WebServletclassloading ในกรณีที่ไม่มีค่า "การโหลดเมื่อเริ่มต้น" init()วิธีการจะถูกเรียกใช้เมื่อใดก็ตามที่คำขอ HTTP เข้าชมเซิร์ฟเล็ตนั้นเป็นครั้งแรก

เมื่อเซิร์ฟเล็ตคอนเทนเนอร์เสร็จสิ้นด้วยขั้นตอนการกำหนดค่าเริ่มต้นทั้งหมดที่อธิบายไว้ข้างต้นแล้วServletContextListener#contextInitialized()จะถูกเรียกใช้

เมื่อปิดภาชนะ servlet ลงก็ unloads การใช้งานเว็บที่ทุกคนเรียกdestroy()วิธีการ Servlets ทั้งหมดเริ่มต้นและตัวกรองและทั้งหมดServletContext, Servlet, FilterและListenerอินสแตนซ์กำลังอยู่ในถังขยะ ในที่สุดServletContextListener#contextDestroyed()ก็จะถูกเรียก

HttpServletRequest และ HttpServletResponse

servlet container นั้นเชื่อมต่อกับเว็บเซิร์ฟเวอร์ที่รับฟังคำร้องขอ HTTP ในหมายเลขพอร์ตที่แน่นอน (โดยปกติจะใช้พอร์ต 8080 ระหว่างการพัฒนาและพอร์ต 80 ในการผลิต) เมื่อไคลเอนต์ (เช่นผู้ใช้ที่มีเว็บเบราว์เซอร์หรือใช้โปรแกรมURLConnection ) ส่งคำร้องขอ HTTP คอนเทนเนอร์ servlet จะสร้างสิ่งใหม่HttpServletRequestและHttpServletResponseวัตถุและส่งผ่านสิ่งที่กำหนดไว้Filterในห่วงโซ่และในที่สุดServletอินสแตนซ์

ในกรณีของฟิลเตอร์ที่doFilter()วิธีการที่จะเรียก เมื่อโค้ดของคอนเทนเนอร์ servlet chain.doFilter(request, response)การร้องขอและการตอบสนองดำเนินการต่อไปยังตัวกรองถัดไปหรือกด servlet ถ้าไม่มีตัวกรองที่เหลืออยู่

ในกรณีของServletsที่service()วิธีการที่จะเรียก โดยค่าเริ่มต้นวิธีการนี้จะกำหนดว่าหนึ่งในวิธีการที่จะเรียกตามออกของdoXxx() request.getMethod()หากเมธอดที่กำหนดไม่อยู่ในเซิร์ฟเล็ตดังนั้นข้อผิดพลาด HTTP 405 จะถูกส่งคืนในการตอบกลับ

วัตถุคำขอให้การเข้าถึงข้อมูลทั้งหมดเกี่ยวกับการร้องขอ HTTP เช่น URL ส่วนหัวสตริงการสืบค้นและเนื้อหา อ็อบเจ็กต์การตอบกลับจัดเตรียมความสามารถในการควบคุมและส่งการตอบกลับ HTTP ตามที่คุณต้องการเช่นอนุญาตให้คุณตั้งค่าส่วนหัวและเนื้อหา (โดยปกติจะมีเนื้อหา HTML ที่สร้างขึ้นจากไฟล์ JSP) เมื่อการตอบสนอง HTTP ถูกคอมมิตและเสร็จสิ้นทั้งคำร้องขอและออบเจ็กต์การตอบสนองจะถูกนำมารีไซเคิลและทำให้พร้อมใช้งานสำหรับการใช้ซ้ำ

HttpSession

เมื่อลูกค้าเยี่ยมชมเว็บแอปเป็นครั้งแรกและ / หรือHttpSessionได้รับเป็นครั้งแรกผ่านทางrequest.getSession()ภาชนะ servlet จะสร้างHttpSessionวัตถุใหม่สร้างรหัสยาวและไม่ซ้ำกัน (ซึ่งคุณสามารถรับได้session.getId()) และเก็บไว้ในเซิร์ฟเวอร์ หน่วยความจำ เซิร์ฟเล็ตคอนเทนเนอร์ยังตั้งค่าCookieในSet-Cookieส่วนหัวของการตอบกลับ HTTP ด้วยJSESSIONIDเป็นชื่อและ ID เซสชันที่ไม่ซ้ำกันเป็นค่า

ตามข้อกำหนดของคุกกี้ HTTP (สัญญาเว็บเบราเซอร์และเว็บเซิร์ฟเวอร์ใด ๆ ที่ดีจะต้องปฏิบัติตาม) ลูกค้า (เว็บเบราว์เซอร์) จะต้องส่งคุกกี้นี้กลับมาในคำขอที่ตามมาในCookieส่วนหัวตราบเท่าที่คุกกี้นั้นถูกต้อง ( เช่น ID ที่ไม่ซ้ำต้องอ้างอิงถึงเซสชันที่ยังไม่หมดอายุและโดเมนและเส้นทางถูกต้อง) เมื่อใช้การตรวจสอบปริมาณข้อมูล HTTP ในเบราว์เซอร์ของคุณคุณสามารถตรวจสอบว่าคุกกี้นั้นถูกต้อง (กด F12 ใน Chrome / Firefox 23+ / IE9 + และตรวจสอบแท็บNet / Network ) ภาชนะ servlet จะตรวจสอบCookieส่วนหัวของคำขอ HTTP ที่เข้ามาทุกครั้งสำหรับการมีคุกกี้ที่มีชื่อJSESSIONIDและใช้ค่าของมัน (ID เซสชั่น) เพื่อให้ได้รับการเชื่อมโยงHttpSessionจากหน่วยความจำของเซิร์ฟเวอร์

HttpSessionคงมีชีวิตอยู่จนกว่าจะได้รับการว่าง (คือไม่ได้ใช้ในการร้องขอ) มานานกว่าค่าหมดเวลาที่ระบุไว้ในการตั้งค่าใน<session-timeout> web.xmlค่าการหมดเวลาเริ่มต้นที่ 30 นาที ดังนั้นเมื่อไคลเอ็นต์ไม่ได้เยี่ยมชมเว็บแอพพลิเคชั่นนานกว่าเวลาที่กำหนด servlet container จะลบเซสชัน ทุกคำขอที่ตามมาแม้จะมีการระบุคุกกี้จะไม่สามารถเข้าถึงเซสชันเดียวกันได้อีกต่อไป เซิร์ฟเล็ตคอนเทนเนอร์จะสร้างเซสชันใหม่

ในฝั่งไคลเอ็นต์คุกกี้เซสชันจะมีชีวิตอยู่ตราบใดที่อินสแตนซ์เบราว์เซอร์กำลังทำงาน ดังนั้นหากลูกค้าปิดอินสแตนซ์ของเบราว์เซอร์ (แท็บ / หน้าต่างทั้งหมด) ดังนั้นเซสชันจะถูกทิ้งในด้านของลูกค้า ในอินสแตนซ์เบราว์เซอร์ใหม่คุกกี้ที่เกี่ยวข้องกับเซสชันจะไม่มีอยู่ดังนั้นจะไม่ถูกส่งอีกต่อไป สิ่งนี้ทำให้เกิดการHttpSessionสร้างใหม่ทั้งหมดโดยมีการใช้คุกกี้เซสชันใหม่ทั้งหมด

โดยสังเขป

  • มีServletContextชีวิตอยู่ตราบใดที่เว็บแอปมีชีวิตอยู่ มันถูกใช้ร่วมกันระหว่างทุกคำขอในทุกการประชุม
  • HttpSessionชีวิตได้นานเท่าที่ลูกค้าจะโต้ตอบกับแอปเว็บด้วยเบราว์เซอร์เช่นเดียวกันและช่วงที่ยังไม่ได้หมดเวลาที่ฝั่งเซิร์ฟเวอร์ มันถูกใช้ร่วมกันระหว่างคำขอทั้งหมดในเซสชั่นเดียวกัน
  • HttpServletRequestและHttpServletResponseสดจากเวลาเซิร์ฟเล็ตที่ได้รับการร้องขอ HTTP จากลูกค้าจนการตอบสนองสมบูรณ์ (หน้าเว็บ) ได้มาถึง มันเป็นเรื่องที่ไม่ได้ใช้ร่วมกันที่อื่น
  • ทั้งหมดServlet, FilterและListenerกรณีมีชีวิตอยู่ตราบเท่าที่ชีวิตของ app เว็บ พวกเขาจะใช้ร่วมกันระหว่างทุกคำขอในทุกการประชุม
  • ใด ๆattributeที่กำหนดไว้ในServletContext, HttpServletRequestและHttpSessionจะมีชีวิตอยู่ได้นานเท่าที่วัตถุในชีวิตของคำถาม วัตถุนั้นแสดงถึง "ขอบเขต" ในเฟรมเวิร์กการจัดการถั่วเช่น JSF, CDI, Spring เป็นต้นเฟรมเวิร์กเหล่านั้นเก็บถั่วที่กำหนดขอบเขตไว้เป็นattributeขอบเขตการจับคู่ที่ใกล้เคียงที่สุด

ความปลอดภัยด้าย

ที่กล่าวว่าความกังวลหลักของคุณอาจจะเป็นความปลอดภัยหัวข้อ ตอนนี้คุณควรรู้ว่า servlets และตัวกรองถูกแชร์ในคำขอทั้งหมด นั่นเป็นสิ่งที่ดีเกี่ยวกับ Java มันเป็นเธรดหลายเธรดและเธรดที่แตกต่างกัน (อ่าน: คำขอ 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.
    } 
}

ดูสิ่งนี้ด้วย:


25
ดังนั้นเมื่อฉันสามารถหา JSessionId ที่ได้รับการส่งไปยังไคลเอนต์ฉันสามารถขโมยเซสชั่นของเขา?
Toskan

54
@Toskan: ถูกต้อง เป็นที่รู้จักกันเป็นเซสชั่นตรึงสับ โปรดทราบว่านี่ไม่เฉพาะเจาะจงกับ JSP / Servlet ภาษาฝั่งเซิร์ฟเวอร์อื่น ๆ ทั้งหมดที่ดูแลเซสชันโดยคุกกี้ก็มีความอ่อนไหวเช่นกันเช่น PHP กับPHPSESSIDคุกกี้, ASP.NET พร้อมASP.NET_SessionIDคุกกี้และอื่น ๆ และนี่คือสาเหตุที่การเขียน URL ใหม่ด้วย;jsessionid=xxxเนื่องจากเฟรมเวิร์กบางส่วนของ JSP / Servlet MVC ทำโดยอัตโนมัติ เพียงตรวจสอบให้แน่ใจว่า ID เซสชันนั้นไม่เคยปรากฏใน URL หรือด้วยวิธีอื่นในหน้าเว็บเพื่อที่ผู้โจมตีที่ไม่รู้ตัวจะไม่ถูกโจมตี
BalusC

11
@Toskan: ตรวจสอบให้แน่ใจว่าเว็บแอปของคุณไม่ไวต่อการโจมตี XSS คือไม่แสดงอินพุตที่ผู้ใช้ควบคุมซ้ำในรูปแบบที่ไม่ใช้ Escape XSS เปิดประตูให้กับวิธีการรวบรวมรหัสเซสชันของผู้ใช้ทั้งหมด ดูเพิ่มเติมแนวคิดทั่วไปที่อยู่เบื้องหลัง XSS คืออะไร
BalusC

2
@BalusC, ขออภัยในความโง่เขลาของฉัน มันหมายความว่าผู้ใช้ทุกคนเข้าถึงอินสแตนซ์เดียวกันนี้ isNOTThreadSafe ใช่ไหม?
overshadow

4
@TwoThumbSticks 404 ถูกส่งคืนเมื่อ servlet ทั้งหมดหายไป 405 ถูกส่งคืนเมื่อเซิร์ฟเล็ตมีอยู่ แต่ไม่มีการใช้วิธี doXxx () ที่ต้องการ
BalusC

428

การประชุม

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

ในระยะสั้น: ปัญหาเว็บเซิร์ฟเวอร์รหัสเฉพาะเพื่อผู้เข้าชมแต่ละเขาครั้งแรกที่เข้าชม ผู้เข้าชมจะต้องนำ ID นั้นกลับมาเพื่อให้เขาได้รับการยอมรับในครั้งต่อไป ตัวระบุนี้ยังอนุญาตให้เซิร์ฟเวอร์แยกวัตถุที่เป็นของเซสชั่นหนึ่งกับของอีกรายการให้ถูกต้อง

Servlet instantiation

หากload-on-startupเป็นเท็จ :

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

หากการโหลดเมื่อเริ่มต้นเป็นจริง :

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

เมื่อเขาอยู่ในโหมดบริการและบนร่องservlet เดียวกันจะทำงานกับคำขอจากไคลเอนต์อื่น ๆ ทั้งหมด

ป้อนคำอธิบายรูปภาพที่นี่

เหตุใดจึงไม่ควรมีหนึ่งอินสแตนซ์ต่อลูกค้า คิดเกี่ยวกับสิ่งนี้: คุณจะจ้างผู้ชายพิซซ่าหนึ่งคนสำหรับทุกคำสั่งที่มาถึงหรือไม่? ทำเช่นนั้นและคุณจะเลิกกิจการในเวลาไม่นาน

มันมาพร้อมกับความเสี่ยงเล็กน้อย ข้อควรจำ: ผู้ชายคนนี้เก็บข้อมูลการสั่งซื้อทั้งหมดไว้ในกระเป๋าของเขาดังนั้นถ้าคุณไม่ระมัดระวังเกี่ยวกับความปลอดภัยของเธรดใน servletsเขาอาจท้ายให้คำสั่งผิดกับลูกค้าบางราย


26
รูปภาพของคุณดีมากสำหรับความเข้าใจของฉัน ฉันมีคำถามหนึ่งข้อร้านพิซซ่านี้จะทำอะไรเมื่อสั่งพิซซ่ามากเกินไปมารอคนพิซซ่าคนเดียวหรือจ้างคนพิซซ่าเพิ่มขึ้น ขอบคุณ
zh18

6
เขาจะส่งคืนข้อความด้วยto many requests at this moment. try again later
Please_Dont_Bully_Me_SO_Lords

3
Servlets ซึ่งแตกต่างจากพนักงานส่งพิซซ่าสามารถทำได้มากกว่าหนึ่งการส่งในเวลาเดียวกัน พวกเขาเพียงแค่ต้องใช้ความระมัดระวังเป็นพิเศษในการที่พวกเขาเขียนลงที่อยู่ของลูกค้ารสพิซซ่าของ ...
bruno

42

เซสชันใน Java servlets เหมือนกับเซสชันในภาษาอื่นเช่น PHP มันเป็นเอกลักษณ์ของผู้ใช้ เซิร์ฟเวอร์สามารถติดตามมันได้หลายวิธีเช่นคุกกี้, url rewriting เป็นต้นบทความเอกสาร Javaนี้อธิบายในบริบทของ Java servlets และบ่งชี้ว่าวิธีที่เซสชันถูกรักษาไว้นั้นเป็นรายละเอียดการใช้งานที่เหลือให้ผู้ออกแบบเซิร์ฟเวอร์ ข้อมูลจำเพาะระบุว่าจะต้องคงไว้ซึ่งไม่ซ้ำกับผู้ใช้ในการเชื่อมต่อหลายครั้งไปยังเซิร์ฟเวอร์ ลองอ่านบทความนี้จาก Oracleสำหรับข้อมูลเพิ่มเติมเกี่ยวกับคำถามทั้งสองข้อ

แก้ไขมีการกวดวิชาที่ดีเยี่ยมที่นี่เกี่ยวกับวิธีการทำงานร่วมกับเซสชั่นภายในของ Servlets และนี่คือบทจาก Sun เกี่ยวกับ Java Servlets สิ่งที่เป็นและวิธีการใช้งาน ระหว่างบทความทั้งสองนี้คุณควรตอบคำถามทุกข้อของคุณได้


นี่เป็นคำถามอีกข้อหนึ่งสำหรับฉันเนื่องจากมีเพียงหนึ่งบริบท servlet สำหรับแอปพลิเคชันทั้งหมดและเราได้รับการเข้าถึงตัวแปรเซสชันผ่าน servletcontext นี้ดังนั้นตัวแปรเซสชันจะไม่ซ้ำกันสำหรับผู้ใช้ทุกคนอย่างไร ขอบคุณ ..
Ku Jon

1
คุณเข้าถึงเซสชันจาก servletContext อย่างไร คุณไม่ได้อ้างถึง servletContext.setAttribute () ใช่ไหม?
matt b

4
@KuJon แต่ละเว็บแอปมีหนึ่งServletContextวัตถุ วัตถุนั้นมีวัตถุเซสชั่นศูนย์หนึ่งหรือมากกว่าหนึ่ง - ชุดของวัตถุเซสชั่น แต่ละเซสชันจะถูกระบุด้วยสตริงตัวระบุบางชนิดตามที่เห็นในการ์ตูนในคำตอบอื่น ๆ ตัวระบุนั้นถูกติดตามลูกค้าโดยคุกกี้หรือการเขียน URL ใหม่ แต่ละเซสชั่นวัตถุมีตัวแปรของตัวเอง
Basil Bourque

33

เมื่อ servlet container (เช่น Apache Tomcat) เริ่มต้นขึ้นมันจะอ่านจากไฟล์ web.xml (เพียงหนึ่งต่อแอปพลิเคชัน) หากมีสิ่งใดผิดพลาดหรือแสดงข้อผิดพลาดที่คอนโซลด้านคอนเทนเนอร์มิฉะนั้นจะปรับใช้และโหลดเว็บทั้งหมด แอ็พพลิเคชันโดยใช้ web.xml (ดังนั้นตั้งชื่อเป็น descriptor การปรับใช้)

ระหว่างเฟสการสร้างอินสแตนซ์ของเซิร์ฟเล็ตอินสแตนซ์ของ servlet จะพร้อมใช้งาน แต่ไม่สามารถให้บริการตามคำขอของไคลเอ็นต์ได้เนื่องจากข้อมูลสองชิ้นหายไป:
1: ข้อมูลบริบท
2: ข้อมูลการกำหนดค่าเริ่มต้น

เอ็นจิ้น servlet สร้าง servletConfig อินเตอร์เฟสวัตถุห่อหุ้มข้อมูลที่หายไปข้างต้นลงในนั้น servlet engine call init () ของ servlet โดยการจัดหา servletConfig อ้างอิงวัตถุเป็นอาร์กิวเมนต์ เมื่อ init () ถูกดำเนินการอย่างสมบูรณ์ servlet ก็พร้อมที่จะให้บริการตามคำขอของลูกค้า

ถาม) ในช่วงอายุการใช้งานของ servlet มีกี่ครั้งที่การเริ่มต้นและการเริ่มต้นเกิดขึ้น?

A) เพียงครั้งเดียว (สำหรับลูกค้าทุกคนที่ร้องขอเธรดใหม่จะถูกสร้างขึ้น) เพียงหนึ่งอินสแตนซ์ของ servlet ให้บริการจำนวนคำขอใด ๆ ของลูกค้าเช่นหลังจากให้บริการหนึ่งเซิร์ฟเวอร์คำขอของลูกค้าไม่ตาย มันรอคำขอไคลเอนต์อื่น ๆ นั่นคือข้อ จำกัด ของ CGI (สำหรับทุกคำขอของลูกค้าที่สร้างกระบวนการใหม่) ด้วย servlet (เอ็นจิน servlet ภายในสร้างเธรด)

Q) แนวคิดของเซสชั่นทำงานอย่างไร

A) เมื่อใดก็ตามที่ getSession () ถูกเรียกบนวัตถุ HttpServletRequest

ขั้นตอนที่ 1 : วัตถุคำขอได้รับการประเมินสำหรับรหัสเซสชันขาเข้า

ขั้นตอนที่ 2 : ถ้า ID ไม่พร้อมใช้งานวัตถุ HttpSession ใหม่จะถูกสร้างขึ้นและ ID เซสชันที่เกี่ยวข้องนั้นถูกสร้างขึ้น (เช่น HashTable) ID เซสชันจะถูกเก็บไว้ในวัตถุตอบสนอง httpservlet และการอ้างอิงของวัตถุ HttpSession จะถูกส่งกลับไปยัง servlet (doGet / doPost) .

ขั้นตอนที่ 3 : หากไม่ได้สร้างวัตถุเซสชันใหม่ ID ที่มีอยู่ ID จะหยิบขึ้นมาจากการค้นหาวัตถุคำขอทำในคอลเลกชันของเซสชันโดยใช้รหัสเซสชันเป็นกุญแจสำคัญ

เมื่อการค้นหาสำเร็จแล้ว ID เซสชันจะถูกเก็บไว้ใน HttpServletResponse และการอ้างอิงวัตถุเซสชันที่มีอยู่จะถูกส่งคืนไปยัง doGet () หรือ doPost () ของ UserDefineservlet

บันทึก:

1) เมื่อการควบคุมปล่อยจาก servlet code ไปยังไคลเอนต์อย่าลืมว่า session object จะถูกเก็บไว้โดย servlet container นั่นคือ servlet engine

2) multithreading ถูกทิ้งไว้ให้กับผู้พัฒนา servlet สำหรับการใช้งานเช่นจัดการกับคำร้องขอหลาย ๆ อย่างของไคลเอนต์โดยไม่ต้องกังวลเกี่ยวกับรหัส multithread

แบบฟอร์มการย่อ:

เซิร์ฟเล็ตถูกสร้างขึ้นเมื่อแอ็พพลิเคชันเริ่มต้น (ถูกปรับใช้บนคอนเทนเนอร์เซิร์ฟเล็ต) หรือเมื่อถูกเข้าถึงครั้งแรก (ขึ้นอยู่กับการตั้งค่า ดังนั้นเซิร์ฟเล็ต (หนึ่งและอินสแตนซ์เดียวเท่านั้น) จัดการคำขอทั้งหมด (บริการของมัน () วิธีการที่ถูกเรียกโดยหลายเธรด) นั่นเป็นสาเหตุที่ไม่แนะนำให้มีการซิงโครไนซ์ใด ๆ ในนั้นและคุณควรหลีกเลี่ยงตัวแปรอินสแตนซ์ของเซิร์ฟเล็ตเมื่อไม่ได้ปรับใช้แอปพลิเคชัน (เซิร์ฟเวอร์ servlet หยุดทำงาน) วิธีทำลาย () ถูกเรียก


20

การประชุม - สิ่งที่คริสทอมป์สันพูด

instantiation - เซิร์ฟเล็ตถูกสร้างเมื่อภาชนะที่ได้รับการร้องขอแรกแมปไปเซิร์ฟเล็ต (เว้นแต่เซิร์ฟเล็ตถูกกำหนดค่าให้โหลดในการเริ่มต้นกับ<load-on-startup>องค์ประกอบในweb.xml) อินสแตนซ์เดียวกันนี้ใช้เพื่อให้บริการตามคำขอ


3
แก้ไข. ความคิดเพิ่มเติม: แต่ละคำขอจะได้รับเธรดใหม่ (หรือรีไซเคิล) เพื่อให้ทำงานบนอินสแตนซ์ Servlet เดียวนั้น แต่ละ Servlet มีหนึ่งอินสแตนซ์และอาจมีหลายเธรด (ถ้ามีหลายคำขอพร้อมกัน)
Basil Bourque

13

Servlet Specification JSR-315กำหนดพฤติกรรมของเว็บคอนเทนเนอร์ในบริการ (และ doGet, doPost, doPut ฯลฯ ) อย่างชัดเจน (2.3.3.1 Multithreading Issues, หน้า 9):

servlet container อาจส่งคำร้องขอพร้อมกันผ่านวิธีการบริการของเซิร์ฟเล็ต เพื่อจัดการกับคำร้องขอผู้พัฒนา Servlet ต้องจัดเตรียมข้อกำหนดที่เพียงพอสำหรับการประมวลผลพร้อมกันที่มีหลายเธรดในวิธีการบริการ

แม้ว่าจะไม่แนะนำ แต่เป็นทางเลือกสำหรับนักพัฒนาที่จะใช้อินเทอร์เฟซแบบ SingleThreadModel ซึ่งต้องการให้คอนเทนเนอร์รับประกันว่ามีเพียงหนึ่งเธรดคำร้องขอในแต่ละครั้งในวิธีการบริการ คอนเทนเนอร์ servlet อาจตอบสนองความต้องการนี้โดยการทำให้เป็นอันดับคำขอบนเซิร์ฟเล็ตหรือโดยการบำรุงรักษากลุ่มของอินสแตนซ์ servlet ถ้าเซิร์ฟเล็ตเป็นส่วนหนึ่งของเว็บแอ็พพลิเคชันที่ถูกทำเครื่องหมายว่าสามารถแจกจ่ายได้คอนเทนเนอร์อาจเก็บพูลของอินสแตนซ์เซิร์ฟเล็ตในแต่ละ JVM ที่แอ็พพลิเคชันกระจาย

สำหรับ servlets ที่ไม่ได้ใช้งานอินเทอร์เฟซ SingleThreadModel หากวิธีการบริการ (หรือวิธีการเช่น doGet หรือ doPost ซึ่งถูกส่งไปยังวิธีการบริการของคลาสนามธรรม HttpServlet) ได้รับการกำหนดด้วยคีย์เวิร์ดที่ซิงโครไนซ์คอนเทนเนอร์ servlet ไม่สามารถใช้ แต่ต้องเรียงลำดับคำขอผ่านมัน ขอแนะนำอย่างยิ่งให้นักพัฒนาไม่ซิงโครไนซ์วิธีการบริการ (หรือวิธีการที่ส่งไป) ในสถานการณ์เหล่านี้เนื่องจากผลกระทบที่เป็นอันตรายต่อประสิทธิภาพการทำงาน


2
FYI ปัจจุบันข้อมูลจำเพาะ Servlet (2015-01) เป็น 3.1 กำหนดโดยJSR 340
Basil Bourque


1
คำตอบที่เรียบร้อยมาก! @tharindu_DG
Tom Taylor

0

จากคำอธิบายข้างต้นชัดเจนจากการใช้SingleThreadModel servlet สามารถมั่นใจได้ในความปลอดภัยของเธรดโดยคอนเทนเนอร์ servlet การใช้คอนเทนเนอร์สามารถทำได้ 2 วิธี:

1) การจัดลำดับคำขอ (การจัดคิว) ให้กับอินสแตนซ์เดียว - ซึ่งคล้ายกับเซิร์ฟเล็ตที่ไม่ได้ใช้งาน SingleThreadModel แต่การซิงโครไนซ์บริการ / วิธีการ doXXX หรือ

2) การสร้างกลุ่มของอินสแตนซ์ - ซึ่งเป็นตัวเลือกที่ดีกว่าและการแลกเปลี่ยนระหว่างความพยายามในการบูต / เริ่มต้น / เวลาของเซิร์ฟเล็ตเมื่อเทียบกับพารามิเตอร์ที่ จำกัด (หน่วยความจำ / เวลา CPU) ของสภาพแวดล้อมที่โฮสต์เซิร์ฟเล็ต


-1

ไม่ Servlets ไม่ปลอดภัยสำหรับเธรด

นี่เป็นการอนุญาตให้เข้าถึงมากกว่าหนึ่งเธรดในแต่ละครั้ง

ถ้าคุณต้องการทำให้ Servlet เป็น Thread ปลอดภัยคุณสามารถทำได้

Implement SingleThreadInterface(i) ซึ่งเป็นอินเตอร์เฟซที่ว่างเปล่าไม่มี

วิธีการ

หรือเราสามารถไปหาวิธีการประสาน

เราสามารถสร้างวิธีการบริการทั้งหมดให้ตรงกันโดยใช้การซิงโครไนซ์

คำสำคัญหน้าวิธีการ

ตัวอย่าง::

public Synchronized class service(ServletRequest request,ServletResponse response)throws ServletException,IOException

หรือเราสามารถใส่บล็อกของรหัสในบล็อกซิงโครไนซ์

ตัวอย่าง::

Synchronized(Object)

{

----Instructions-----

}

ฉันรู้สึกว่าการซิงโครไนซ์บล็อกดีกว่าการทำทั้งวิธี

Synchronized

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.