1. Giới thiệu về Servlet

Hiện nay, trong lập trình có một xu hướng rất quan trọng đang được tập trung phát triển ứng dụng, đó là xây dựng các chương trình dịch vụ Java ở phía máy chủ (Server).

Servlet là thành phần chính được sử dụng để phát triển các chương trình dịch vụ Java ở phía máy chủ. Các Servlet là các chương trình Java thực hiện ở các ứng dụng Server (tên gọi “Servlet” cũng gần giống như “Applet” ở phía máy Client) để trả lời cho các yêu cầu của Client. Các Servlet không bị ràng buộc chặt với một giao thức Client-Server cụ thể nào cả, nhưng giao thức thường được sử dụng là HTTP, do vậy, khi nói tới Servlet nghĩa là nói tới HTTP Servlet. Servlet là sự phát triển mở rộng của CGI để đảm bảo Server thực hiện được các chức năng của mình. Ta có thể sử dụng Servlet của Java để tuỳ chỉnh lại một dịch vụ bất kỳ, như Web Server, Mail Server, v.v.

Web Server hiển thị các tư liệu được viết trong HTML và hồi đáp cho yêu cầu của người sử dụng qua HTTP. Các tư liệu HTML chứa các văn bản được đánh dấu (định dạng) để các trình duyệt như IE, Netscape đọc được.

Một trình duyệt chấp nhận đầu vào ở dạng HTML, khi người sử dụng nhấn một nút để yêu cầu một số thông tin nào đó, một Servlet đơn giản được gọi để xử lý các yêu cầu đó. Các công việc chính của Servlet được mô tả khái quát trong hình 1, bao gồm:

  • Đọc các dữ liệu tường minh được Client gửi đến từ các yêu cầu (dữ liệu theo các khuôn dạng – form data).
  • Đọc các dữ liệu không tường minh được Client gửi đến từ các yêu cầu (dữ liệu trong phần đầu của yêu cầu – request headers).
  • Xử lý và lưu trữ các dữ liệu được cung cấp dưới dạng HTML.
  • Gửi trả lời dữ liệu tường minh cho Client (dạng HTML), cung cấp các nội dung động, ví dụ trả lời yêu cầu Client về các câu truy vấn vào các CSDL.
  • Quản lý các thông tin trạng thái và trả lời dữ liệu không tường minh cho Client (các mã trạng thái và các phần đầu của trả lời).

Hình 1 Vai trò của Servlet

Viết một Servlet là tương đối dễ. Ta chỉ cần có Tomcat, nó là tổ hợp của Java Server PagesTM 1.1 và Servlets 2.2.  Tomcat có thể nạp miễn phí từ http://java.sun.com/products/jsp/tomcat/, phần cài đặt sẽ được mô tả ở phần sau.

Các Servlet cũng được sử dụng thay cho kịch bản giao diện cổng chung CGI Script. Khi tạo ra một trang Web, ta cũng sẽ tạo ra một ứng dụng Web.

Trước khi sử dụng Servlet để tạo ra các ứng dụng Web, chúng ta đi tìm hiểu xem có những khả năng lựa chọn nào khác để phát triển những ứng dụng Web.

  • CGI: Theo cách thông thường, để bổ sung các chức năng vào cho một Web Server người ta hay sử dụng Common Gateway Interface (CGI), một giao diện độc lập với ngôn ngữ cho phép một Server khởi động một tiến trình ngoại để nhận thông tin được yêu cầu thông qua các biến môi trường. Mỗi yêu cầu được trả lời bởi một tiến trình riêng thông qua một đại diện riêng của một chương trình CGI hoặc bởi một kịch bản CGI (thường được viết bằng ngôn ngữ thông dịch như Perl).
  • Fast CGI: Open Marked đã phát triển một chuẩn khác thay cho CGI được gọi là Fast CGI.  Fast CGI hành động giống như CGI. Nó khác ở chỗ, Fast CGI tạo ra một tiến trình bền vững cho từng chương trình.
  • Một số chương trình ứng dụng khác như ASP và Java Script cũng hỗ trợ để tạo ra các ứng dụng Web. ASP được Microsoft phát triển để tạo ra các nội dung cho các trang Web động. Trong ASP, trang HTML có thể nhúng những phần nhỏ được viết bằng VBScript hoặc JScript. Netscape đưa ra kỹ thuật được gọi là JavaScript, cho phép đưa các phần mã lệnh nhỏ nhúng vào trang HMTL, nhằm tạo ra những nội dung Web động một cách linh họat hơn. Ngoài ra, Netscape còn cung cấp NSAPI, Microsoft đưa ra ISAPI cho các Web Server của họ.

Servlet có một số ưu điểm so với CGI:

  • Một Servlet không làm việc trong một tiến trình riêng. Điều này loại bỏ được việc phải tạo ra quá nhiều tiến trình mới cho mỗi yêu cầu.
  • Một Servlet sẽ thường trực trong bộ nhớ giữa các yêu cầu, trong khi các chương trình CGI cần phải tải xuống và được khởi động cho từng yêu cầu CGI.
  • Chỉ cần một Servlet trả lời đồng thời cho tất cả các yêu cầu. Điều này cho phép tiết kiệm được bộ nhớ và đảm bảo nó dễ dàng quản lý được dữ liệu một cách thống nhất.
  • Một Servlet có thể thực hiện bởi một Servlet Engine trong phạm vi kiểm soát Sandbox để đảm bảo an toàn trong việc sử dụng các Servlet.

Các lớp Servlet  của Java có thể được nạp tự động để mở rộng các chức năng của Server. Các Servlet của Java thực hiện bên trong JVM. Chúng được đảm bảo an toàn và chuyển đổi tương thích giữa các hệ điều hành và giữa các Server với nhau. Điều này khác với các Applet, Servlet chỉ thao tác được trong miền của một Server.

Servlet API được phát triển dựa trên những điểm mạnh của Java platform nhằm giải quyết vấn đề của CGI và Server API. Nó là một API đơn giản, hỗ trợ tất cả các Web server và thậm chí cho phép các ứng dụng máy chủ dùng để kiểm tra và quản lý các công việc trên Server. Nó giải quyết vấn đề thực thi bằng việc thực hiện tất cả các yêu cầu như các luồng Thread trong quá trình xử lý, hoặc việc cân bằng tải trên một Server trong các cụm máy tính Cluster. Các Servlet dễ dàng chia sẻ tài nguyên với nhau.

Trong định nghĩa Servlet, vấn đề bảo mật được cải tiến theo nhiều cách. Trước hết, bạn hiếm khi thực thi được các câu lệnh trên Shell với dữ liệu cung cấp bởi người dùng mà Java API đã cung cấp với những khả năng truy cập đến tất cả các hàm  thông dụng. Bạn có thể sử dụng Java Mail để đọc và gửi mail, kết nối vào các CSDL (thông qua JDBC), tệp lớp (.class) và những lớp liên quan để truy cập hệ thống tệp, CSDL, RMI, CORBA, Enterprise Java Beans (EJB), …

2. Ưu điểm của Servlet

Servlet được sử dụng để thay thế cho những công nghệ Web động. Việc sử dụng Servlet mang lại những lợi thế:

  • Dễ di chuyển. Servlet được viết bằng Java nên nó có tính di động cao, thực hiện được trên nhiều hệ điều hành, trên các Web Server khác nhau. Khái niệm “Viết một lần, chạy ở mọi nơi” cũng rất đúng với Servlet.
  • Mạnh mẽ. Servlet hỗ trợ rất hiệu quả cho việc sử dụng các giao diện lõi API như lập trình mạng, xử lý đa luồng, xử lý ảnh, nén dữ liệu, kết nối các CSDL, bảo mật, xử lý phân tán và triệu gọi từ xa RMI, CORBA, v.v. Nó cũng thích hợp để trao đổi tin, truyền thông giữa Client và Server một cách bình thường.
  • Hiệu quả. Servlet có tính hiệu quả cao. Một khi được tải về, nó sẽ được lưu lại trong bộ nhớ của máy chủ. Servlet duy trì các trạng thái của nó, do vậy những tài nguyên ngoại như việc kết nối với CSDL cũng sẽ được lưu giữ lại.
  • An toàn. Bởi vì Servlet được viết bằng Java nên nó kế thừa được tính an toàn của Java. Cơ chế tự động dọn rác và việc không sử dụng con trỏ của Java giúp cho Servlet thoát khỏi nhiều công việc quản lý bộ nhớ. Đồng thời nó xử lý các lỗi rất an toàn theo cơ chế xử lý ngoại lệ của Java.
  • Tính tích hợp. Các Servlet được tích hợp với các Server. Chúng cộng tác với các Server tốt hơn các chương trình CGI.
  • Tính linh hoạt. Các Servlet hoàn toàn mềm dẻo. Một HTTP Servlet được sử dụng để tạo ra một trang Web, sau đó ta có thể sử dụng thẻ <Servlet> để đưa nó vào trang Web tĩnh, hoặc sử dụng với các Servlet khác để lọc ra các nội dung cần thiết.

3. Môi trường thực hiện Servlet

Các Servlet thường là sự mở rộng (kế thừa) các lớp chuẩn Java trong gói javax.servlet (chứa các khuôn mẫu cơ bản của Servlet) và javax.servlet.http (mở rộng các khuôn mẫu cơ bản của Servlet và các yêu cầu theo HTTP).

Servlet là một lớp Java và vì thế cần được thực thi trên một máy ảo Java (JVM) và bằng một dịch vụ được gọi là mô tơ Servlet (Servlet Engine). Servlet Engine tải lớp Servlet lần đầu tiên nó được yêu cầu, hoặc ngay khi Servlet Engine được bắt đầu. Servlet ngừng tải để xử lý nhiều yêu cầu khi Servlet Engine bị tắt hoặc nó bị dừng lại.

Như vậy, để dịch và thực hiện các Servlet, việc có các Servlet là chưa đủ, mà cần phải có một mô tơ  Servlet để kiểm tra và triển khai chúng. Hiện nay một số mô tơ tương thích với nhiều loại Web Server khác nhau, nhưng nguyên lý hành động tương đối giống nhau. Người ta chia chúng thành ba loại.

  • Mô tơ Servlet đơn
  • Mô tơ Servlet gộp
  • Mô tơ Servlet nhúng.

3.1 Mô tơ Servlet đơn

Đây là loại Server được xây dựng để hỗ trợ cho các Servlet. Ưu điểm của nó là mọi thứ làm việc với các hộp kết quả đầu ra rất phong phú. Tuy nhiên, nó có nhược điểm là ta phải chờ những phiên bản mới của Web Server để nhận được những hỗ trợ mới nhất cho Servlet. Hiện nay có các loại mô tơ đơn sau:

  • Java Server Web Development (JSWDK) của Sun Microsystem: được viết hoàn toàn bằng Java: http://java.sun.com.products/servlet/. Nó được sử dụng như là một Server độc lập để kiểm tra các Servlet và các trang JSP trước khi phát triển thành một Web Server thực sự.
  • Jagsaw Server của WWW Consortium, cũng được viết bằng Java. Chi tiết hơn, xem http://www.w3.org/Jigsaw.
  • Netscape Enterprise Server. Đây là Web Server rất nổi tiếng, nó hỗ trợ để xây dựng Servlet.
  • Lotus Domino Go WebServer. Một loại Web Server khác cũng hỗ trợ để xây dựng Servlet.   

3.2 Mô tơ Servlet gộp

Servlet gộp là loại mô tơ được viết cho nhiều loại Server khác nhau, kể cả Apache, Fast Track Server, Enterprise Server của Netscape, Personal Web Server, v.v. Hiện nay có các loại sau:

  • Apache Tomcat: Mô tơ này hỗ trợ thêm cho Apache.  Nó được sử dụng như là một Server độc lập để kiểm tra các Servlet và các trang JSP, hoặc được tích hợp vào Apache Web Server, http://java.sun.com.products/servlet/.
  • .Jrun của Live Software: Jrun là mô tơ cho Servlet và JSP, hỗ trợ đầy đủ Servlet API trong các Web Server phổ biến trên mọi hệ điều hành, http://www.allaire.com.products/jrun/.
  • WebSphere Application Server của IBM: còn được gọi là ServletExpress.
  • ServletExec của New Atlanta: ServletExec là mô tơ cho Servlet và JSP, hỗ trợ đầy đủ Servlet API trong các Web Server phổ biến trên mọi hệ điều hành, http://newatlanta.com/.

3.3 Mô tơ Servlet nhúng

Loại mô tơ này có thể nhúng vào phần mềm ứng dụng khác. Hiện nay có các loại sau:

  • Java Server Engine của Sun. Đây là loại mô tơ được viết hoàn toàn bằng Java và là Web Server đầu tiên hỗ trợ đầy đủ cho các đặc tả của Servlet 2.1 và JSP 1.0,  http://www.sun.com.software/jwebserver/try.
  • Nexus Web Server của Anders Kristensen. Nó có thể dễ dàng nhúng vào các chương trình ứng dụng Java.

4. Kiến trúc của Servlet

Gói javax.servlet cung cấp các giao diện và các lớp để xây dựng các Servlet. Kiến trúc của chúng được mô tả như sau.

Hình 2 Kiến trúc của Servlet

4.1 Giao diện Servlet

Giao diện Servlet là một khái niệm trừu tượng trung tâm trong Servlet API. Tất cả các Servlet đều cài đặt trực tiếp hoặc gián tiếp giao diện này hoặc mở rộng (kế thừa) những lớp đã cài đặt nó.

Giao diện này khai báo ba phương thức định nghĩa vòng đời của Servlet.

  • public void init(ServletConfig config) throws ServletException

Phương thức này được gọi một lần khi Servlet được tải vào trong Servlet Engine, trước khi Servlet được yêu cầu để xử lý một yêu cầu nào đó. Phương thức init() có một thuộc tính là đối tượng của ServletConfig, và Servlet có thể đọc các đối số khởi tạo của nó thông qua đối tượng ServletConfig. Chúng thường được định nghĩa trong một tệp cấu hình. Một ví dụ thông thường của một đối số khởi tạo là định danh database cho một CSDL.


private String databaseURL;

public void init(ServletConfig config) throws ServletException {

super.init(config);

databaseURL = config.getInitParameter(“database”);

}

  • public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException

Phương thức này được gọi để xử lý các yêu cầu. Nó có thể không được gọi, gọi một lần hay nhiều lần cho đến khi Servlet được ngưng tải. Nhiều Thread (mỗi Thread cho một yêu cầu) có thể thực thi phương thức này song song, vì thế nó trở nên an toàn và hiệu quả hơn.

  • public void  destroy()

Phương thức này chỉ được gọi một lần trước khi Servlet được ngưng tải và sau khi đã kết thúc các dịch vụ.

Servlet API có cấu trúc để Servlet có thể cho phép bổ sung một giao thức khác với HTTP. Gói javax.servlet chứa các lớp và các giao diện được kế thừa giao diện Servlet một cách độc lập. Gói javax.servlet.http chứa các lớp và giao diện HTTP cụ thể.

4.2. Lớp cơ sở HttpServlet

Như ta đã biết, theo giao thức HTTP, dữ liệu được trao đổi giữa máy chủ Server và các máy Client theo một trong hai phương thức GET hay POST. Java định nghĩa một lớp có tên là HttpServlet ở trong goi javax.servlet để truyền và nhận dữ liệu theo cả hai phương thức trên.

Lớp trừu tượng HttpServlet cung cấp một khung làm việc để xử lý các yêu cầu GET, POST của giao thức HTTP. HTTPServlet kế thừa giao diện Servlet cộng với một số các phương thức hữu dụng khác.

Một tập các phương thức trong HTTPServlet là những phương thức xác định dịch vụ trong giao diện Servlet. Việc bổ sung dịch vụ trong HTTPServlet giống như một kiểu của các yêu cầu được xử lý (GET, POST, HEAD, …) và gọi một phương thức cụ thể cho mỗi kiểu. Bằng việc làm này, các nhà phát triển Servlet sẽ an tâm khi xử lý chi tiết những yêu cầu như HEAD, TRACE, OPTIONS, … và có thể tập trung vào những yêu cầu thông dụng hơn như GET và POST.

HTTP sinh ra các trang HTML và ta có thể nhúng các Servlet vào một trang HTML.

Khi có một yêu cầu được gửi tới, đầu tiên nó phải chỉ ra lệnh cho HTTP bằng cách gọi một phương thức tương ứng. Phương thức này chỉ cho Server biết kiểu hành động mà nó muốn thực hiện.

Khi có một Client gửi tới một yêu cầu, Server sẽ xử lý yêu cầu nhận được và gửi trả lại kết quả cho Client. Hai phương thức doGet() và doPost() được sử dụng chung để nhận và gửi tin trong các Servlet.

Một Servlet bất kỳ, ví dụ MyServlet phải kế thừa HttpServlet và viết đè ít nhất một trong các phương thức doGet() để thực thi thao tác GET của HTTP, hay doPost() để thực thi thao tác POST của HTTP.

Trong ví dụ đầu tiên, chúng ta sẽ viết đè phương thức doGet() dạng

protected void doGet(HttpServletRequest request, HttpServletResponse

response) throws ServletException, IOException {


}

Phương thức doGet() có hai tham số đối tượng thuộc hai lớp HttpServletRequest và HttpServletResponse (cả hai lớp này được định nghĩa trong javax.servlet.http). Hai đối tượng này cho phép chúng ta truy cập đầy đủ tất cả các thông tin yêu cầu và cho phép gửi dữ liệu kết quả cho Client để trả lời cho yêu cầu đó.

Với CGI, các biến môi trường và stdin được sử dụng để nhận thông tin về yêu cầu, tuy nhiên việc đặt tên các biến môi trường có thể khác nhau giữa các chương trình  CGI, và một vài biến có thể không được cung cấp bởi tất cả các Web Server.

Đối tượng HttpServletRequest cũng cung cấp thông tin giống như biến môi trường của CGI nhưng theo một hướng chuẩn. Nó cũng cung cấp những phương thức để mở ra các tham số HTTP từ dãy các câu truy vấn hoặc từ nội dung của yêu cầu phụ thuộc vào kiểu yêu cầu (GET hay POST).

Ví dụ 1 Chương trình FirstServlet để đếm và hiển thị số lần nó được truy cập.

package myservlet;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class FirstServlet extends HttpServlet{

int i = 0;

public void doGet(HttpServletRequest re, HttpServletResponse resp)

throws ServletException, IOException{

resp.setContentType(“text/html”);

PrintWriter out = resp.getWriter();

i++;

out.println(“So lan duoc truy cap: ” + i);

out.close();

}

}

doGet(HttpServletRequest req, HttpServletResponse resp) sử dụng đối số thứ nhất req để đọc các phần đầu, tiêu đề (header) của HTTP gửi tới (ví dụ như dữ liệu dạng HTML mà người dùng nhập vào), và sử dụng resp để xác định dòng trả lời cho HTTP (xác định kiểu nội dung trao đổi, đặt Coookie). Điều quan trọng nhất là phải nhận được một đối tượng của PrintWriter (ở java.io) thông qua resp.getWriter()để gửi kết quả trả lại cho Client. Ngoài doGet(), doPost() HttpServlet còn có các phương thức:

  • service(): thực hiện khi đối tượng của lớp được tạo lập và triệu gọi doGet() hoặc doPost().
  • doPut(): thực hiện thao tác PUT của  HTTP.
  • doDelete(): thực hiện thao tác DELETE của  HTTP.
  • init() và destroy(): khởi tạo và huỷ bỏ các Servlet.
  • getServletInfo(): nhận các thông tin về Servlet.

Lưu ý: Cả doGet() và doPost() đều có thể phát sinh ra một trong hai ngoại lệ ServletException, hay IOException, do vậy ta phải khai báo chúng như trên. Ngoài ra, một điều nữa chúng ta cũng chú ý là hai phương thức doGet() và doPost() sẽ được phương thức service() gọi để thực hiện và đôi lúc ta có thể viết đè service() thay cho hai phương thức trên.

Tham khảo: Lập trình Java nâng cao của Đoàn Văn Ban

Các bài liên quan:
Tìm hiểu Servlet – Phần 2