TRƯỜNG CAO ĐẲNG CÔNG NGHỆ THÔNG TIN TP.HCM

LẬP TRÌNH ỨNG DỤNG MẠNG BÀI 7 XXỬỬ LÝ BI

N SESSION LÝ BIẾẾN SESSION

GIẢNG VIÊN: VÕ TẤN DŨNG

1

g n ũ D n ấ T õ V

:

V G

2

g n ũ D n ấ T õ V

:

V G

PHẦN 1 KHÁI NIỆM SESSION

(cid:121) Giao thức HTTP là giao thức phi trạng thái (stateless protocol). Khi một lời yêu cầu (request) được tạo ra từ client thì một kết nối (connection) được mở ra, đáp ứng (response) gửi từ server xuống client. Sau đó, kết nối được đóng lại ngay.

(cid:121) Nếu một transaction (giao tác) thực hiện một chuỗi liên tiếp các request/response liên tiếp thì hậu quả là Web Server không nhớ được các bước request/response trước đó.

(cid:121) Ví dụ, khi ta mua sắm online, ta chọn các mặt hàng xong thì chuyển sang trang tính tiền. Lúc này Web Server không nhớ trước đó ta đã chọn mặt hàng nào.

3

g n ũ D n ấ T õ V

:

V G

HTTP llàà giaogiao ththứứcc phi phi trtrạạngng ththááii HTTP

(cid:121) Ta đã nhận rõ một điều rằng trong dịch vụ Web không có kết nối duy trì thường xuyên giữa trình khách (web browser) và trình chủ (web server).

(cid:121) Khi trình duyệt cần trình chủ cung cấp một trang tài

liệu, trình duyệt mở kết nối, lấy về trang dữ liệu và sau đó đóng kết nối ngay lập tức. Vì vậy Web Server sẽ không biết được trước đó trình duyệt đã có những trạng thái nào.

(cid:121) Session tượng trưng một giai đoạn duy trì kết nối giữa trình khách và trình chủ trong quá trình liên lạc. Một loạt các request từ một client sẽ được liên kết với một session.

4

g n ũ D n ấ T õ V

:

V G

session KhKhááii niniệệmm session

(cid:121) Như vậy, làm thế nào để server nhớ được các giao tác xảy ra trước đó của một client bất kỳ? Ta có thể theo dõi các phiên làm việc (session tracking) của một web client bằng các cách sau: (cid:121) Lưu dữ liệu trong các biến ẩn của form (hidden fields). (cid:121) Lưu dữ liệu trong đối tượng session. (cid:121) Lưu dữ liệu trong bảng băm (hash table) (cid:121) Lưu dữ liệu toàn cục của ứng dụng web trong đối tượng

application.

5

g n ũ D n ấ T õ V

:

V G

session KhKhááii niniệệmm session

6

g n ũ D n ấ T õ V

:

V G

PHẦN 2 HIDDEN FORM FIELDS

(cid:121) Ý tưởng ở đây là mỗi khi người dùng thực hiện thao tác submit một form, form sẽ chứa một số biến ẩn chứa thông tin trạng thái hoặc liên quan đến người dùng đang tương tác với ứng dụng.

(cid:121) Trở ngại lớn nhất của phương pháp này là chương trình luôn phải truyền các biến ẩn liên tục giữa các trang có liên hệ với nhau.

(cid:121) Ví dụ: ta hãy xem ví dụ ở slide sau đây. Mục đích của ví dụ này là giữ lại thông tin username để các trang khác truy cập.

7

g n ũ D n ấ T õ V

:

V G

HIDDEN FORM FELDS HIDDEN FORM FELDS

Login.html Login.html

Login

Please log in

User Name:
Password:


8

g n ũ D n ấ T õ V

:

V G

9

g n ũ D n ấ T õ V

:

V G

HIDDEN FORM FELDS HIDDEN FORM FELDS

Login.jsp File File Login.jsp

<% //Lay cac thong tin dang nhap

String userName=request.getParameter("username");

String password=request.getParameter("password");

%> Welcome, <%=userName%>!

<%--Luu username vao bien form an --%>

Please enter your favorite book:

10

g n ũ D n ấ T õ V

:

V G

(cid:121) A

11

g n ũ D n ấ T õ V

:

V G

Login.jsp File File Login.jsp

public class BookServlet extends GenericServlet

{ public void service(ServletRequest request, ServletResponse response)

throws IOException

{

response.setContentType("text/html");

PrintWriter out=response.getWriter();

String userName=request.getParameter("username");

String book = request.getParameter("book");

out.println("");

out.println("");

out.println("Well, I see that "+userName+"'s favorite book is "+ book +".");

out.println("");

out.println("");

}

} 12

g n ũ D n ấ T õ V

:

V G

BookServlet.java File File BookServlet.java import javax.servlet.*; import java.io.*;

(cid:121) Ví dụ trên cho ta thấy, thông tin hay giá trị của username được nhập vào từ trang Login.html truyền cho trang Login.jsp. Trang Login.jsp lưu giá trị này trong biến ẩn của form và chuyển tiếp cho Servlet. Quá trình cứ thế tiếp diễn cho đến khi nào bạn thôi không còn muốn sử dụng thông tin của username nữa.

13

g n ũ D n ấ T õ V

:

V G

BookServlet.java File File BookServlet.java

14

g n ũ D n ấ T õ V

:

V G

PHẦN 3 SỬ DỤNG HASH TABLE (dùng để bảo mật các biến ẩn của Form)

(cid:121) Một trong những lý do mà biến ẩn của Form không

được sử dụng nhiều trong các ứng dụng Web thương mại nhất là các site e-commerce đó là tính không bảo mật của giá trị và tên biến.

(cid:121) Với ví dụ BookServlet của các slide trước, người dùng có thể đánh lừa BookServlet bằng cách dùng trình duyệt xem code HTML mà BookServlet gửi xuống và dễ dàng nhận thấy có biến ẩn username. Sau đó người dùng có thể truyền trực tiếp giá trị cho username ngay trên đường dẫn: (cid:121) http://localhost:8080/BookServlet?username=abc&book=Java

15

g n ũ D n ấ T õ V

:

V G

NG HASH TABLE SSỬỬ DDỤỤNG HASH TABLE

(cid:121) Để giải quyết tính không bảo mật của các biến ẩn trong

Form, ta dùng cơ chế bảng băm (Hash Table).

(cid:121) Khi việc chứng thực username/password thành công,

bạn sinh ra một khóa ngẫu nhiên tương ứng với username. Khóa này được đặt trong biến ẩn của Form đồng thời lưu giá trị thực tế của biến username và khóa trong đối tượng bảng băm trên server.

(cid:121) Lần kế tiếp người dùng chuyển biến ẩn lên server,

trang JSP hay Servlet của ta không chuyển giá trị của username mà chuyển giá trị của khóa tương ứng với nó. Có giá trị khóa, thực hiện dò trong bảng băm ta sẽ tìm ra được giá trị của biến username.

16

g n ũ D n ấ T õ V

:

V G

NG HASH TABLE SSỬỬ DDỤỤNG HASH TABLE

(cid:121)

Đối tượng bảng băm dùng sinh khóa và lưu dữ liệu cho biến được cài đặt thành lớp UserDataTable như sau:

/* UserDataTable.java */ package storage; import java.util.*;

public class UserDataTable {

protected static Hashtable userData=new Hashtable();

protected static Random keyGenerator = new Random();

public static String createUserData()

{ String userKey=""+keyGenerator.nextLong();

userData.put(userKey, new Hashtable());

return userKey;

}

public static Hashtable getUserData(String userKey)

{ if(userKey==null) return null;

return (Hashtable)userData.get(userKey);

}

public static void clearUserData(String userKey)

{ if(userKey==null) return;

userData.remove(userKey);

}

g n ũ D n ấ T õ V

:

17 }

V G

UserDatatable.java File File UserDatatable.java

(cid:121) Trang Login2.jsp sau đây thay vì lưu nội dung username vào biến ẩn của Form, chúng ta gọi

UserDataTable sinh khóa và lưu khóa vào biến Form ẩn.

<%-- Login2.jsp --%> <%@ page language="java" import="java.util.*;" %>

<% String userName=request.getParameter("username");

String password=request.getParameter("password");

String userKey=storage.UserDataTable.createUserData();

Hashtable userData=storage.UserDataTable.getUserData(userKey);

userData.put("username", userName); %>

Welcome, <%=userName%>!

Please enter your favorite Book:

18

g n ũ D n ấ T õ V

:

V G

File Login2.jsp File Login2.jsp

(cid:121) Dưới đây là mã nguồn của BookServlet2.jsp thay thế cho BookServlet. BookServlet nhận giá trị

khóa, tìm dữ liệu tương ứng của khóa trong bảng băm và in ra kết xuất.

/* BookServlet2.java */

package storage;

import javax.servlet.*;

import java.io.*;

import java.util.*;

public class NewServlet /*BookServlet2*/ extends GenericServlet

{

public void service(ServletRequest request, ServletResponse response)

throws IOException

{

response.setContentType("text/html");

PrintWriter out = response.getWriter();

String userKey=request.getParameter("userkey");

String book=request.getParameter("book");

19

Hashtable userData=storage.UserDataTable.getUserData(userKey);

g n ũ D n ấ T õ V

:

V G

File BookServlet2.java File BookServlet2.java

if(userData==null)

{

out.println("");

out.println("

Sorry

");

out.println("The system is experiencing problems.");

out.println("");

return;

}

String userName=(String)userData.get("username");

out.println("");

out.println("");

out.println("Well, I see that "+userName+"'s favorite book is "+book+".");

out.println("");

out.println("");

}

} 20

g n ũ D n ấ T õ V

:

V G

File BookServlet2.java File BookServlet2.java

21

g n ũ D n ấ T õ V

:

V G

PHẦN 4 SỬ DỤNG ĐỐI TƯỢNG SESSION

(cid:121) Trong Java, Web server cài đặt sẵn đối tượng session thuộc lớp HttpSession. HttpSession dựa vào khái niệm cookie quy định giữa trình khách và trình chủ. Cookie là một mẩu thông tin được gởi về trình duyệt phía máy khách khi có yêu cầu trang từ server. Mỗi khi trình duyệt phát sinh yêu cầu gửi lên server, nó lại chuyển mẩu cookie trở lại trình chủ. Dựa vào cookie, trình khách và trình chủ sẽ có được những thông tin trạng thái thông báo cho nhau.

22

g n ũ D n ấ T õ V

:

V G

HttpSession LLỚỚP P HttpSession

(cid:121) Với đối tượng session thuộc lớp HttpSession, ba

phương thức mà ta thường sử dụng nhất là: (cid:121) public void setAttribute(String name, Object value)

throws IlligalStateException

(cid:121) public Object getAttribute(String name) throws

IlligalStateException

(cid:121) public void removeAttribute(String name) throws

IlligalStateException

(cid:121) Biến session chỉ tồn tại trong một thời gian nhất định. Nếu muốn chủ động làm cho session hết hiệu lực thì ta gọi phương thức: session.invalidate()

23

g n ũ D n ấ T õ V

:

V G

SSỬỬ DDỤỤNG NG ĐĐỐỐI TI TƯƯỢỢNG SESSION V I JSP NG SESSION VỚỚI JSP

(cid:121) Chú ý: Giá trị mà ta muốn lưu hay lấy về phải là

SSỬỬ DDỤỤNG NG ĐĐỐỐI TI TƯƯỢỢNG SESSION V I JSP NG SESSION VỚỚI JSP

một đối tượng (Object). Đối với các giá trị có kiểu int, float, boolean,… thì ta phải chuyển sang kiểu lớp tương ứng như Integer, Float, Boolean,…

(cid:121) Ví dụ:

Integer tuoicuatui= new Integer(35); session.setAttribute(“tuoi”,tuoicuatui); Integer my_age = (Integer)session.getAttribute(“tuoi”);

24

g n ũ D n ấ T õ V

:

V G

25

g n ũ D n ấ T õ V

:

V G

ViViếếtt llạạii trang trang Login2.jsp session Login2.jsp ddùùngng session

26

g n ũ D n ấ T õ V

:

V G

ViViếếtt llạạii trang trang Login2.jsp session Login2.jsp ddùùngng session

(cid:121) Trong JSP có sẵn đối tượng session để sử dụng nhưng trong Servlet thì session không có sẵn. Ta phải lấy session thông qua đối tượng request. (cid:121) HttpSession session=request.getSession();

(cid:121) Nội dung dữ liệu mà ta lưu vào session trong trang JSP

hoàn toàn có thể truy xuất được từ servlet.

(cid:121) Nếu ta tạo servlet từ lớp GenericServlet thì ta không có được đối tượng HttpRequest để truy xuất biến session.

27

g n ũ D n ấ T õ V

:

V G

SSỬỬ DDỤỤNG NG ĐĐỐỐI TI TƯƯỢỢNG SESSION V Servlet NG SESSION VỚỚI I Servlet

28

g n ũ D n ấ T õ V

:

V G

SSửửaa llạạii BookServlet2 BookServlet3 BookServlet2 ththàànhnh BookServlet3

29

g n ũ D n ấ T õ V

:

V G

SSửửaa llạạii BookServlet2 BookServlet3 BookServlet2 ththàànhnh BookServlet3

(cid:121) Khi bộ xử lý Servlet (Servlet engine) của Web server tạo ra đối tượng session, trình chủ gửi một định danh ID của session cho trình duyệt.

(cid:121) Trình duyệt nhận số định danh ID này và xem nó như

một mẩu tin cookies.

(cid:121) Bất kỳ khi nào trình duyệt yêu cầu một trang tài liệu nào từ server, trình duyệt sẽ gửi ngược định danh ID này về trình chủ.

30

g n ũ D n ấ T õ V

:

V G

CCÁÁCH SESSION L CH SESSION LÀÀM VIM VIỆỆCC

(cid:121) Thông thường mẩu tin cookies sẽ được trình duyệt hủy

bỏ khi bạn đóng cửa sổ trình duyệt.

(cid:121) Trình duyệt còn có thể lưu thông tin cookies lên đĩa

cứng cho lần sử dụng kế tiếp.

(cid:121) Bởi vì session chỉ cần tồn tại trong một khoảng thời

gian tương tác ngắn nên không nhất thiết lúc nào cũng phải lưu thông tin cookies xuống đĩa cứng trừ khi bạn muốn cấu hình cơ chế lưu cookies này.

(cid:121) Nếu một đối tượng session đã được giải phóng mà trình duyệt vẫn gửi yêu cầu gọi nó thì trình chủ sẽ phát sinh ngoại lệ IllegalStateException.

31

g n ũ D n ấ T õ V

:

V G

CCÁÁCH SESSION L CH SESSION LÀÀM VIM VIỆỆCC

32

g n ũ D n ấ T õ V

:

V G

CCÁÁCH SESSION L CH SESSION LÀÀM VIM VIỆỆCC

(cid:121) Ví dụ khi người dùng đăng nhập và mua hàng online trên trang web của bạn. Người dùng chọn một số mục hàng rồi sau đó lại không muốn mua.

(cid:121) Thay vì chọn chức năng xóa các mục hàng đã chọn trên trang web thì người dùng lại chọn giải pháp thoát ra và đăng nhập trở lại. Khi đó toàn bộ thông tin mua hàng cùng với các thông tin trước đó phải bị xóa sạch.

(cid:121) Do đó khi người dùng đăng nhập trở lại thì ta phải viết code xóa nội dung trong session hoặc tạo một session mới.

33

g n ũ D n ấ T õ V

:

V G

BUBUỘỘC TRÌNH CH C TRÌNH CHỦỦ TTẠẠO SESSION M O SESSION MỚỚII

(cid:121) Tạo một session mới hoặc lấy về một đối tượng session hiện có

chúng ta đều dùng phương thức getSession().

(cid:121) Nếu đối số chuyển cho getSession() là true thì session mới sẽ được tạo ra nếu nó chưa có trước đó. Ngược lại với đối số là false, khi không tìm thấy đối tượng session thì phương thức getSession() sẽ trả về giá trị null.

(cid:121) Ví dụ:

34

g n ũ D n ấ T õ V

:

V G

BUBUỘỘC TRÌNH CH C TRÌNH CHỦỦ TTẠẠO SESSION M O SESSION MỚỚII

(cid:121) Đối tượng session có thể chấm dứt và bị hủy bỏ trong

hai trường hợp: ta chủ động gọi phương thức invalidate() của nó hoặc Webserver hủy session do thời gian hiệu lực hết hạn (session timeout).

(cid:121) Tùy theo dữ liệu lưu trong session mà ta phải thực hiện một vài thao tác xóa biến, dọn dẹp các đối tượng trước khi session bị hủy.

(cid:121) Ví dụ ta có thể lưu trong các session các thông tin kết nối đến cơ sở dữ liệu. Hãy thực hiện hủy kết nối này trước khi xóa session vì nó làm cho ứng dụng của ta tăng tốc xử lý đối với các người dùng còn lại.

35

g n ũ D n ấ T õ V

:

V G

XXỬỬ LÝ CH T SESSION LÝ CHẤẤM DM DỨỨT SESSION

(cid:121) Đối tượng session cũng cài đặt cơ chế gọi ngược lại

(callback) để thông báo cho một đối tượng nào đó trạng thái đối tượng được ràng buộc vào session hoặc khi session bị hủy. (cid:121) Cụ thể khi ta gọi

session.setAttribute(“somename”,someObject), đối tượng some Object được thông báo rằng nó được ràng buộc vào session. Khi session hết hạn, someObject cũng sẽ được thông báo về sự kết thúc của session để đối tượng có thể tự thực hiện các thao tác hủy của mình.

36

g n ũ D n ấ T õ V

:

V G

XXỬỬ LÝ CH T SESSION LÝ CHẤẤM DM DỨỨT SESSION

(cid:121) Để cài đặt cơ chế thông báo của session, ta dùng giao diện HttpSessionBindingListener. Giao diện này có 2 phương thức cơ bản là: (cid:121) public void valueBound(HttpSessionBindingEvent evt) (cid:121) public void valueUnBound(HttpSessionBindingEvent evt) (cid:121) valueBound sẽ được gọi khi đối tượng được ràng buộc vào session còn valueUnBound sẽ được gọi khi đối tượng bị loại bỏ khỏi session.

(cid:121) Ví dụ trong slide tiếp sau đây là lớp BindListener lắng nghe các trạng thái ràng buộc đối tượng vào session bằng cách tăng hoặc giảm biến đếm cho biết số lần đối tượng được đưa vào hoặc lấy ra khỏi session.

37

g n ũ D n ấ T õ V

:

V G

XXỬỬ LÝ CH T SESSION LÝ CHẤẤM DM DỨỨT SESSION

38

g n ũ D n ấ T õ V

:

V G

BindListener.java BindListener.java

39

g n ũ D n ấ T õ V

:

V G

BindListener.java BindListener.java

40

g n ũ D n ấ T õ V

:

V G

BindTest.jsp BindTest.jsp

41

g n ũ D n ấ T õ V

:

V G

BindTest.jsp BindTest.jsp

42

g n ũ D n ấ T õ V

:

V G

BindTest.jsp BindTest.jsp

43

g n ũ D n ấ T õ V

:

V G

BindTest.jsp BindTest.jsp

44

g n ũ D n ấ T õ V

:

V G

XXỬỬ LÝ CH T SESSION LÝ CHẤẤM DM DỨỨT SESSION

TTẠẠO SESSION KHÔNG C

(cid:121) Nhưng rất nhiều người khi lướt web thì họ đã thiết lập

cấu hình không cho trình duyệt sử dụng cơ chế cookies.

(cid:121) Ta có thể tự tạo session ID và truyền chúng như là

tham số đến tất cả các trang JSP và Servlet trong ứng dụng.

45

(cid:121) Thay vì để trình duyệt tự động giấu session ID trong cookies và chuyển đi trong mỗi lời yêu cầu, ta thực hiện việc này một cách tường minh với session ID được đặt trên URL.

g n ũ D n ấ T õ V

:

V G

N COOKIES O SESSION KHÔNG CẦẦN COOKIES (cid:121) Session mà JSP và Servlet sử dụng dựa trên cơ chế HTTP cookies. Cookies lưu trữ giá trị nhận dạng session ID cho mỗi yêu cầu phát sinh và trao đổi giữa trình duyệt với Web server.

(cid:121) Lớp HttpServletResponse cung cấp hai phương thức cho phép chèn session ID vào đường dẫn URL trong các lời gọi trang và Servlet: (cid:121) public String encodeURL(String url) (cid:121) public String encodeRedirectURL(String url)

(cid:121) Phương thức encodeURL và encodeRedirectURL sẽ trả

về đường dẫn tham chiếu URL chứa session ID.

(cid:121) Trang RewriteDemo.jsp của slide tiếp theo sẽ hiển thị một form, xử lý và nhận dữ liệu do form submit, đặt các giá trị nhận được từ form vào biến session.

46

g n ũ D n ấ T õ V

:

V G

TTẠẠO SESSION KHÔNG C N COOKIES O SESSION KHÔNG CẦẦN COOKIES

47

g n ũ D n ấ T õ V

:

V G

RewriteDemo.jsp RewriteDemo.jsp

48

g n ũ D n ấ T õ V

:

V G

RewriteDemo.jsp RewriteDemo.jsp

49

g n ũ D n ấ T õ V

:

V G

RewriteDemo2.jsp RewriteDemo2.jsp

50

g n ũ D n ấ T õ V

:

V G

TTẠẠO SESSION KHÔNG C N COOKIES O SESSION KHÔNG CẦẦN COOKIES

51

g n ũ D n ấ T õ V

:

V G

PHẦN 5 SỬ DỤNG ĐỐI TƯỢNG APPLICATION

(cid:121) Lớp HttpSession cung cấp đối tượng session lưu dữ

liệu tương ứng và tách biệt đối với người dùng. Mặc dù vậy sẽ có lúc ta cần lưu những biến toàn cục để mọi trang JSP hay Servlet thuộc về các session khác nhau đều có thể nhìn thấy được giá trị của biến.

(cid:121) Trong JSP ta gọi đối tượng application để lưu tất cả các

biến có thể nhìn thấy toàn cục.

52

g n ũ D n ấ T õ V

:

V G

U TRONG APPLICATION LLƯƯU DU DỮỮ LILIỆỆU TRONG APPLICATION

(cid:121) Các phương thức mà đối tượng application cung cấp để lưu trữ và loại bỏ biến hoàn toàn tương tự các phương thức mà session cung cấp.

53

g n ũ D n ấ T õ V

:

V G

U TRONG APPLICATION LLƯƯU DU DỮỮ LILIỆỆU TRONG APPLICATION

(cid:121) Ví dụ: trang Default.jsp trong ứng dụng BookStore đếm số người dùng truy cập trang web bằng biến GlobalCounter lưu trong đối tượng application như sau:

54

g n ũ D n ấ T õ V

:

V G

U TRONG APPLICATION LLƯƯU DU DỮỮ LILIỆỆU TRONG APPLICATION

(cid:121) Đối tượng application trong JSP thực sự được cài đặt từ giao diện ServletContext. Trong servlet ta có thể lấy giao tiếp này để dùng cho mục đích lưu biến vào đối tượng application. Biến application trong servlet có được bằng cách sử dụng lệnh sau:

(cid:121) Hoặc trong phương thức init() của Servlet, ta lấy về tham chiếu của đối tượng application như sau:

55

g n ũ D n ấ T õ V

:

V G

U TRONG APPLICATION LLƯƯU DU DỮỮ LILIỆỆU TRONG APPLICATION

(cid:121) Để phân biệt biến lưu trong session và biến lưu trong application khác nhau ra sao, ta có thể kiểm tra bằng trang TestVariable.jsp như sau:

56

g n ũ D n ấ T õ V

:

V G

TestVariable.jsp TestVariable.jsp

57

g n ũ D n ấ T õ V

:

V G

TestVariable.jsp TestVariable.jsp

(cid:121) Ta gọi trang TestVariable.jsp trong hai cửa sổ trình duyệt khác nhau. Kết quả giá trị biến appCount tăng liên tục trong khi biến sesCounter chỉ tăng cục bộ trong từng cửa sổ trình duyệt.

58

g n ũ D n ấ T õ V

:

V G

TestVariable.jsp TestVariable.jsp

59

g n ũ D n ấ T õ V

:

V G

TestVariable.jsp TestVariable.jsp

60

g n ũ D n ấ T õ V

:

V G

HẾT BÀI 7