CHU KỲ SỐNG CỦA SERVLET

Một phần của tài liệu Giáo trình lập trình Web với Servlet và JSP - Đặng Thanh Dũng (Trang 62 - 67)

Chương 5 : CƠ BẢN VỀ SERVLET

5.6. CHU KỲ SỐNG CỦA SERVLET

Phương thức INIT() sẽ được gọi để khởi tạo servlet. Sau đó, mỗi user yêu cầu gửi kết quả trong một thread bằng cách gọi phương thức service(). Khi nhiều user yêu cầu trả kết quả cùng lúc sẽ dẫn đến việc nhiều thread gọi phương thức service() cùng lúc mặc dù servlet chỉ có thể được cài đặt ở chế độ SingleThreadModel, chỉ cho phép chạy một thread

tại cùng một thời điểm. Phương thức service() sau đó sẽ gọi hàm doGet(), doPost() hoặc một hàm doXXXnào đó khác, tùy thuộc vào loại HTTP request gửi tới nó. Sau cùng, khi serverquyết định unload servlet thì phương thức destroy() của servlet đó sẽ được gọi.

5.6.1. Phương thức service

Mỗi khi server nhận một request từ servlet, server sẽ bắt đầu một thread mới và gọi phương thức service(). Phương thức này sẽ kiểm tra loại HTTPrequest (GET, POST, PUT, DELETE…), sau đó gọi các phương thức tương ứng doGet, doPost, doPut, doDelete…

Giả sử chúng ta có một servlet cần xử lý cả hai request là POSTvà GET giống nhau, khi đó chúng ta thường có khuynh hướng ghi đè phương thức service hơn là cài đặt cả hai hàm doGetvà doPost. Đây thực sự không phải là cách giải quyết tốt. Thay vào đó, hãy để doPost gọi doGethoặc ngược lại như sau:

Bảng 5.8 - Ví dụ cài đặt phương thức doPost gọi doGetpublic void doGet(HttpServletRequest request, public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

// Servlet code

}

public void doPost(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException { doGet(request, response);

}

Phương pháp này có nhiều ưu điểm hơn so với cách trực tiếp ghi đè phương thức service: (1) sau này, có thể thêm hỗ trợ cho các phương thức HTTP request bằng cách thêm doPut, doTrace… trong một subclass nào đó, (2) có thể thêm hỗ trợ xem ngày chỉnh sửa bằng cách thêm vào phương thức getLastModified (vì getLastModified được gọi bởi phương thức service mặc định nên việc ghi đè phương thức servicesẽ làm mất đi tính năng này), (3) phương thức service mặc định tự động hỗ trợ các requestHEAD, OPTION, TRACE.

5.6.2. Các phương thức doGet, doPost, doXXX

Phần lớn thời gian khi chạy ứng dụng, chúng ta hầu như chỉ quan tâm đến hai request là GET và POST, và khi đó sẽ override hai phương thức doGetvà doPost. Tuy nhiên, nếu cần, chúng ta cũng có thể ghi đè các phương thức doDelete cho request DELTE, doPut cho request

PUT, doOptions cho request OPTIONS, doTrace cho request TRACE. Cũng cần lưu ý rằng phương thức servicetự động hỗ trợ cho request OPTIONSvà TRACE.

Thông thường, không cần phải cài đặt phương thức doHead để xử lý request HEAD vì hệ thống sẽ tự động gọi doGet và sử dụng các cài đặt trạng thái kết quả của dòng (line) và tiêu đề (head) để trả lời

request HEAD. Tuy nhiên, đôi khi chúng ta nên cài đặt doHead để

giải quyết các request HEAD đặc biệt (chẳng hạn như các request từ client mà chỉ cần các HTTP headers chứ không phải toàn bộ tài liệu (document), cần thời gian nhanh hơn khi không cần phải xuất ra toàn bộ document cùng lúc.

5.6.3. Phương thức init

Thông thường, servlet chỉ đối phó với dữ liệu của mỗi request. Do vậy, chúng ta chỉ cần hai phương thức doGet và doPost. Tuy nhiên, đôi khi bạn cần thực hiện các tác vụ cài đặt phức tạp tại thời điểm servlet load lên lần đầu tiên chứ không cần lặp lại ở mỗi request. Khi đó, chúng ta cần dùng phương thức init. Hàm này được gọi khi tạo servlet lần đầu tiên và không gọi lại ở mỗi request.

Bảng 5.9 - Định nghĩa phương thức init() public void init() throws ServletException { // Initialization code...

}

Phương thức init vận hành hai loại khởi tạo: khởi tạo thông thường và khởi tạo có tham số.

Khởi tạo thông thường

Phương thức init chỉ tạo hoặc tải (load) những dữ liệu sẽ được dùng trong suốt chu kỳ sống của servlet, hoặc vận hành một vài tính toán chỉ dùng một lần (one-time computation).

Trong ví dụ bên dưới, phương thức init thực hiện hai việc:

(1) Tạo một mảng 10 phần tử số nguyên (integer). Do những tính toán trên các phần tử này rất phức tạp nên chúng ta sẽ không muốn lặp lại việc tính toán cho mỗi request. Vì vậy, hàm doGet sẽ lấy giá trị kết quả mà phương thức init tính được thay vì phải tính kết quả này mỗi lần có request.

(2) Do kết quả xuất ra của servlet không thay đổi trừ khi reboot lại server nên phương thức init cũng lưu lại thời điểm chỉnh sửa trang web, và giá trị này sẽ được hàm getLastModified sử dụng. Phương thức này sẽ trả về thời gian chỉnh sửa tính từ năm 1970 (đơn vị tính là milisecond). Giá trị thời gian này sẽ tự động đổi sang giá trị ngày GMT.

Bảng 5.10 - coreservlets/LotteryNumbers.java

package coreservlets;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

/** Ví dụ sử dụng servlet initialization và phương thức */

public class LotteryNumbers extends HttpServlet {

private long modTime;

private int[] numbers = new int[10];

/** Phương thức init() được gọi chỉ khi servlet được * loaded, trước khi request đầu tiên được xử lý. */

public void init() throws ServletException {

// Làm tròn

modTime = System.currentTimeMillis()/1000*1000;

for(int i=0; i<numbers.length; i++) {

numbers[i] = randomNum(); }

}

/** Trả về các số được tính trong init() */

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Your Lottery Numbers"; String docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">\n"; out.println(docType + "<HTML>\n" + "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=CENTER>" + title + "</H1>\n" +

"<B>Based upon extensive research of " +

"astro-illogical trends, psychic farces, " +

"and detailed statistical claptrap, " +

" best lottery numbers for you.</B>" + "<OL>");

for(int i=0; i<numbers.length; i++) { out.println(" <LI>" + numbers[i]); }

out.println("</OL>" + "</BODY></HTML>"); }

public long getLastModified(HttpServletRequest request) {

return(modTime); }

// Số ngẫu nhiên từ 0 đến 99.

private int randomNum() {

return((int)(Math.random() * 100)); }

}

Hình 5.5 - Kết quả của servlet Lottery Numbers

Sự khởi tạo được kiểm soát bởi các tham số khởi tạo

Thông thường có ba nhóm đối tượng có nhu cầu điều chỉnh servlet hoặc JSP page.

(1) Developer: thay đổi hành vi của servlet bằng cách thay đổi code. (2) End user: thay đổi hành vi của servlet bằng cách nhập dữ liệu vào

HTML form.

(3) Deployer: chuyển servlet từ machine này sang machine khác và thay đổi một vài tham số nhất định (địa chỉ CSDL, thư mục chứa tập tin dữ liệu,…) mà không phải chỉnh sửa code của servlet. Đây chính là mục đích sử dụng chính của phương thức khởi tạo có tham số. Dưới đây là hướng dẫn vắn tắt về cách sử dụng hàm khởi tạo có tham số:

 Bước 1: Sử dụng phần tử web.xml servlet để đặt tên cho servlet.

 Bước 2: Sử dụng phần tử web.xml servlet-mapping để gán custom URL cho servlet (không sử dụng URL mặc định dạng http://.../servlet/ServletName khi sử dụng hàm init có tham số).

 Bước 3: Thêm subelement init-paramvào phần tử web.xml servlet để gán tên và giá trị của các tham số khởi tạo.

 Bước 4: Trong phương thức init của servlet, gọi phương getServletConfig để lấy tham chiếu đến đối tượng ServletConfig.

 Bước 5: Gọi phương thức getInitParameter của ServletConfig theo tên của tham số khởi tạo. Kết quả trả về chính là giá trị của tham số init (có thể mang giá trị null nếu không tìm thấy tham số khởi tạo có tên giống tên tham số truyền vào).

5.6.4. Phương thức destroy

Server gọi phương thức destroy khi muốn loại bỏ thể hiện của servlet (servlet instance). Phương thức này thực hiện việc đóng CSDL của servlet, tạm dừng tất cả các thread mà servlet đã tạo, chép cookies lên đĩa cứng đồng thời xóa các activity.

Một phần của tài liệu Giáo trình lập trình Web với Servlet và JSP - Đặng Thanh Dũng (Trang 62 - 67)