1. บทนำสู่ Servlet
Servlet เป็นเทคโนโลยีที่จัดทำโดย Sun Company สำหรับการพัฒนาทรัพยากรเว็บแบบไดนามิก
Sun จัดเตรียมอินเทอร์เฟซ servlet ใน API หากผู้ใช้ต้องการส่งทรัพยากรเว็บแบบไดนามิก (นั่นคือพัฒนาโปรแกรม Java เพื่อส่งออกข้อมูลไปยังเบราว์เซอร์) พวกเขาจำเป็นต้องทำสองขั้นตอนต่อไปนี้:
1. เขียนคลาส Java เพื่อใช้อินเตอร์เฟส servlet
2. ปรับใช้คลาส Java ที่พัฒนาขึ้นไปยังเว็บเซิร์ฟเวอร์
ตามนิสัยชื่อทั่วไปเรามักจะเรียกโปรแกรม Java ที่ใช้ servlet อินเตอร์เฟส servlet
2. กระบวนการดำเนินการของ servlet
โปรแกรม servlet เรียกโดยเว็บเซิร์ฟเวอร์ หลังจากเว็บเซิร์ฟเวอร์ได้รับคำขอการเข้าถึง servlet ของลูกค้า:
①เว็บเซิร์ฟเวอร์ก่อนตรวจสอบว่ามีการโหลดและสร้างวัตถุอินสแตนซ์ของ servlet หรือไม่ ถ้าเป็นเช่นนั้นให้ดำเนินการขั้นตอนที่ 4 โดยตรง มิฉะนั้นให้ดำเนินการขั้นตอนที่ 2
②โหลดและสร้างวัตถุอินสแตนซ์ของ servlet
③เรียกเมธอด init () ของวัตถุอินสแตนซ์ servlet
④สร้างวัตถุ HTTPSERVLETREQUEST สำหรับการห่อหุ้มข้อความร้องขอ HTTP และวัตถุ HTTPSERVLETRESSESSESS ที่แสดงข้อความตอบกลับ HTTP จากนั้นเรียกใช้เมธอดบริการของ Servlet () และผ่านวัตถุคำขอและการตอบสนองเป็นพารามิเตอร์
⑤ก่อนที่เว็บแอปพลิเคชันจะหยุดหรือรีสตาร์ทเอ็นจิ้น servlet จะถอนการติดตั้ง servlet และเรียกวิธีการทำลาย () ของ servlet ก่อนที่จะถอนการติดตั้ง
3. ไดอะแกรมการโทร Servlet
4. พัฒนา servlet ใน eclipse
สร้างโครงการเว็บใหม่ใน Eclipse และ Eclipse จะสร้างโครงสร้างไดเรกทอรีที่แสดงในรูปด้านล่างโดยอัตโนมัติ:
4.1. คลาสการใช้งานอินเตอร์เฟส servlet
Servlet Interface Sun Company กำหนดคลาสการใช้งานเริ่มต้นสองคลาสคือ: Genericservlet และ Httpservlet
httpservlet หมายถึง servlet ที่สามารถจัดการคำขอ HTTP มันเพิ่มวิธีการประมวลผลโปรโตคอล HTTP ลงในอินเตอร์เฟสเซิร์ฟเล็ตดั้งเดิมซึ่งมีประสิทธิภาพมากกว่าอินเตอร์เฟส servlet ดังนั้นเมื่อเขียน servlets นักพัฒนาควรสืบทอดคลาสนี้และหลีกเลี่ยงการใช้อินเตอร์เฟส servlet โดยตรง
เมื่อ httpservlet ใช้อินเตอร์เฟส servlet มันจะเขียนทับวิธีการบริการ รหัสในวิธีการจะกำหนดวิธีการร้องขอของผู้ใช้โดยอัตโนมัติ หากเป็นคำขอ GET เมธอด doget ของ httpservlet จะถูกเรียก หากเป็นคำขอโพสต์วิธีการ DOPOST จะถูกเรียก ดังนั้นเมื่อเขียน servlets นักพัฒนามักจะต้องเขียนทับวิธี doget หรือ dopost แทนที่จะเขียนทับวิธีการบริการ
4.2. สร้างและเขียน servlets ผ่าน eclipse
เลือกแพ็คเกจ gacl.servlet.study คลิกขวา→ใหม่→ servlet ดังแสดงในรูปด้านล่าง:
ด้วยวิธีนี้เราจะใช้ Eclipse เพื่อช่วยเราสร้าง servlet ด้วยชื่อ ServletDemo1 จะมีรหัสต่อไปนี้ใน ServletDemo01 ที่สร้างขึ้น
แพ็คเกจ gacl.servlet.study; นำเข้า java.io.ioexception; นำเข้า java.io.printwriter; นำเข้า Javax.servlet.servletexception; นำเข้า Javax.servlet.http.httpservlet; javax.servlet.http.httpservletResponse; คลาสสาธารณะ servletdemo1 ขยาย httpservlet { /*** วิธี detg ของ servlet <br> * * วิธีนี้เรียกว่าเมื่อแบบฟอร์มมีวิธีแท็กค่าเท่ากับที่จะได้รับ * * @param Request คำขอส่งโดยไคลเอนต์ไปยังเซิร์ฟเวอร์ * @param Response การตอบกลับส่งโดยเซิร์ฟเวอร์ไปยังไคลเอนต์ * @throws servletexception หากเกิดข้อผิดพลาด * @throws ioexception หากเกิดข้อผิดพลาด */ โมฆะสาธารณะ Response.SetContentType ("ข้อความ/html"); PrintWriter out = response.getWriter (); out.println ("<! doctype html สาธารณะ/"-// w3c // dtd html 4.01 transitional // en/">"); out.println ("<head> <title> a servlet </title> </head>"); out.println ("<body>"); out.print ("นี่คือ"); out.print (this.getClass ()); out.println ("โดยใช้วิธีการรับ"); out.println ("</body>"); out.println ("</html>"); out.flush (); out.close (); } /*** วิธี DOPOST ของ servlet <br> * * วิธีนี้เรียกว่าเมื่อแบบฟอร์มมีวิธีแท็กค่าเท่ากับโพสต์ * * @param Request คำขอส่งโดยไคลเอนต์ไปยังเซิร์ฟเวอร์ * @param Response การตอบกลับส่งโดยเซิร์ฟเวอร์ไปยังไคลเอนต์ * @throws servletexception หากเกิดข้อผิดพลาด * @throws ioexception หากเกิดข้อผิดพลาด */ โมฆะสาธารณะ Response.SetContentType ("ข้อความ/html"); PrintWriter out = response.getWriter (); out.println ("<! doctype html สาธารณะ/"-// w3c // dtd html 4.01 transitional // en/">"); out.println ("<html>"); out.println ("<head> <title> a servlet </title> </head>"); out.println ("<body>"); out.println ("<body>"); out.println ("นี่คือ"); out.print (this.getClass ()); out.println ("โดยใช้วิธีการโพสต์"); out.println ("</body>"); out.println ("</html>"); out.flush (); out.close (); -รหัสเหล่านี้ถูกสร้างขึ้นโดยอัตโนมัติโดย Eclipse และมีแท็กสองคู่ในไฟล์ web.xml <servlet> </servlet> และ <servlet-mapping> </servlet-mapping> แท็กสองคู่นี้ได้รับการกำหนดค่าด้วย servletDemo1 ดังแสดงในรูปด้านล่าง:
จากนั้นเราสามารถเข้าถึง servletdemo1 servlet ผ่านเบราว์เซอร์ดังแสดงในรูปด้านล่าง:
5. ใส่ใจในรายละเอียดในการพัฒนาเซิร์ฟเล็ต
5.1. การกำหนดค่าการแมป URL Servlet Access
เนื่องจากไคลเอนต์เข้าถึงทรัพยากรในเว็บเซิร์ฟเวอร์ผ่านที่อยู่ URL หากโปรแกรม servlet ต้องการเข้าถึงโดยโลกภายนอกจึงต้องแมปโปรแกรม servlet กับที่อยู่ URL งานนี้ทำในไฟล์ web.xml โดยใช้องค์ประกอบ <servlet> และ <servlet-mapping> องค์ประกอบ
องค์ประกอบ <servlet> ใช้เพื่อลงทะเบียน servlet มันมีองค์ประกอบลูกหลักสององค์ประกอบ: <servlet-name> และ <servlet-class> ซึ่งใช้ในการตั้งค่าชื่อการลงทะเบียนของ servlet และชื่อคลาสเต็มของ servlet ตามลำดับ
องค์ประกอบ A <servlet-mapping> ใช้เพื่อแมปเส้นทางการเข้าถึงภายนอกไปยัง servlet ที่ลงทะเบียน มันมีองค์ประกอบเด็กสององค์ประกอบ: <servlet-name> และ <url-pattern> ซึ่งใช้เพื่อระบุชื่อการลงทะเบียนของ servlet และเส้นทางการเข้าถึงภายนอกของ servlet ตัวอย่างเช่น:
<servlet> <servlet-name> servletdemo1 </servlet-name> <servlet-lass> gacl.servlet.study.servletdemo1 </servlet-lass> </servlet> <servlet-mapping> <servlet-name> servlet เดียวกันสามารถแมปกับ URL หลายตัวนั่นคือค่าการตั้งค่าขององค์ประกอบเด็ก <servlet-name> ขององค์ประกอบ <servlet-mapping> หลายองค์ประกอบสามารถเป็นชื่อการลงทะเบียนของ servlet เดียวกัน ตัวอย่างเช่น: <servlet> <servlet-name> servletdemo1 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo1 </servlet-class> </servlet> <servlet-mapping> <servlet-mapping> <url-pattern>/servlet/servletdemo1 </url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <url-pattern> /1.htm </url-pattern> <url-pattern> /2.jsp </url-pattern> </servlet-mapping> <servlet-mapping> <servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <url-pattern> /3.php </url-pattern> <url-pattern> /4.aspx </url-pattern> </servlet-mapping>
ผ่านการกำหนดค่าข้างต้นเมื่อเราต้องการเข้าถึง servlet ด้วยชื่อ servletDemo1 เราสามารถใช้ที่อยู่ต่อไปนี้เพื่อเข้าถึง:
http: // localhost: 8080/javaweb_servlet_study_20140531/servlet/servletdemo1
http: // localhost: 8080/javaweb_servlet_study_20140531/1.htm
http: // localhost: 8080/javaweb_servlet_study_20140531/2.jsp
http: // localhost: 8080/javaweb_servlet_study_20140531/3.php
http: // localhost: 8080/javaweb_servlet_study_20140531/4.aspx
ServletDemo1 ถูกแมปกับ URL หลายตัว
5.2. ใช้ * การทำแผนที่ไวด์การ์ดสำหรับ URL Servlet Access
อักขระแทนการ์ดสามารถใช้ใน URL ที่แผนที่ servlet ได้ แต่สามารถมีเพียงสองรูปแบบคงที่: หนึ่งคือ "*. ส่วนขยาย" และอีกรูปแบบหนึ่งคือการเริ่มต้นด้วย slash ไปข้างหน้า (/) และลงท้ายด้วย "/*" ตัวอย่างเช่น:
<servlet> <servlet-name> servletdemo1 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo1 </servlet-class> </servlet> <servlet-mapping> <servlet-name>
*สามารถจับคู่อักขระใด ๆ ได้ดังนั้นคุณสามารถใช้ URL ใด ๆ เพื่อเข้าถึง ServletDemo1 Servlet ดังที่แสดงในรูปด้านล่าง:
สำหรับความสัมพันธ์การทำแผนที่ด้านล่าง:
servlet1 แผนที่ไปที่ /abc /*
Servlet2 แผนที่ไปที่ /*
Servlet3 แผนที่ไป /ABC
servlet4 แผนที่ถึง *.do
คำถาม:
เมื่อ URL คำขอคือ "/abc/a.html", "/abc/*" และ "/*" ทั้งคู่ที่ตรงกันซึ่ง Servlet ตอบกลับไปยังเอ็นจิ้น servlet จะเรียก servlet1
เมื่อ URL คำขอคือ "/ABC" ทั้งคู่ "/ABC/*" และ "/ABC" ซึ่ง Servlet ตอบกลับไปยังเอ็นจิ้น servlet จะเรียก servlet3
เมื่อ URL คำขอคือ "/abc/a.do" ทั้งคู่ "/abc/*" และ "*.do" ซึ่ง Servlet ตอบกลับไปยังเอ็นจิ้น servlet จะเรียก servlet1
เมื่อ URL คำขอคือ "/a.do" ทั้ง "/*" และ "*.do" การจับคู่ซึ่ง Servlet ตอบกลับไปยังเอ็นจิ้น servlet จะเรียก servlet2
เมื่อ URL คำขอคือ "/xxxx/yyy/a.do" ทั้งคู่ "/*" และ "*.do" ซึ่ง Servlet ตอบกลับไปยังเอ็นจิ้น servlet จะเรียก servlet2
หลักการของการจับคู่คือ "ใครก็ตามที่ดูเหมือนว่าจะพบว่าใครก็ตามที่ดูมากขึ้น"
5.3. ความแตกต่างระหว่างคลาส Servlet และคลาส Java ธรรมดา
Servlet เป็นคลาส Java สำหรับการโทรโดยโปรแกรม Java อื่น ๆ (Servlet Engines) มันไม่สามารถทำงานได้อย่างอิสระและการดำเนินการของมันถูกควบคุมและกำหนดโดยเอ็นจิ้นเซิร์ฟเล็ตอย่างสมบูรณ์
สำหรับคำขอ servlet หลายตัวจากไคลเอนต์โดยปกติแล้วเซิร์ฟเวอร์จะสร้างวัตถุอินสแตนซ์เซิร์ฟเล็ตเท่านั้น กล่าวคือเมื่อวัตถุอินสแตนซ์เซิร์ฟเล็ตถูกสร้างขึ้นมันจะอยู่ในหน่วยความจำและให้บริการคำขออื่น ๆ ที่ตามมา วัตถุอินสแตนซ์ servlet จะไม่ถูกทำลายจนกว่าเว็บคอนเทนเนอร์จะออก
ตลอดชีวิตของ Servlet วิธีการเริ่มต้นของ servlet เรียกว่าเพียงครั้งเดียว คำขอการเข้าถึงแต่ละครั้งไปยัง servlet ทำให้เอ็นจิ้น servlet เรียกใช้วิธีการบริการ servlet หนึ่งครั้ง สำหรับการร้องขอการเข้าถึงแต่ละครั้งเอ็นจิ้น Servlet จะสร้างวัตถุคำขอ HTTPSERVLETREQUEST ใหม่และวัตถุตอบกลับ HTTPSERVLETRESSESSENSE ใหม่จากนั้นส่งผ่านวัตถุทั้งสองนี้เป็นพารามิเตอร์ไปยังวิธีการบริการ () ของ Servlet ที่เรียก วิธีการบริการจะเรียกวิธี Doxxx ตามวิธีการร้องขอ
หากองค์ประกอบ <load-on-startup> ถูกกำหนดค่าในองค์ประกอบ <servlet> จากนั้นเมื่อเว็บแอปพลิเคชันเริ่มต้นจะโหลดและสร้างวัตถุอินสแตนซ์ servlet และเรียกเมธอด init () ของวัตถุอินสแตนซ์ servlet
ตัวอย่างเช่น:
<servlet> <servlet-name> Invoker </servlet-name> <servlet-class> org.apache.catalina.servlets.invokerservlet </servlet-class> <load-on-startup> 1 </load-on-startup>
วัตถุประสงค์: เขียน InitServlet สำหรับเว็บแอปพลิเคชัน servlet นี้ได้รับการกำหนดค่าให้โหลดเมื่อเริ่มต้นเพื่อสร้างตารางฐานข้อมูลที่จำเป็นและข้อมูลสำหรับเว็บแอปพลิเคชันทั้งหมด
5.4. servlet เริ่มต้น
หากเส้นทางการแมปของ servlet เป็นเพียง slash ไปข้างหน้า (/) ดังนั้น servlet นี้จะกลายเป็น servlet เริ่มต้นของแอปพลิเคชันเว็บปัจจุบัน
URL ใด ๆ ขององค์ประกอบ <servlet-mapping> ที่ไม่สามารถพบได้ในไฟล์ web.xml คำขอการเข้าถึงของพวกเขาจะถูกส่งไปยัง Servlet เริ่มต้นสำหรับการประมวลผลนั่นคือ servlet เริ่มต้นใช้เพื่อจัดการคำขอการเข้าถึงที่ไม่ได้ประมวลผลโดย servlets อื่น ๆ ตัวอย่างเช่น:
<servlet> <servlet-name> servletdemo2 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo2 </servlet-class> <load-on-startup> 1 </load-on-startup> </servlet> <servlet-name> servletdemo2 </servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
เมื่อเข้าถึง servlet ที่ไม่มีอยู่จริง servlet เริ่มต้นที่กำหนดค่าจะใช้สำหรับการประมวลผลดังแสดงในรูปด้านล่าง:
ใน <tomcat directory> /conf/web.xml ไฟล์ไฟล์ servlet ชื่อ org.apache.catalina.servlets.defaultservlet ได้ลงทะเบียนและ Servlet นี้ถูกตั้งค่าเป็น Servlet เริ่มต้น
<servlet> <servlet-name> ค่าเริ่มต้น </servlet-name> <servlet-lass> org.apache.catalina.servlets.defaultservlet </servlet-lass> <init-param> <param-name> debug </param-name> <param-value> false </param-value> </init-param> <load-on-startup> 1 </load-on-startup> </servlet> <!-การแมปสำหรับ Servlet เริ่มต้น-> <servlet-mapping>
เมื่อเข้าถึงไฟล์และรูปภาพ HTML แบบคงที่ในเซิร์ฟเวอร์ Tomcat คุณกำลังเข้าถึง servlet เริ่มต้นนี้จริง ๆ
5.5. ปัญหาด้านความปลอดภัยของด้ายเซิร์ฟเล็ต
เมื่อไคลเอนต์หลายรายเข้าถึงเซิร์ฟเล็ตเดียวกันพร้อมกันเว็บเซิร์ฟเวอร์จะสร้างเธรดสำหรับคำขอการเข้าถึงของไคลเอนต์แต่ละรายการและเรียกใช้วิธีการบริการของเซิร์ฟเล็ตในเธรดนี้ ดังนั้นหากมีการเข้าถึงทรัพยากรเดียวกันในวิธีการบริการอาจทำให้เกิดปัญหาด้านความปลอดภัยของด้าย ตัวอย่างเช่นรหัสต่อไปนี้:
รหัสที่ไม่มีปัญหาด้านความปลอดภัยของเธรด:
แพ็คเกจ gacl.servlet.study; นำเข้า java.io.ioexception; นำเข้า Javax.servlet.servletexception; นำเข้า Javax.servlet.http.httpservlet; นำเข้า Javax.servlet.http.httpservletRequest; javax.servlet.http.httpservletResponse; คลาสสาธารณะ servletdemo3 ขยาย httpservlet {โมฆะสาธารณะ doget (httpservletrequest คำขอ, httpservletresponse การตอบสนอง) การตอบสนองความปลอดภัย ตัวแปร I ถูกเข้าถึงพร้อมกันหลายเธรด แต่ไม่มีปัญหาด้านความปลอดภัยของเธรดเพราะฉันเป็นตัวแปรท้องถิ่นในวิธีการ DOGE * เมื่อหลายเธรดเข้าถึงวิธี detg พร้อมกันแต่ละเธรดมีตัวแปร I ของตัวเอง * แต่ละเธรดแต่ละตัวทำงานตัวแปร I ของตัวเองดังนั้นจึงไม่มีปัญหาด้านความปลอดภัยของเธรด * เมื่อมัลติเธรดเข้าถึงวิธีการบางอย่างพร้อมกันหากมีทรัพยากรบางอย่าง (ตัวแปรคอลเลกชัน ฯลฯ ) i ++; Response.getWriter (). เขียน (i); } โมฆะสาธารณะ dopost (คำขอ httpservletrequest, httpservletResponse การตอบสนอง) พ่น servletexception, ioexception {doget (คำขอ, การตอบสนอง); - รหัสที่มีปัญหาด้านความปลอดภัยของเธรด:
แพ็คเกจ gacl.servlet.study; นำเข้า java.io.ioexception; นำเข้า Javax.servlet.servletexception; นำเข้า Javax.servlet.http.httpservlet; นำเข้า javax.servlet.http.httpservletrequest; ขยาย httpservlet {int i = 1; โมฆะสาธารณะ DOGET (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) พ่น servletexception, ioexception {i ++; ลอง {thread.sleep (1,000*4); } catch (interruptedException e) {e.printStackTrace (); } response.getWriter (). เขียน (i+""); } โมฆะสาธารณะ dopost (คำขอ httpservletrequest, httpservletResponse การตอบสนอง) พ่น servletexception, ioexception {doget (คำขอ, การตอบสนอง); -กำหนดว่าฉันเป็นตัวแปรระดับโลก เมื่อหลายเธรดการเข้าถึงตัวแปรฉันพร้อมกันจะมีปัญหาด้านความปลอดภัยของเธรดดังแสดงในรูปด้านล่าง: เปิดเบราว์เซอร์สองตัวในเวลาเดียวกันเพื่อจำลองการเข้าถึง servlet เดียวกันพร้อมกัน โดยปกติเบราว์เซอร์แรกควรเห็น 2 และเบราว์เซอร์ที่สองควรเห็น 3 แต่เบราว์เซอร์ทั้งสองมองเห็น 3 ซึ่งไม่ปกติ
ปัญหาด้านความปลอดภัยของเธรดจะมีอยู่เฉพาะเมื่อหลายเธรดทำงานทรัพยากรเดียวกันพร้อมกัน ดังนั้นเมื่อเขียน servlet หากมีการเข้าถึงทรัพยากรบางอย่าง (ตัวแปรการรวบรวม ฯลฯ ) พร้อมกันจะมีปัญหาด้านความปลอดภัยของเธรด แล้วจะแก้ปัญหานี้ได้อย่างไร?
มาดูรหัสต่อไปนี้:
แพ็คเกจ gacl.servlet.study; นำเข้า java.io.ioexception; นำเข้า Javax.servlet.servletexception; นำเข้า Javax.servlet.http.httpservlet; นำเข้า javax.servlet.http.httpservletrequest; ขยาย httpservlet {int i = 1; โมฆะสาธารณะ DOGET (คำขอ httpservletRequest, การตอบสนอง httpservletResponse) พ่น servletexception, ioexception { /*** หลังจากเพิ่มการซิงโครไนซ์แล้วไม่มีปัญหาด้านความปลอดภัยของเธรดเมื่อเข้าถึง i * เหตุใดจึงไม่มีปัญหาด้านความปลอดภัยของเธรดหลังจากเพิ่มการซิงโครไนซ์? * หากมีเธรดที่เข้าถึงวัตถุ Servlet ในขณะนี้มันจะได้รับการล็อคของวัตถุ servlet* หลังจากดำเนินการแล้วมันจะส่งคืนการล็อคไปยังวัตถุ Servlet เนื่องจากเป็นครั้งแรกที่ได้รับการล็อคของวัตถุ servlet * ดังนั้นเมื่อเธรดอื่นเข้าถึงวัตถุ servlet เนื่องจากล็อคถูกนำออกไปโดยเธรดก่อนหน้าเธรดที่ตามมาสามารถรอได้ในบรรทัด * */ซิงโครไนซ์ (นี้) {// ใน Java แต่ละวัตถุมีล็อค ลอง {thread.sleep (1,000*4); } catch (interruptedException e) {e.printStackTrace (); } response.getWriter (). เขียน (i+""); }} โมฆะสาธารณะ dopost (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) พ่น servletexception, ioexception {doget (คำขอ, การตอบกลับ); -ตอนนี้วิธีการนี้คือการเพิ่มล็อคไปยังวัตถุ servlet เพื่อให้มั่นใจว่ามีเพียงเธรดเดียวเท่านั้นที่เข้าถึงทรัพยากรในวัตถุ Servlet ได้ตลอดเวลาดังนั้นจะไม่มีปัญหาด้านความปลอดภัยของเธรดดังแสดงในรูปด้านล่าง:
แม้ว่าวิธีนี้จะแก้ปัญหาความปลอดภัยของด้ายการเขียน Servlets จะต้องไม่จัดการกับปัญหาความปลอดภัยของด้ายด้วยวิธีนี้ หาก 9999 คนเข้าถึง servlet ในเวลาเดียวกันผู้คน 9999 คนเหล่านี้จะต้องเข้าคิวเพื่อเข้าถึงตามลำดับ
ในการตอบสนองต่อปัญหาความปลอดภัยของเธรดของ Servlets Sun ให้วิธีแก้ปัญหา: ให้ Servlet ใช้อินเตอร์เฟส SinglethreadModel หาก Servlet ใช้อินเตอร์เฟส SingleThreadModel เอ็นจิ้น servlet จะเรียกวิธีการบริการในโหมดเธรดเดี่ยว
เมื่อดูที่ Sevlet API คุณจะเห็นได้ว่าอินเตอร์เฟส SinglethreatHreadModel ไม่ได้กำหนดวิธีการหรือค่าคงที่ใด ๆ ใน Java อินเทอร์เฟซที่ไม่ได้กำหนดวิธีการหรือค่าคงที่ใด ๆ ที่เรียกว่าแท็กอินเตอร์เฟส หนึ่งในอินเตอร์เฟสแท็กทั่วไปที่คุณมักจะเห็นคือ "serializable" อินเทอร์เฟซนี้ยังไม่ได้กำหนดวิธีการหรือค่าคงที่ใด ๆ การใช้อินเตอร์เฟสแท็กใน Java คืออะไร? ฟังก์ชั่นหลักคือการทำเครื่องหมายวัตถุและบอก JVM ว่าวัตถุนี้สามารถทำอะไรได้บ้าง ตัวอย่างเช่นวัตถุของคลาสที่ใช้อินเทอร์เฟซ "serializable" สามารถทำให้เป็นอนุกรมและยังมีอินเทอร์เฟซ "cloneable" ซึ่งเป็นอินเตอร์เฟสแท็ก โดยค่าเริ่มต้นวัตถุใน Java จะไม่ได้รับอนุญาตให้โคลนเช่นเดียวกับผู้คนในชีวิตจริงการโคลนนิ่งไม่ได้รับอนุญาต แต่ตราบใดที่อินเทอร์เฟซ "cloneable" ถูกนำไปใช้งานสามารถโคลนวัตถุได้
ให้ servlet ใช้อินเทอร์เฟซ SinglethreatHreadModel เพียงเพิ่มการประกาศเพื่อใช้อินเตอร์เฟส SingLetHreadModel ไปยังคำจำกัดความของคลาส Servlet
สำหรับ Servlets ที่ใช้อินเตอร์เฟส SingLetHreadModel เอ็นจิ้น servlet ยังคงรองรับการเข้าถึงแบบมัลติเธรดมัลติเธรดพร้อมกับ servlet วิธีการคือการสร้างวัตถุอินสแตนซ์ servlet หลายรายการและแต่ละเธรดพร้อมกันเรียกวัตถุอินสแตนซ์เซิร์ฟเล็ตอิสระแยกกัน
การใช้อินเทอร์เฟซ SingleThreadModel ไม่สามารถแก้ปัญหาความปลอดภัยของเธรดของ Servlets ได้จริง ๆ เนื่องจากเอ็นจิ้น servlet จะสร้างวัตถุอินสแตนซ์เซิร์ฟเล็ตหลายรายการและการแก้ปัญหาความปลอดภัยแบบมัลติเธรดอย่างแท้จริงหมายถึงปัญหาที่วัตถุอินสแตนซ์เซิร์ฟเล็ตถูกเรียกโดยหลายเธรดในเวลาเดียวกัน ในความเป็นจริงใน Servlet API 2.4 SinglethreadModel ได้รับการทำเครื่องหมายว่าเลิกใช้แล้ว (ล้าสมัย)
ข้างต้นเป็นเรื่องเกี่ยวกับบทความนี้ฉันหวังว่ามันจะเป็นประโยชน์กับการเรียนรู้ของทุกคน