javacentrix com chap07-0

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

Upload: -

Post on 07-Aug-2015

90 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Javacentrix com chap07-0

บทที ่ 7 คุกก ี ้และเซสชั ่นด้วยเซ ิร ์ฟเล ็ต

การทำงานของระบบเว็บซึ่งประกอบด้วยบราวเซอร์และเว็บเซิร์ฟเวอร์นั่น

การทำงานในการเชื่อมโยงการติดต่อเป็นรูปแบบที่อิสระต่อกัน

กล่าวคือเว็บเซิร์ฟเวอร์จะไม่จดจำสถานการณใ์ช้งานของบราวเซอร์และไม่สามาร

ถทราบได้ว่า การร้องขอข้อมูลแต่ละครั้งมาจากบราวเซอร์เดียวกัน

ในเทคโนโลยีของเซิร์ฟเล็ตนั้นได้ออกแบบรองรับในจุดนี้

โดยได้มีการนำรูปแบบมาใช้งานคือคุกกี้ซึ่งผู้พัฒนาระบบสามารถจัดการข้อมูลคุก

กี้ได้อย่างง่ายดายผ่านคลาส Cookie

นอกเหนือไปจากนั้นเซิร์ฟเล็ตยังสามารถทำงานในรูปแบบเซสชั่นซึ่งสามาร

ถปฏิบัติการให้การใช้งานมีรูปแบบเป็นกิจกรรมดำเนินงานคือมีจุดเริ่มต้น

และมีจุดสิ้นสุดการใช้งานโดยสามารถบันทึกข้อมูลการใช้งานของผู้ใช้

ไม่ว่าผู้ใช้จะมีการย้ายการดูข้อมูลไปอยู่จุดใดก็ได้ตามที่ผู้สร้างระบบได้ออกแบบเอ

าไว ้

ท้ายสุดของบทมีตัวอย่างการสร้างเซิร์ฟเล็ตที่ปฏิบัติงานทางด้านพาณิชย์อิเล็

กทรอนิกส์อย่างง่าย

เพื่อให้ผู้อ่านได้เห็นตัวอย่างการนำเอาเซสชั่นมาประยุกต์งานเพื่อให้เกิดเป็นระบบ

งานเกิดขึ้น

Page 2: Javacentrix com chap07-0

ด้วยการทำงานของรูปแบบระบบเว็บโดยทั่วไปคือการรับ-ส่งข้อมูลเอกสาร HTML จากเว็บเซิร์ฟเวอร์และบราวเซอร์ต่อมา

การใช้งานมีจำนวนหลากหลายยิ่งขึ้น ทั้งจากจำนวนและเทคโนโลยีที่สืบเนื่องจากการใช้งาน

มีรูปแบบการจัดสร้างระบบงานบนเว็บที่น่าสนใจ และมีการนำไปใช้งานกันอย่างกว้างขวางให้เกิดเป็นระบบงานทางธุรกิจเช่น

พาณิชย์อิเล็กทรอนิกส์ (E-Commerce) เกิดขึ้น คือคุกกี้ (Cookie) และเซสชั่น (Session)

โดยคุกกี้เป็นการจัดเก็บข้อมูลขนาดเล็กจากเว็บเซิร์ฟเวอร์ไว้บนบราวเซอร์ เพื่อที่เว็บเซิร์ฟเวอร์จะสามารถอ่านเข้ามาใช้งานได้ในภายหลัง

ส่วนเซสชั่นเป็นการที่เว็บเซิร์ฟเวอร์จะสามารถจดจำสถานะปัจจุบันของการใช้งานจากผู้ใช้บนบราวเซอร์ได้

โดยทั้งสองรูปแบบสามารถสร้างเซิร์ฟเล็ตให้จัดการในรูปแบบดังกล่าวได้ ดังรายละเอียดต่อไปนี ้

1. ความหมายของคุกกี้ (Cookie)

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

โดยที่บราวเซอร์สามารถจัดเก็บไว้ที่พื้นที่ที่เรียกว่าแคช เพื่อนำมาใช้งานในภายหลังได้

และข้อมูลดังกล่าวที่ใช้ในการจัดเก็บถือว่าเป็นเนื้อข้อมูลที่เว็บเซิร์ฟเวอร์ต้องการนำเสนอต่อบราวเซอร์เท่านั้น

แต่หากเว็บเซิร์ฟเวอร์ต้องการส่งข้อมูลนอกเหนือจากนั้นมาจัดเก็บไว้ในพื้นที่ใดๆของบราวเซอร์ก่อน

เพื่อในภายหลังหากบราวเซอร์เรียกใช้งานเว็บเซิร์ฟเวอร์ตัวเดิม เว็บเซิร์ฟเวอร์ก็จะหยับเอาข้อมูลนี้มาใช้งานในภายหลัง

ซึ่งข้อมูลนี้เรียกกันโดยทั่วไปว่าคุกกี้

รูปแสดงการจัดเก็บและการเรียกใช้ข้อมูลคุกกี้

การใช้ประโยชน์จากคุกกี้นั้นสามารถนำมาประยุกต์การใช้งานได้ เช่น

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

เว็บเซิร์ฟเวอร์ก็จะส่งชื่อและนามสกุลผู้ใช้มาเก็บไว้ที่บราวเซอร์เอง

และหลังจากนั้นหากบราวเซอร์มีการเรียกใช้เว็บเซิร์ฟเวอร์ตัวเดียวกันนี้อีก

เว็บเซิร์ฟเวอร์ก็จะอ่านชื่อและนามสกุลที่ฝากไว้ที่บราวเซอร์มาใช้ได้เลย

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

ซึ่งเป็นการอำนวยความสะดวกในการใช้งานเกิดขึ้นนั้นเอง

ลักษณะในการจัดเก็บข้อมูลดังกล่าวอาจไม่เกิดผลดีนัก หากการเก็บข้อมูลที่บราวเซอร์เป็นการเก็บข้อมูลที่สำคัญ เช่น

หมายเลขรหัสผ่าน หมายเลขบัตรเครดิต เป็นต้น

เนื่องจากหากผู้อื่นที่ไม่ใช้เจ้าของเครื่องคอมพิวเตอร์สามารถเข้ามายังเครื่องที่จัดเก็บข้อมูลคุกกี้ดังกล่าวไว้

ก็สามารถเข้าไปอ่านข้อมูลคุกกี้นี้อย่างง่ายดาย และนำไปใช้ประโยชน์ส่วนตัวได้

การจัดเก็บข้อมูลคุกกี้ของบราวเซอร์นั้นมีการจัดเก็บข้อมูลที่เป็นรูปแบบตัวอักษรเท่านั้น

ดังนั้นจึงไม่จำเป็นต้องกลัวว่าเว็บเซิร์ฟเวอร์จะส่งไวรัสคอมพิวเตอร์มาได้ เนื่องจากตัวอักษรไม่สามารถทำตัวเป็นไวรัสคอมพิวเตอร์ได้

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

โดยแต่ละคุกกี้จะบรรจุข้อมูลตัวอักษรได้ไม่เกิน 4 กิโลไบต์ และจำนวนคุกกี้ทั้งหมดในบราวเซอร์อ้างถึงเว็บเซิร์ฟเวอร์ทุกตัวต้องไม่เกิน

3,000 คุกกี้ ดังนั้นผู้ใช้จำไม่ต้องกังวลเรื่องขนาดข้อมูลจะไปกระทบถึงพื้นที่ใช้งานปกติ

นอกจากนั้นแล้วหากผู้ใช้บราวเซอร์ไม่ต้องการให้มีการจัดเก็บคุกกี้ไว้ที่เครื่องของตนเองก็สามารถยกเลิกพฤติกรรมนี้ได้โดยตรงจากบราว

เซอร์เอง

2. การใช้งานคุกกี้

เซิร์ฟเล็ตสามารถควบคุมการใช้งานคุกกี้ผ่านทางข้อมูลส่วนหัวของโพรโตคอล HTTTP

โดยหากต้องการจัดเก็บข้อมูลคุกกี้ไว้ที่บราวเซอร์ก็กำหนดผ่านข้อมูลส่วนหัวโต้ตอบ (ส่วน Set-Cookie)ไปยังบราวเซอร์ก่อน

หลังจากนั้นหากเว็บเซิร์ฟเวอร์มีการอ้างจากบราวเซอร์ในเส้นทางเดิมอีกบราวเซอร์ก็จะส่งข้อมูลคุกกี้นี้มายังขอ้มูลส่วนหัวร้องขอ (ส่วน

Page 3: Javacentrix com chap07-0

Cookie) มาให้เว็บเซิร์ฟเวอร์ด้วย ดังนั้นเซิร์ฟเล็ตก็สามารถอ่านข้อมูลดังกล่าวมาใช้งานได้ แต่สำหรับการใช้งานคุกกี้แล้วคลาส

HttpServletRequest และ Htttp

ServletResponse มีเมธอดเฉพาะสำหรับการดำเนินงานในส่วนคุกกี้ให้ใช้งานได้อย่างสะดวก

โดยไม่จำเป็นต้องจัดการข้อมูลส่วนหัวให้ยุ่งยากเลย ดังมีรายละเอียดคือ

รายละเอียดที่เกี่ยวข้องกับการใช้งานคุกกี้

คอนสตรักเตอร์ของคลาส Cookie

Cookie()

Cookie(String name, String value)

คอนสตรักเตอร์ของคลาส Cookie สำหรับกำหนดชื่อ name และข้อมูลใน value โดยการตั้งชื่อคุกกี้นั้น

ให้ใช้ภาษาอังกฤษสามารถมีช่องว่าง และสัญลักษณ์ [ ] ( ) = , " / ? @ : ;ได้

เมธรอดที่เกี่ยวกับการกำหนดค่า และการอ่านค่าของคลาส Cookie

public void setComment(String comment)

ใช้กำหนดข้อมูลเสริมของคุกกี้ เหมือนการใส่หมายเหตุเพื่ออธิบายรายละเอียดของการใช้งานคุกกี้ตัวนี้

โดยแต่ละคุกกี้สามารถมีข้อมูลหมายเหตุแยกแต่ละตัวได้

public String getComment()

สำหรับอ่านข้อมูลหมายเหตุของคุกกี้

public void setDomain(String domain)

สำหรับกำหนดชื่อโดเมน เพื่อให้ใช้งานคุกกี้เดียวกันนี้ได้ โดยรูปแบบโดเมนต้องมีสัญญาลักษณ .

อยู่มากกว่า 2 ตำแหน่ง เช่น .javacentrix.com หรือ .kmitl.ac.th เป็นต้น

public String getDomain()

สำหรับอ่านค่าโดเมนเพื่อใช้งาน

public void setMaxAge(int lifetime)

สำหรับกำหนดอายุคุกกี้ที่จะเก็บไว้ที่บราวเซอร์ หากเกิดกำหนดบราวเซอร์จะลบออกจากเครื่อง

มีหน่วยเป็นวินาที หากกำหนดเป็น 0 หรือค่าติดลบ หมายถึงให้ลบทันทีที่เลิกใช้งานบราวเซอร ์

public int getMaxAge()

สำหรับอ่านข้อมูลอายุของคุกกี้

public void setName(String name)

สำหรับกำหนดชื่อให้กับคุกกี ้

public String getName()

สำหรับอ่านชื่อของคุกกี้

public void setPath(String path)

สำหรับกำหนดเส้นทางที่จะใช้งานคุกกี้ได้ โดยระบุเป็นข้อมูล url โดยที่ไม่ต้องระบุไฟล์เอกสาร

เช่น http://online.javacentrix.com/order/ แต่ไม่ใช่ http://online.javacentrix.com/order/new.html

public String getPath()

Page 4: Javacentrix com chap07-0

สำหรับอ่านข้อมูลเส้นที่ที่คุกกี้จัดเก็บไว้สำหรับใช้งาน

public void setSecure(boolean flag)

สำหรับค่าสถานการณร์ักษาความปลอดภัยในการเข้ารหัสข้อมูลแบบ SSL คือเริ่มต้นคือ false

public boolean getSecure()

สำหรับค่าสถานการณร์ักษาความปลอดภัย

public void setValue(String value)

สำหรับกำหนดข้อมูลให้กับคุกกี้

public String getValue()

สำหรับอ่านชื่อคุกกี้

public void setVersion(int version)

สำหรับกำหนดเวอร์ชันให้กับคุกกี ้

public int getVersion()

สำหรับอ่านเวอร์ชันของคุกกี้

การส่งคุกกี้ไปเก็บที่บราวเซอร์

ในการส่งข้อมูลไปเก็บไว้เป็นคุกกี้ในบราวเซอร์จำเป็นต้องเริ่มต้นจากเซิร์ฟเล็ตส่งไปให้ในครั้งแรกก่อน

ซึ่งการจะเก็บได้หรือไม่ได้ขึ้นอยู่กับความยินยอมที่กำหนดจากโปรแกรมบราวเซอร์เอง

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

(ยกเว็บผู้ใช้เข้าไปดูคุกกี้ภายในเครื่องใช้งานเอง) โดยต้องอาศัยเมธอด addCookie ของคลาส HttpServletResponse

มีรูปแบบการจัดเก็บดังนี ้

Cookie my_cookie = new Cookie("WebsiteName", "JavaCentrix.com");

my_cookie.setMagAge(60 * 60); // กำหนดเวลาหนึ่งชั่วโมง (วินาที x นาที) ในการเก็บไว้ที่บราวเซอร ์

response.addCookie(my_cookie);

จากตัวอย่างเป็นส่วนของคำสั่งเพื่อสร้างคุกกี้ชื่อ WebsiteName ที่บรรจุข้อมูล JavaCentrix.com

และกำหนดให้มีอายุการจัดเก็บที่บราวเซอร์ 1 ชั่วโมงหลังจากนั้นบราวเซอร์จะรับผิดชอบในการลบคุกกี้ออกจากระบบเอง

และในคำสั่งต่อมาเป็นการใส่คุกกี้ให้กับส่วนโต้ตอบของเซิร์ฟเล็ตผ่านเมธอด addCookie

เพื่อที่เวลาเซิร์ฟเล็ตส่งข้อมูลกลับให้บราวเซอร์จะส่งข้อมูลคุกกี้ไปที่ข้อมูลโต้ตอบส่วนหัวไปด้วย

การอ่านคุกกี้จากบราวเซอร์

สำหรับการอ่านข้อมูลคุกกี้นั้นเซิร์ฟเล็ตที่ทำหน้าที่อ่านข้อมูลจากคุกกีไ้ด้นั้น สามารถเรียกใช้เมธอด getCookie จากคลาส

HttpServletRequest ได้เลย หากเคยส่งคุกกี้ไปเก็บไว้ที่บราวเซอร์แล้ว แต่หากไม่เคยเมธอดดังกล่าวจะคือค่า null กลับมา

และเมื่อเซิร์ฟเล็ตได้รับคุกกี้กลับมา ก็สามารถเรียกใช้เมธอดคุกกี้ในกลุ่ม getXxx

ที่มีรายละเอียดอยู่ก่อนหน้านี้อ่านข้อมูลมาใช้งานได้ต่อไป

ตัวอย่างการใช้งานคุกกี้

ตัวอย่างการกำหนดคุกกี้เป็นตัวนับ

Page 5: Javacentrix com chap07-0

ก่อนที่จะดูตัวอย่างการงานคุกกี้

ขอเสริมรายละเอียดของคลาสหนึ่งคลาสที่บรรจุเมธอดเพื่อใช้งานคุกกี้ให้สะดวกยิ่งขึ้นคลาสดังกล่าวคือ ServeltUtilitiese

ที่บรรจุอยู่ในแพ็กเกจ EJP ในไฟล์ ServeltUtilitiese.java ดังมีซอร์สโค้ดดังนี้ 1 package EJP; 2 import java.io.*; 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 6 public class ServletUtilities { 7 public static int DAY_LIFE = 60*60*24; 8 public static int MONTH_LIFE = 60*60*24*30; 9 public static int YEAR_LIFE = 60*60*24*365; 10 11 public static Cookie getCookie(Cookie[] cookies, String name) { 12 Cookie this_cookie; 13 if (cookies == null) 14 return null; 15 for(int i=0; i<cookies.length; i++) { 16 this_cookie = cookies[i]; 17 if (this_cookie.getName().equals(name)) 18 return this_cookie; 19 } 20 return null; 21 } 22 public static String getCookieValue(Cookie[] cookies, String name, String default_value) { 23 Cookie cookie = getCookie(cookies, name); 24 if (cookie!=null) 25 return cookie.getValue(); 26 else return default_value; 27 } 28 }

จากตัวอย่างซอร์สโค้ดด้านบนมีการกำหนดค่าคงที่ให้กับ DAY_LIFE เพื่อกำหนดเวลาหนึ่งวันซึ่งมีค่าเป็นมิลลิวินาทีเกิดจาก 60

วินาทีคูณ 60 วินาทีคูณ 24 ชั่วโมง และเช่นกันค่าคงที่ MONTH_LIFE และ YEAR_LIFE สำหรับเวลาหนึ่งเดือนและหนึ่งปีตามลำดับ

นอกจากนั้นเมธอด getCookie เป็นการดึงอินสแตนซ์ Cookie หนึ่งตัวออกจากอะเรย์ cookies หากมีชื่อคุกกี้ตรงกับข้อมูล name

ในส่วนพารามิเตอร์ของเมธอด และหากไม่มีการคุกกี้ที่ต้องการก็จะได้รับค่า null กลับมา

สำหรับ getCookieValue คือเมธอดที่ดึงค่าข้อมูลออกจากคุกกี้เหมือนกับคลาส getCookie

แต่ต่างกันที่หากไม่มีค่าของคุกกี้ที่ต้องการก็จะส่งค่า default_value ที่ระบุในพารามิเตอร์กลับมา

คลาส ServletUtilities นี้จะถูกนำมาใช้งานในตัวอย่างต่อไปนี้ 1 import java.io.*; 2 import java.util.*; 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import EJP.HTMLUtilities; 6 import EJP.ServletUtilities; 7 8 public class CookieCounter extends HttpServlet { 9 public void doGet (HttpServletRequest request, HttpServletResponse response) 10 throws ServletException, IOException { 11 response.setContentType("text/html; charset=windows-874"); 12 PrintWriter out = response.getWriter(); 13 HTMLUtilities.createHTMLStart(out, "Counter by Cookie");

Page 6: Javacentrix com chap07-0

14 Cookie cookies[] = request.getCookies(); 15 String counter = ServletUtilities.getCookieValue(cookies, "counter", null); 16 if (counter!=null) { 17 counter = (Integer.parseInt(counter) + 1) + ""; 18 19 } else { 20 counter = "1"; 21 } 22 Cookie cookie_counter = new Cookie("counter", counter); 23 cookie_counter.setMaxAge(ServletUtilities.YEAR_LIFE); 24 response.addCookie(cookie_counter); 25 out.println("<H1><CENTER>������������������������������� " + counter + "</CENTER></H1>"); 26 HTMLUtilities.createHTMLEnd(out); 27 } 28 public void doPost (HttpServletRequest request, HttpServletResponse response) 29 throws ServletException, IOException { 30 doGet(request,response); 31 } 32 }

จากตัวอย่างคลาส CookieCounter เป็นการสร้างตัวนับการใช้งานเว็บโดยอาศัยการทำงานของคุกกี ้เริ่มต้นที่ในบรรทัดที่ 14

ของซอร์สโค้ดเป็นการอ่านข้อมูลคุกกี้ที่ได้รับมาจากบราวเซอร์ทุกตัวมาเก็บไว้ในอะเรย์ cookies

จากนั้นในสเตจเม็นต์ถัดมาของบรรทัดที่ 15 อะเรย์ดังกล่าวจะถูกผ่านเป็นพารามิเตอร์ไปในเมธอด getCookieValue ของคลาส

ServletUtilities เพื่อหาว่ามีคุกกี้ชื่อ counter อยู่หรือไม่ หากมีจะได้รับข้อมูลมาเก็บไว้ในตัวแปร counter

(สังเกตจากตัวอย่างเป็นตัวเอียงในซอร์สโค้ด) หากไม่มีก็จะได้รับคือ null กลับมายังตัวแปร counter

ซึ่งในการใช้งานครั้งแรกของเซิร์ฟเล็ต CookieCounter นี้ค่าคุกกี้จะเป็น null เนื่องจากยังไม่เคยมีการส่งคุกกี้ไปเก็บมาก่อน ดังนั้นตัวแปร

counter จึงถูกกำหนดให้เป็นการใช้งานครั้งแรกจากบรรทัดที่ 20 แต่หากมีบราวเซอร์มีคุกกี้ชื่อ counter

แล้วข้อมูลที่ได้รับมาใส่ไว้ในตัวแปร counter ดังนั้นในบรรทัดที่ 17 ค่าในตัวแปร counter จะถูกแปลงเป็นตัวเลขจากเมธอด

Integer.parstInt และนำไปเพิ่มค่าขึ้นหนึ่งค่า จากนั้นแปลงเป็นข้อความเก็บไว้ในตัวแปร counter ตามเดิม

(การแปลงจากตัวเลขเป็นข้อความทำได้ด้วยการอาศัยเทคนคิการรวมกับข้อความว่าง ซึ่งจากตัวอย่างคือ + "" )

เมื่อทราบจำนวนจากตัวแปร counter แล้วส่วนต่อไปในบรรทัดที่ 23 คือการสร้างอินสแตนซ์จากคลาส Cookie ด้วยชื่อ

counter และมีข้อมูลจากตัวแปร counter กำหนดอยู่ จากนั้นจึงอ้างถึงด้วยตัวแปร cookie_counter

จากนั้นมีการกำหนดค่าอายุของคุกกี้เป็นหนึ่งปีในบรรทัดที่ 23 ท้ายที่สุดคือการรวมคุกกี้นี้ไว้ในส่วน response

เพื่อส่งกลับไปให้กับบราวเซอร ์

รูปด้านล่างเป็นผลลัพธ์จากการเรียกใช้งานเซิร์ฟเล็ต CookieCounter ในครั้งที่ 13 ตัวเลขจะเปลี่ยนไปตามจำนวนครั้ง

สามารถทดสอบได้ด้วยการกดปุ่ม Refresh หรือ Ctrl+R จากบราวเซอร์โดยตรง

รูปแสดงผลของการเรียกใช้งานเซิร์ฟเล็ต CookieCounter ในครั้งที่ 13

ตัวอย่างการกำหนดคุกกี้ในการจดจำข้อมูลในฟอร์ม

เซิร์ฟเล็ต CookieForm.java ในตัวอย่างซอร์สโค้ดต่อไปนี้ เป็นการสร้างตัวนับเช่นกัน

แต่จะนำเฉพาะการใช้งานเมื่อนับจากการสร้างอินสแตนซ์ของเซิร์ฟเล็ตนี้ขึ้นมาเท่านั้น

Page 7: Javacentrix com chap07-0

ไม่เหมือนกับตัวนับก่อนหน้านี้ที่จะนับทุกครั้งที่มีการเรียกใช้งานเซิร์ฟเล็ต

ไม่ว่าจะปิดการทำงานและเปิดเซิร์ฟเล็ตจากเว็บเซิร์ฟเวอร์กี่ครั้งก็ตาม 1 import java.io.*; 2 import java.util.*; 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import EJP.HTMLUtilities; 6 import EJP.ServletUtilities; 7 8 public class CookieForm extends HttpServlet { 9 public void doGet (HttpServletRequest request, HttpServletResponse response) 10 throws ServletException, IOException { 11 response.setContentType("text/html; charset=windows-874"); 12 PrintWriter out = response.getWriter(); 13 HTMLUtilities.createHTMLStart(out, "Read Cookie"); 14 Cookie cookies[] = request.getCookies(); 15

out.println("<H1><CENTER>�������������������������������</CENTER></H1>");

16 out.println("<FORM METHOD=\"POST\" ACTION=\"/ejp/servlet/CookiePage\">"); 17 out.println("<TABLE>"); 18 String login_value = ServletUtilities.getCookieValue(cookies, "login", null); 19 if (login_value==null) 20 out.println("<TR><TD>����������</TD><TD>" + 21 "<INPUT TYPE=\"TEXT\" NAME=\"login\"></TD></TR>"); 22 else 23 out.println("<TR><TD>����������</TD><TD>" + 24 "<INPUT TYPE=\"TEXT\" NAME=\"login\"" + 25 " value=\"" + login_value+ "\"></TD></TR>"); 26 out.println("<TR><TD>��������</TD><TD>" + 27 "<INPUT TYPE=\"PASSWORD\" NAME=\"password\"></TD></TR>"); 28 out.println("<TR><TD></TD><TD>" + 29 "<INPUT TYPE=\"submit\" NAME=\"Submit\" VALUE=\"Submit\"></TD></TR>"); 30 out.println("</TABLE>"); 31 out.println("</FORM>"); 32 HTMLUtilities.createHTMLEnd(out); 33 } 34 public void doPost (HttpServletRequest request, HttpServletResponse response) 35 throws ServletException, IOException { 36 doGet(request,response); 37 } 38 }

จากตัวอย่างซอร์สโค้ดเป็นการสร้างเซิร์ฟเล็ตชื่อ CookieForm ที่ทำหน้าที่อ่านค่าคุกกี้ชื่อ login

จากบราวเซอรม์าเก็บไว้ในตัวแปร login_value ในบรรทัดที่ 50 เพื่อตรวจสอบว่ามีการส่งข้อมูลคุกกี้นี้ไปเก็บที่เซิร์ฟเวอร์แล้วหรือยัง

หากยังไม่เจอก็จะแสดงช่องกรอกข้อมูลของฟอร์มโดยไม่มีค่าเริ่มต้นจากบรรทัดที่ 52-53

แต่หากมีก็จะแสงช่องกรอกข้อมูลของฟอร์มโดยมีค่าเริ่มต้นตามค่าของตัวแปร login_value ผลลัพธ์จากเซิร์ฟเล็ต CookieForm

นี้เป็นการสร้างฟอร์มกรอกข้อมูลที่บรรจุด้วยช่องกรอกข้อมูล 2 ช่อง ช่องแรกชื่อ login ช่องที่สองชื่อ password และปุ่ม Submit

หากผู้ใช้กรอกข้อมูลและกดปุ่ม Submit ข้อมูลดังกล่าวจะถูกส่งไปยังเซิร์ฟเล็ตที่ชื่อ CookiePage

ตัวอย่างซอร์สโค้ดต่อไปนี้เป็นการทดสอบการทำงานของคุกกี้ให้จดจำข้อมูลจากการใช้งานในครั้งก่อนหน้านี้

ซึ่งจะบันทึกข้อมูลไว้ที่เซิร์ฟเวอร์ในเวลาที่ยาวนานถึง 1 ปี ดังนั้นเมื่อมีการเปิดบราวเซอร์ขึ้นมาใช้งานในครั้งใด

ก็จะนำเอาข้อมูลดังกล่าวมาใช้งานอย่างอัตโนมัติ ซอร์สโค้ดบรรจุในไฟล์ CookieForm.java

Page 8: Javacentrix com chap07-0

1 import java.io.*; 2 import java.util.*; 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import EJP.HTMLUtilities; 6 import EJP.ServletUtilities; 7 8 public class CookiePage extends HttpServlet { 9 public void doGet (HttpServletRequest request, HttpServletResponse response) 10 throws ServletException, IOException { 11 response.setContentType("text/html; charset=windows-874"); 12 PrintWriter out = response.getWriter(); 13 HTMLUtilities.createHTMLStart(out, "Set Cookie"); 14 Cookie cookies[] = request.getCookies(); 15 String login_value = request.getParameter("login"); 16 if (login_value!=null) { 17 if (login_value.length()>0) { 18 Cookie cookie_login = new Cookie("login", login_value); 19 cookie_login.setMaxAge(60); // ������������������ 20 response.addCookie(cookie_login); 21 out.println("<H1><CENTER>��������������� '" + login_value + 22 "' �������������</CENTER></H1>"); 23 } else { 24

out.println("<H1><CENTER>��������������������������������������������" +

25 "</CENTER></H1>"); 26 out.println("<CENTER><A HREF=\"/ejp/servlet/CookieForm\">" + 27 "�������������������</A></CENTER>"); 28 } 29 } 30 HTMLUtilities.createHTMLEnd(out); 31 } 32 public void doPost (HttpServletRequest request, HttpServletResponse response) 33 throws ServletException, IOException { 34 doGet(request,response); 35 } 36 }

เซิร์ฟเล็ต CookiePage เป็นการรับข้อมูลจากช่องกรอกข้อมูลที่ได้จากฟอร์มของเซิร์ฟเล็ต CookieForm

เมื่อทำงานจะอ่านข้อมูลพารามิเตอร์ของฟอร์มมาเก็บไว้ในตัวแปร login_value ในบรรทัดที่ 15

และตรวจสอบว่าผู้ใช้ได้กรอกข้อมูลลงในฟอร์มหรือไม่ในด้วยเงื่อนไข if ในบรรทัดที่ 16

และหากมีข้อมูลและความยาวมากกว่าศูนย์ตัวอักษรแล้ว เริ่มสร้างคุกกี้ชื่อ login โดยมีข้อมูลเริ่มต้นจากตัวแปร login_value ในบรรทัดที ่

18 หลังจากนั้นเป็นการกำหนดอายุคุกกี้เป็นเวลา 60 วินาทีและส่งลงไปในอินสแตนซ์ response ในบรรทัดที่ 19 และ 20 ตามลำดับ

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

Page 9: Javacentrix com chap07-0

รูปแสดงผลลัพธ์ที่ได้จากการเรียกใช้เซิร์ฟเล็ต CookieForm ในครั้งแรก

จากรูปตัวอย่างการทดสอบให้ใส่ข้อมูลลงในช่องกรอกข้อมูลทั้งสองช่องคือช่องชื่อผู้ใช้ และช่องรหัสผ่าน

และให้จำข้อมูลที่กรอกไว้ในในช่องชื่อผู้ใช้เอาไว้ว่ากรอกข้อมูลอะไรลงไป ซึ่งในการทดสอบครั้งนีใ้ช้ชื่อผู้ใช้เป็น JavaCentrix

และรหัสผ่านเป็น javacentrix ดังสังเกตได้จากรูปด้านล่าง

รูปแสดงการป้อนข้อมูลลงในฟอร์มด้วยชื่อผู้ใช้ JavaCentrix และรหัสผ่านเป็น javacentrix

ซึ่งหลังจากคลิกปุ่ม Submit แล้วข้อมูลทั้งสองส่วนจะถูกส่งเป็นพารามิเตอร์ให้กับเซิร์ฟเล็ตที่ชื่อ CookiePage

ซึ่งจะสร้างคุกกี้ชื่อ login และนำเอาข้อมูลจากพารามิเตอร์ส่งไปเก็บไว้ที่บราวเซอร์ (จากตัวอย่างคือข้อมูล JavaCentrix)

และจากนั้นก็แสดงข้อความตอบรับดังรูปด้านล่าง

รูปแสดงผลลัพธ์จากเซิร์ฟเล็ต CookiePage ซึ่งได้รับข้อมูลจากฟอร์มของเซิร์ฟเล็ต CookieForm

ต่อจากนี้ทีเ่ครื่องคอมพิวเตอร์ผู้ใช้ได้ทำการเก็บข้อมูลลงในคุกกี้ชื่อ login ไว้เรียบร้อยแล้ว

ในขั้นตอนต่อไปของการทดสอบให้ทำในช่วงเวลาหนึ่งนาที เนื่องจากในเซิร์ฟเล็ตระบุอายุคุกกี้กำหนดไว้ที่ 60 วินาที

โดยให้ปิดบราวเซอร์เพื่อไม่ให้บราวเซอร์จดจำค่าเดิมไว้จากบราวเซอร์เอง และเปิดขึ้นมาใหม่จากนั้นลองอ้างไปยังเซิร์ฟเล็ต CookieForm

ตัวเดิม ผลลัพธ์ที่ได้รับกลับมาคือฟอร์มกรอกข้อมูลสองช่องเช่นเดิม

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

CookieForm หลังจากหนึ่งนาทีผ่านไปช่องกรอกข้อความจะเป็นช่องว่างๆเท่านั้น

Page 10: Javacentrix com chap07-0

รูปแสดงผลลัพธ์จากเรียกใช้เซิร์ฟเล็ต CookieForm ในครั้งที่สองห่างจากครั้งแรกไม่เกิน 60 วินาท ี

จากตัวอย่างเซิร์ฟเล็ตไม่มีการบันทึกค่ารหัสผ่านไว้ในคุกกี้

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

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

จึงมักไม่นิยมนำมาเก็บไว้ในคุกกี้เพื่อทำงาน

3. ความหมายของเซสชั่น Session

การทำงานของระบบเว็บในส่วนการติดต่อระหว่างบราวเซอร์ และเว็บเซิร์ฟเวอร์ เป็นการทำงานแบบ Stateless

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

การติดต่อแต่ละครั้งเป็นของบราวเซอร์จากผู้ใช้คนเดียวกันหรือไม่

ยกตัวอย่างเช่นหากเนื้อข้อมูลที่นำเสนอหน้าเอกสารที่ประกอบจากรูป 2 รูป ข้อความหนึ่งย่อหน้า ดังนี ้

รูปแสดงการติดต่อระหว่างบราวเซอร์และเว็บเซิร์ฟเวอร์ของเอกสารหนึ่งหน้า

จากรูปแสดงให้เห็นว่าในเอกสารดังกล่าว การติดต่อที่เกิดขึ้นจากบราวเซอร์ซึ่งสร้างช่องทางการสื่อสารผ่านโพรโตคอล HTTP

ทำไว้ถึงสามช่องทาง ช่องทางแรกคือการเอกสาร HTML ปกติ ในขณะที่อีกสองช่องทางที่เหลือเป็นการอ้างไปยังรูปภาพในตำแหน่งอีก 2

ตำแหน่ง และเว็บเซิร์ฟเวอร์ก็จะส่งเนื้อข้อมูลรูปภาพไปให้กับบราวเซอร์

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

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

และในสภาพความเป็นจริงการร้องขอข้อมูลจากบราวเซอร์นั้น ไม่ใช่ว่าจะมีเพียง 3 ช่องทางการสื่อสาร แต่อาจจะมากกว่านั้น

ขึ้นอยู่ว่าหน้าเอกสารมีโครงสร้างอย่างไร และยังรวมถึงจำนวนผู้ใช้บราวเซอร์ด้วยว่าอ้างมายังเซิร์ฟเวอร์ดังกล่าวอยู่กี่จำนวน อาจจะ 2

คน หรือ 10 คน หรือมากกว่านั้น

ข้อยุ่งยากดังกล่าวหากผู้ใช้หนึ่งคนพยายามจะเรียกดูเอกสารหลายเอกสาร

และต้องการข้อมูลที่เชื่อมโยงกันจะทำไม่ได้ในสภาวะปกติ เช่นหากเป็นการสร้างแอปพลิเคชั่นจำพวกพาณิชย์อิเล็กทรอนิกส์

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

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

อิเล็กทรอนิกส์มีตัวอย่างให้เห็นในระบบงานตัวอย่างช่วงท้ายของหนังสือ จากความต้องการลักษณะนี้

เว็บเซิร์ฟเวอร์จึงจำเป็นต้องอาศัยรูปแบบอื่นๆมาใช้งาน ซึ่งสามารถทำได้ดังนี ้

การจดจำสถานะผู้ใช้ด้วยรูปแบบต่างๆ

แบบที่ 1 การใช้งานพารามิเตอร ์(URL-Rewriting)

ในการส่งข้อมูลจากหน้าเอกสารหนึ่ง

ไปยังหน้าเอกสารหนึ่งสามารถกำหนดได้ด้วยเทคนคิการอาศัยพารามิเตอร์ที่ส่งไปในส่วนท้ายของ URL

Page 11: Javacentrix com chap07-0

เพื่อบอกถึงสถานะภาพการใช้งานของหน้าเอกสารก่อนหน้านี้ เช่น หากผู้ใช้เลือกที่เว็บหน้าที่มีรายชื่อสินค้าอยู่ 3 รายการ

หากผู้ใช้เลือกสินค้าในการสั่งซื้อ ให้สร้างลิงก์สำหรับสินค้าด้วยข้อมูลที่ต่างกัน ดังนี้

สินค้ารายการที่ 1 มีลิงก์ไปยัง URL http://www.javacentrix.com/order.html?product=1

สินค้ารายการที่ 2 มีลิงก์ไปยัง URL http://www.javacentrix.com/order.html?product=2

สินค้ารายการที่ 3 มีลิงก์ไปยัง URL http://www.javacentrix.com/order.html?product=3

ทำให้เว็บหน้า order.html สามารถรับรู้ไดจ้ากค่าพารามิเตอร์ชื่อ product ดังกล่าว แต่วิธีนี้มีข้อเสียคือการเรียกไปยัง

order.html สามารถเกิดขึ้นได้พร้อมกันในช่วงเวลาเดียวกันจากผู้ใช้หลายคน ทำให้ไม่สามารถทราบได้ว่าเป็นของผู้ใช้รายใด

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

ของบราวเซอร์โดยตรง ซึ่งทำให้ข้อมูลไม่ได้ถูกปกปิดหากเป็นข้อมูลสำคัญ

ปัญหาที่สามคือตัวอักษรที่ถูกใช้เป็นข้อมูลต่อท้ายมีความยาวได้ไม่มากนัก

แบบที่ 2 การใช้งานฟิลด์แบบซ่อนข้อมูลของฟอร์ม (Hidden Form Field)

การใช้งาน URL ในแบบแรกสามารถปกปิดข้อมูลด้วยการสร้างฟอร์มเพื่อส่งค่าพารามิเตอร์ โดยอาศัยข้อมูลที่อยู่ในแบบ

HIDDEN ซึ่งเป็นคุณสมบัติของฟอร์มในภาษา HTML ซึ่งจะทำให้ข้อมูลสินค้า

หรือข้อมูลใดๆที่อาศัยคุณสมบัตินี้ไม่สามารถมองเห็นได้จากช่อง URL ของบราวเซอร์

และเว็บที่รับข้อมูลก็ยังสามารถรับข้อมูลได้เช่นเดียวกันกับแบบที่ 1

แต่ก็ยังไม่สามารถแก้ปัญหาการเรียกใช้งานพร้อมกันจากผู้ใช้หลายคนได้

แบบที่ 3 การใช้งานคุกกี้ (Cookie)

หากมีการเรียกใช้งานคุกกี้แล้ว สามารถแก้ไขปัญหาได้เหมือนกับแบบที่ 2 คือการใช้ฟอร์ม

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

แต่เนื่องจากที่กล่าวให้ทราบแล้วว่าคุกกี้จะเป็นข้อมูลที่บันทึกไว้ที่บราวเซอร์โดยตรง ทำให้ไม่มีความปลอดภัยมากนัก

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

ทำให้การใช้คุกกี้ไม่สามารถทำงานได้หากผู้ใช้ไม่ยอมรับการจัดเก็บคุกกี้

ทั้ง 3 แบบเป็นรูปแบบการส่งข้อมูลจากหน้าเอกสารหนึ่งไปยังอีกหน้าเอกสารหนึ่งที่เซิร์ฟเวอร์เดียวกันได้

แต่ก็ไม่สามารถแก้ไขปัญหาได้จนครอบคลุมการใช้งานของบราวเซอร์ได้ครบทั้งหมด

สำหรับเซิร์ฟเล็ตแล้วมีรูปแบบการทำงานด้วยการสร้างเซสชั่น (Session) การทำงานขึ้น

ดังมีรายละเอียดที่สามารถศึกษาได้จากหัวข้อต่อไป

4. การใช้งานเซสชั่น

เซสชั่นเป็นการทำงานสามารถทำให้ผู้ใช้งานบราวเซอร์สามารถใช้งานได้อย่างต่อเนื่อง

โดยการควบคุมความต่อเนื่องนี้เกิดจากเซิร์ฟเล็ตเก็บรายละเอียดการทำงานเอาไว้

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

สำหรับเซิร์ฟเล็ตสามารถจัดการทำงานรูปแบบเซสชั่นได้ไม่ยาก โดยอาศัยการใช้งานของคลาส HttpSession

ที่ได้รับจากส่วนร้องขอของบราวเซอร์ การจัดเก็บข้อมูลของเซสชั่นจะอยู่ในรูปแบบของออปเจ็ค

ดังนั้นเมื่อต้องการเก็บข้อมูลในเซสชั่นจึงควรสร้างอินสแตนซ์ขึ้นมาก่อนที่จะจัดส่งให้กับเซสชั่น

รายละเอียดที่เกี่ยวข้องกับการใช้งานเซสชั่นของคลาส HttpSession

public String[] getAttributeNames()

สำหรับอ่านอะเรย์รายชื่อออปเจ็คต่างๆที่จัดเก็บไว้ในเซสชั่น เมธอดนี้ใช้ในเซิร์ฟเล็ตเวอร์ชัน 2.2

Page 12: Javacentrix com chap07-0

public void setAttrubute(String name, Object value)

สำหรับการจัดเก็บออปเจ็ค value ลงในเซสชั่นโดยการระบุชื่อออปเจ็คในเซสชั่นจาก name

เมธอดนี้ใช้ในเซิร์ฟเล็ตเวอรชัน 2.2

public Object getAttribute(String name)

สำหรับอ่านข้อมูลออปเจ็คที่อยู่ในเซสชั่นตามชื่อ name เมธอดนี้ใช้ในเซิร์ฟเล็ตเวอร์ชัน 2.2

public void removeAttribute(String name)

สำหรับลบออปเจ็คทีบ่รรจุในเซสชั่นตามชื่อ name เมธอดนี้ใช้ในเซิร์ฟเล็ตเวอร์ชัน 2.1

public String[] getValueNames()*

สำหรับอ่านอะเรย์รายชื่อออปเจ็คต่างๆที่จัดเก็บไว้ในเซสชั่น เมธอดนี้ใช้ในเซิร์ฟเล็ตเวอร์ชัน 2.1

public void putValue(String name, Object value)*

สำหรับการจดัเก็บออปเจ็ค value ลงในเซสชั่นโดยการระบุชื่อออปเจ็คในเซสชั่นจาก name

เมธอดนี้ใช้ในเซิร์ฟเล็ตเวอรชัน 2.1

public Object getValue(String name)*

สำหรับอ่านข้อมูลออปเจ็คที่อยู่ในเซสชั่นตามชื่อ name เมธอดนี้ใช้ในเซิร์ฟเล็ตเวอร์ชัน 2.1

public void removeValue(String name)*

สำหรับลบออปเจ็คที่บรรจุในเซสชั่นตามชื่อ name เมธอดนี้ใช้ในเซิร์ฟเล็ตเวอร์ชัน 2.1

public String getId()

สำหรับอ่านค่ารหัสเซสชั่น ซึ่งรหัสนี้ถูกใช้ในการเชื่อมโยงเว็บแต่ละหน้าเข้าหากันสำหรับผู้ใช้รายเดียวกัน

public boolean isNew()

สำหรับอ่านข้อมูลในเว็บแต่ละหน้าว่า เป็นครั้งแรกของการใช้งานเซสชั่นหากได้รับเป็นค่า true

นอกนั้นเป็นการใช้งานต่อเนื่องในเซสชั่นเดียวกันหากได้รับเป็นค่า false

public long getCreationTime()

สำหรับอ่านค่าเวลาทีเ่ซสชั่นเริ่มมีการทำงาน โดยค่าที่ได้ถูกนำไปใช้ในคลาส Date เพื่อทำงานในคราวต่อไป

public long getLastAccessedTime()

สำหรับอ่านค่าเวลาที่มีการเข้าใชเ้ซสชั่นครั้งล่าสุด โดยค่าที่ได้ถูกนำไปใช้ในคลาส Date

public int getMaxInactiveInterval()

สำหรับอ่านค่าเวลาเป็นวินาที หากมีการหยุดใช้งานจากผู้ใช้ โดยไม่มีการดำเนินการใดๆในเซสชั่นต่อไป

ซึ่งจะทำใหเ้ซสชั่นถูกปิดลง

public void setMaxInactiveInterval(int seconds)

สำหรับกำหนดค่าเวลาในการทำงานแต่ละเซสชั่น ซึ่งจะถูกปิดลงหากไม่มีการปฏิบัติการใดๆภายในเซสชั่น

public void invalidate()

สำหรับยกเลิกเซสชั่น และถอดออปเจ็คต่างๆออกจากเซสชั่นทั้งหมด

หมายเหต ุเมธอดที่มีสัญลักษณ์ * อยู่ตามหลังคือชื่อที่ใช้สำหรับเซิร์ฟเล็ตเวอร์ชัน 2.1 แต่สามารถใช้งานได้ในเวอร์ชัน 2.2 ได้

ซึ่งจะอยู่ในรูปแบบ deprecated คือไม่ได้เป็นไปตามข้อกำหนด แต่รองรับการใช้งานได้

Page 13: Javacentrix com chap07-0

การอ่านค่าเซสชั่นจากบราวเซอร์

การอ่านค่าเซสชั่นถูกอ่านได้จากข้อมูลร้องขอของบราวเซอร์ โดยการเรียกใช้เมธอด getSession จากคลาส

HttpServletRequest โดยมีรูปแบบการใช้งานดังนี ้

HttpSession session = request.getSession(true);

ซึ่งในคำสั่งด้านบนเป็นการอ่านค่าอินสแตนซ์เซสชั่นมาเก็บไว้ในตัวแปร session ค่า true ที่ระบุไว้ในเมธอด getSession

นั้นเป็นการระบุว่าหากยังไม่มีการใช้งานเซสชั่น เซิร์ฟเล็ตจะเริ่มต้นสร้างเซสชั่นให้และใช้เวลาดังกล่าว

เป็นเวลาเริ่มต้นการทำงานของเซสชั่นด้วย และค่าที่ได้ของ session จะเป็นค่า null

แต่หากเซสชั่นถูกสร้างไว้แล้วค่าที่ได้รับจะเป็นอินสแตนซ์ที่สามารถอ่านข้อมูลออปเจ็คได้ในคราวต่อไป

การส่งข้อมูลออปเจ็คลงในเซสชั่น

เนื่องจากเซสชั่นมีรูปแบบการเก็บข้อมูลเป็นออปเจ็ค ซึ่งต่างจากคุกกี้ที่เป็นการเก็บข้อมูลข้อความเท่านั้น

ดังนั้นหากต้องการส่งข้อมูลไปในเซสชั่นจึงควรสร้างอินสแตนซ์จากคลาสใดๆก่อน

จากนั้นให้ส่งอินสแตนซ์บรรจุลงในเซสชั่นด้วยเมธอด setAttribute (หรือ putValue) พร้อมทั้งระบุชื่อให้กับออปเจ็คดังกล่าว

Integer i = new Integer(999);

session.setAttrubute("myNumber", i);

จากตัวอย่างด้านบนเป็นการสร้างอินสแตนซ์จากคลาส Integer ที่มีข้อมูล 999 ขึ้นอ้างถึงได้จากตัวแปร i ในสเตจเม็นต์บน

และในสเตจเม็นต์ถัดมาเป็นการบรรจุอินสแตนซ์ดังกล่าวลงในเซสชั่นที่มีการระบุชื่อของออปเจ็คว่า myNumber

การอ่านข้อมูลออปเจ็คจากเซสชั่น

สำหรับการอ่านข้อมูลจากเซสชั่นนั้น สามารถทำได้จากการเรียกใช้เมธอด getAttrubute (หรือ getValue)

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

จากนั้นใช้วิธี casting ไปเป็นรูปแบบอินสแตนซ์ตามที่ต้องการ

Integer x = (Integer) session.getAttribute("myNumber");

จากตัวอย่างด้านบนเมธอด getAttribute อ่านค่าออปเจ็คในเซสชั่นที่ชื่อ myNumber จากนั้นมีการ casting

ออปเจ็คให้เป็นรูปแบบอินสแตนซ์ของ Integer โดยอ้างด้วยตัวแปร x

ตัวอย่างของการตรวจข้อมูลในเซสชั่นและกำหนดตัวนับด้วยเซสชั่น

ตัวอย่างซอร์สโค้ดในไฟล์ SessionShow.java เป็นการสร้างเซิร์ฟเล็ต SessionShow

เพื่ออ่านค่าข้อมูลต่างๆที่เกี่ยวกับการใช้งานเซสชั่น 1 import java.io.*; 2 import java.text.*; 3 import java.util.*; 4 import javax.servlet.*; 5 import javax.servlet.http.*; 6 import EJP.HTMLUtilities; 7 8 public class SessionShow extends HttpServlet {

Page 14: Javacentrix com chap07-0

9 public void doGet (HttpServletRequest request, HttpServletResponse response) 10 throws ServletException, IOException { 11 response.setContentType("text/html; charset=windows-874"); 12 PrintWriter out = response.getWriter(); 13 HTMLUtilities.createHTMLStart(out, "Show Information of Session"); 14 HttpSession session = request.getSession(true); // ����������������� 15 String session_counter = (String)session.getAttr ibute("counter"); // ��������������� counter 16 if (session_counter !=null) { // ���������������� null ���������������������������� 17 session_counter = (Integer.parseInt(session_counter) + 1) + ""; 18 } else { 19 session_counter = "1"; // ����������������������� "1" 20 } 21 session.setAttr ibute("counter", session_counter ); // � � � � � � � � � � � � � � � �� � � � � � �� � � � counter 22 out.println("<H1><CENTER>���������������������</CENTER></H1>"); 23 out.println("<TABLE>"); 24 out.println("<TR><TD>��������������������������</TD><TD>" + session_counter + "</TD></TR>"); 25 out.println("<TR><TD>�����������</TD><TD>" + session.getId() + "</TD></TR>"); 26 out.println("<TR><TD>����������������</TD><TD>" + 27 DateFormat.getDateTimeInstance().format( 28 new Date(session.getCreationTime())) + "</TD></TR>"); 29 out.println("<TR><TD>����������������������������</TD><TD>" + 30 DateFormat.getDateTimeInstance().format( 31 new Date(session.getLastAccessedTime())) + "</TD></TR>"); 32 out.println("<TR><TD>���������������������������������������(������)</TD><TD>" + 33 session.getMaxInactiveInterval() + "</TD></TR>"); 34 out.println("</TABLE>"); 35 HTMLUtilities.createHTMLEnd(out); 36 } 37 public void doPost (HttpServletRequest request, HttpServletResponse response) 38 throws ServletException, IOException { 39 doGet(request,response); 40 } 41 }

จากตัวอย่างซอรส์โค้ดเป็นการสร้างเซิร์ฟเล็ตชื่อ SessionShow ซึ่งในบรรทัดที่ 28, 31 เป็นการอ่านค่าเวลาการสร้างเซสชั่น

และเวลาการเข้าใช้งานเซสชั่นครั้งล่าสุดตามลำดับ ข้อมูลทั้งสอบส่วนถูกนำมาใช้งานในคลาส Date

และปรับรูปแบบการแสดงผลลัพธ์ด้วยคลาส DateFormat บรรทัดที ่25 และ 33 เป็นการอ่านข้อมูลรหัสเซสชั่น

และเวลาในการสิ้นสุดเซสชั่นมาแสดงผลตามลำดับ

สำหรับการทำหน้าที่ตัวนับนั้นมีรูปแบบการทำงานคล้ายกับการทำงานที่ใช้ในคุกกี้จากเซิร์ฟเล็ต CookieCounter

โดยเกิดขึ้นระหว่างบรรทัดที่ 15 – 21 ซึ่งเป็นการตรวจสอบเซสชั่นว่ามีออปเจ็คที่ชื่อ counter หรือไม่หากค่าที่ได้เป็นค่า null

ก็เริ่มสร้างอินสแตนซ์จากคลาส String โดยกำหนดให้มีข้อมูล "1" เป็นค่าให้กับอินสแตนซ์ก่อนนำไปเก็บไว้ในเซสชั่น

หากในเซสชั่นมีออปเจ็ค counter อยู่แล้วก็นำข้อมูลเดิมมาเพิ่มค่าอีกหนึ่งค่าเป็นตัวนับ ก่อนบรรจุไว้ในเซสชั่นในชื่อเดียวกัน

ผลลัพธ์ของการทำงานในคลาส SessionShow แสดงในรูปต่อไป

Page 15: Javacentrix com chap07-0

รูปแสดงการทำงานของเซิร์ฟเล็ต SessionShow

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

เริ่มจากไฟล์ SessionProductListing.java ที่ใช้แสดงรายการสินค้าดังต่อไปนี ้1 import java.io.*; 2 import java.text.*; 3 import java.util.*; 4 import javax.servlet.*; 5 import javax.servlet.http.*; 6 import EJP.HTMLUtilities; 7 // ���� Product �������������������������������� 8 class Product { 9 public String ID; // ���������� 10 public String image; // ���������������� 11 public String title; // ���������� 12 public float price; // ���������������� 13 Product(String p_id, String p_image, String p_title, float p_price) { 14 ID = p_id; image = p_image; 15 title = p_title; price = p_price; 16 } 17 } 18 19 class ProductList { // ��������������� products ������������������������� 20 public Product products[] = { 21 new Product("01", "product01.jpg", "�����", 1300.00F), 22 new Product("02", "product02.jpg", "������������", 520.00F), 23 new Product("03", "product03.jpg", "����������������������", 480.00F), 24 new Product("04", "product04.jpg", "����������", 475.00F), 25 new Product("05", "product05.jpg", "��������������", 295.00F) }; 26 } 27 28 public class SessionProductList ing extends HttpServlet { 29 public void doGet (HttpServletRequest request, HttpServletResponse response) 30 throws ServletException, IOException { 31 Str ing add_cart_uri = "/ejp/servlet/SessionProductOrder"; // ������������������������������������� 32 response.setContentType("text/html; charset=windows-874"); 33 PrintWriter out = response.getWriter(); 34 HTMLUtilities.createHTMLStart(out, "Product Listing"); 35 ProductList our_products = new ProductList(); 36 out.println("<H1>������������</H1>"); 37 out.println("<TABLE>"); 38 for(int i=0; i < our_products.products.length; i++) { 39 out.println("<FORM METHOD=\"POST\" ACTION=\"" + add_cart_uri + "\">"); 40 out.println("<TR><TD VALIGN=\"TOP\">"); 41 out.println("<IMG SRC=\"/ejp/images/" + our_products.products[i].image + "\">");

Page 16: Javacentrix com chap07-0

42 out.println("</TD><TD VALIGN=\"TOP\">"); 43 out.println(" <B>����������: </B>" + our_products.products[i].ID); 44 out.println(" <B>����������: </B>" + our_products.products[i].title + "<BR>"); 45 out.println(" <B>����: </B>" + our_products.products[i].price + " ���"); 46 out.println("<BR><BR>"); 47 out.println("<INPUT TYPE=\"HIDDEN\" NAME=\"product_id\" VALUE=\"" + 48 our_products.products[i].ID +"\">"); 49 out.println("<INPUT TYPE=\"SUBMIT\" NAME=\"Submit\" VALUE=\"�����������\">"); 50 out.println("<TD></TR>"); 51 out.println("</FORM>"); 52 } 53 out.println("</TABLE>"); 54 HTMLUtilities.createHTMLEnd(out); 55 } 56 public void doPost (HttpServletRequest request, HttpServletResponse response) 57 throws ServletException, IOException { 58 doGet(request,response); 59 } 60 }

จากเซิร์ฟเล็ต SessionProductListing ทำหน้าที่แสดงรายชื่อสินค้าที่เก็บอยู่ในอะเรย์ชื่อ products ที่อยู่ในคลาส ProductList

โดยอ่านข้อมูลมาแสดงในเทเบิล และสินค้าแต่ละรายการบรรจุอยู่ในฟอร์ม หากมีการเลือกสินค้าจะส่งข้อมูลไปยังเซิร์ฟเล็ตชื่อ

SessionProductOrder ที่กำหนดไว้ตั้งแต่บรรทัดที่ 31 หากสังเกตที่การสร้างฟอร์มในภาษา HTML

เป็นการวนลูปในจำนวนเท่ากับอิลิเม็นต์ในอะเรย์ ในแต่ละครั้งของการวนลูปเป็นการสร้างฟอร์ม (บรรทัดที่ 39 – 51)

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

SessionProductOrder สามารถรับรู้สินค้าที่ผู้ใช้เลือกจากฟิลด์ product_id นั่นเอง

หมายเหตุ ในเซิร์ฟเล็ต SessionProductListing นี้ยังไม่มีการปฏิบัติกิจกรรมใดๆเกี่ยวกับเซสชั่น

ซอร์สโค้ดต่อไปเป็นเซิร์ฟเล็ตในการทำงานเพื่อสรุปรายการสินค้าที่เลือกจากเซิร์ฟเล็ตก่อนหน้านี้

และสามารถปรับปรุงจำนวนสินค้าจากการเลือกซื้อได้ด้วย ซอร์สโค้ดนี้บรรจุในไฟล์ SessionProductOrder.java 1 import java.io.*; 2 import java.text.*; 3 import java.util.*; 4 import javax.servlet.*; 5 import javax.servlet.http.*; 6 import EJP.HTMLUtilities; 7 8 class ProductItem { 9 public String ID; 10 public byte qty; 11 ProductItem(String p_id, byte p_qty) { 12 ID = p_id; qty = p_qty; 13 } 14 } 15 16 class Cart { 17 protected Vector this_cart; 18 Cart() { 19 this_cart = new Vector(); 20 } 21 public void addProductItem(String p_id, byte p_qty) { 22 if (p_qty<=0) { 23 removeProductItem(p_id); 24 } 25 else { 26 if (!updateProductItem(p_id, p_qty))

Page 17: Javacentrix com chap07-0

27 this_cart.addElement(new ProductItem(p_id, p_qty)); 28 } 29 } 30 public void removeProductItem(String p_id) { 31 ProductItem item; 32 for (int i=0;i<this_cart.size();i++) { 33 item = (ProductItem)this_cart.elementAt(i); 34 if (item.ID.equals(p_id)) { 35 this_cart.removeElementAt(i); 36 } 37 } 38 } 39 public boolean updateProductItem(String p_id, byte p_qty) { 40 // ��������������������������������������� �������������������������������������� 41 ProductItem item; 42 for (int i=0;i<this_cart.size();i++) { 43 item = (ProductItem)this_cart.elementAt(i); 44 if (item.ID.equals(p_id)) { 45 item.qty = p_qty; 46 return true; 47 } 48 } 49 return false; 50 } 51 public Product getProduct(String p_id) { 52 Product our_products[] = (new ProductList()).products; 53 for(int i=0; i<our_products.length;i++) 54 if (our_products[i].ID.equals(p_id)) 55 return our_products[i]; 56 return null; 57 } 58 public Vector getCart() { 59 return this_cart; 60 } 61 } 62 63 public class SessionProductOrder extends HttpServlet { 64 public void doGet (HttpServletRequest request, HttpServletResponse response) 65 throws ServletException, IOException { 66 String add_cart_uri = "/ejp/servlet/SessionProductOrder "; 67 response.setContentType("text/html; charset=windows-874"); 68 PrintWriter out = response.getWriter(); 69 HTMLUtilities.createHTMLStart(out, "Shopping Cart Product Listing"); 70 HttpSession session = request.getSession(true); 71 Cart shopping_cart = (Cart)session.getAttr ibute("ShoppingCart"); 72 // �������������������������������������������������� 73 if (shopping_cart == null) { 74 shopping_cart = new Cart(); 75 session.setAttr ibute("ShoppingCart", shopping_cart ) ; 76 } 77 // ��������������������� 78 String p_id = request.getParameter("product_id"); 79 byte p_qty; 80 try { 81 p_qty = Byte.parseByte(request.getParameter("product_qty")); 82 } catch (NumberFormatException e) { 83 p_qty = 1; 84 } 85 if (!p_id.equals("")) { 86 shopping_cart .addProductItem(p_id, p_qty);

Page 18: Javacentrix com chap07-0

87 } 88 89 Vector cart = shopping_cart.getCart(); 90 // ��������������������������������������� 91 out.println("<H1>���������������������������</H1>"); 92 out.println("<TABLE BORDER=\"1\">"); 93 out.println("<TR><TD><B>����������</B></TD><TD><B>����������</TD>" + 94 "<TD><B>������������</B></TD><TD><B>�����</B></TD>" + 95 "<TD><B>���(���)</B></TD><TD><B>������������</B></TD></TR>"); 96 97 Product product; String id; byte qty; 98 float total = 0; 99 for(int i=0; i<cart.size(); i++) { 100 id = ((ProductItem)cart.elementAt(i)).ID; 101 qty = ((ProductItem)cart.elementAt(i)).qty; 102 product = shopping_cart.getProduct(id); 103 out.println("<FORM METHOD=\"POST\" ACTION\"" + add_cart_uri + "\">"); 104 out.println("<TR><TD>"); 105 out.println(id); 106 out.println("<INPUT TYPE=\"HIDDEN\" NAME=\"product_id\" VALUE=\"" + id + "\">"); 107 out.println("</TD><TD>"); 108 out.println(product.title); 109 out.println("</TD><TD ALIGN=\"RIGHT\">"); 110 out.println(product.price); 111 out.println("</TD><TD ALIGN=\"RIGHT\">"); 112 out.println("<INPUT TYPE=\"TEXT\" NAME=\"product_qty\" SIZE=\"3\" VALUE=\"" + 113 qty + "\">"); 114 out.println("</TD><TD ALIGN=\"RIGHT\">"); 115 out.println(qty * product.price); 116 out.println("</TD><TD>"); 117 out.println("<INPUT TYPE=\"SUBMIT\" NAME=\"Submit\" VALUE=\"��������\">"); 118 out.println("<TD></TR>"); 119 out.println("</FORM>"); 120 total += qty * product.price; 121 } 122 out.println("<TR><TD></TD><TD></TD><TD></TD><TD>�����������</TD>" + 123 "<TD ALIGN=\"RIGHT\">" + total + "</TD><TD>���</TD></TR>"); 124 out.println("</TABLE>"); 125 out.println("<BR><BR><A HREF=\"/ejp/servlet/SessionProductListing\">" + 126 "����������������������</A>"); 127 HTMLUtilities.createHTMLEnd(out); 128 } 129 public void doPost (HttpServletRequest request, HttpServletResponse response) 130 throws ServletException, IOException { 131 doGet(request,response); 132 } 133 }

จากซอร์สโค้ดด้านบนทำให้เกิดคลาส 3 คลาสคือ ProductItem, Cart และ SessionProductOrder ซึ่งคลาส ProductItem

ถูกใช้สำหรับเก็บรหัสสินค้า และจำนวนสินค้าในการสั่งซื้อ ส่วนคลาส Cart ใช้เก็บข้อมูล ProductItem ของสินค้าในแต่ละรายการลงใน

Vecter ซึ่งทำให้สามารถลบรายการสินค้าหรือเปลี่ยนแปลงรายการสินค้าของ ProductItem ได้

จากคลาส Cart เมธอด addProductItem ใช้สำหรับเพิ่มรายการสินค้า เมธอด removeProductItem

ใช้สำหรับลบรายการสินค้า เมธอด updateProductItem ใช้สำหรับปรับปรุงรายละเอียดของรายการสินค้า เมธอด getProduct

ใช้สำหรับอ่านรายการสินค้าตามรหัสสินค้าที่ต้องการ ส่วนเมธอด getCart คืออ่านรายการสินค้าที่เก็บไว้ใน Vector

คลาส SessionProductOrder เป็นเซิร์ฟเล็ตที่แสดงสรุปรายการสั่งซื้อสินค้า โดยแสดงรายชื่อ

และจำนวนสินค้าที่สั่งซื้อรวมถึงสรุปค่าใช้จ่ายทั้งหมดของการสั่งซื้อสินค้านี้

Page 19: Javacentrix com chap07-0

รูปแสดงรายชื่อสินค้าจากการทำงานของเซิร์ฟเล็ต SessionProductListing

รูปแสดงตัวอย่างรายชื่อสินค้าจำนวน 5 ชิ้นที่มีฟอร์มที่มีฟิลด์รหัสซ่อนไว้ในแต่ละสินค้าหากมีการคลิกที่ปุ่ม "เลือกสินค้า"

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

Page 20: Javacentrix com chap07-0

รูปแสดงการทำงานของเซิร์ฟเล็ต SessionProductOrder หลังจากผู้ใช้คลิกเลือกสินค้าพัดลม

รูปด้านบนแสดงรายงานสรุปรายชื่อสินค้าที่เลือกจากผู้ใช้ในเซิร์ฟเล็ต SessionProductListing โดยในเซิร์ฟเล็ตที่ทำงานนี้คือ

SessionProductOrdet ซึ่งมีการจัดการเซสชั่น โดยการบรรจุข้อมูลออปเจ็คที่สร้างจากคลาส Cart

ซึ่งจัดเก็บรายการสินค้าในแต่ละรายการด้วยคลาส ProductItem อีกคราวหนึ่ง

รูปหลังจากผู้ใช้คลิกเลือกสินค้านาฬิกาปลุกเพิ่มจาก SessionProductListing และเปลี่ยนค่าจำนวนพร้อมคลิกปุ่ม “ปรับปรุง”

จากรายการสินค้าพัดลมที่เลือกไว้ในครั้งแรกหากมีการย้อนกลับไปที่รายชื่อสินค้าแล้วเลือกรายการนาฬิกาปลุกอีกหนึ่งชิ้น

ในครั้งแรกรายการจำนวนสำหรับนาฬิกาปลูกคือ 1 ชิ้น ต่อมามีการเปลี่ยนตัวเลขจากเลข 1 ไปเป็นเลข 3 แล้วคลิกปุ่ม ปรับปรุง

ข้อมูลดังกล่าวจะถูกปรับปรุงพร้อมราคารวมก็ถูกเปลี่ยนแปลงตามไปด้วย

ข้อแนะนำ เซิร์ฟเล็ตสองเซิร์ฟเล็ตดังกล่าวที่สนับสนุนการค้าในรูปแบบ E-Commerce

นั้นหากได้รับการปรับปรุงในเรื่องการจัดเก็บข้อมูลลงในระบบฐานข้อมูล

และการซิงโครไนซ์ข้อมูลให้สัมพันธ์กันหากมีการใช้งานเกิดขึ้นพร้อมกันแล้ว จะสามารถนำไปใช้งานได้ในการทำงานจริง

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