Thứ Ba, 23 tháng 4, 2013

Java Servlet : Giới thiệu

1. Java Servlet là gì?

Với mục đích tương tự như Java Applet, Java Servlet nhằm cung cấp nội dung động đến người dùng; nhưng trái với các applet chạy ở phía khách (trên trình duyệt web chẳng hạn), các servlet là những môđun mã Java chạy trên máy chủ web (server web). Về mặt từ ngữ applet có nghĩa là ứng dụng nhỏ (bắt nguồn từ từ application với hậu tố -et hàm nghĩa là nhỏ), hiểu theo nghĩa tương tự servlet cũng là ứng dụng nhỏ chạy trên máy chủ (ghép của server và applet). Servlet không gắn chặt với một giao thức khách-chủ đặc thù nào cả, nhưng vì hầu như thường được dùng với giao thức HTTP nên từ Servlet thường được hiểu với nghĩa HTTP Servlet.

Một servlet được thực thi động trên máy chủ và cho phép mở rộng thêm chức năng cho máy chủ này như : xử lý/lưu dữ liệu gởi từ mẫu HTML (HTML form), cung cấp dữ liệu động qua việc lấy thông tin thông qua kết nối với cơ sở dữ liệu, thực hiện giao dịch thương mại điện tử ...


2. So sánh Servlet và CGI

Khởi đầu, HTTP cung cấp một cơ chế chuẩn có tên Common Gateway Interface, viết tắt CGI (Giao diện cầu nối chung) để mở rộng máy chủ; và các văn lệnh (scripts) CGI là kỹ thuật chính để phát sinh dữ liệu động. Vì là một giao diện không phụ thuộc ngôn ngữ nên các văn lệnh CGI có thể được viết bằng nhiều ngôn ngữ thông dịch như Perl, PHP, Python ... Máy chủ gởi truy vấn (request) đến trình xử lý CGI (CGI-aware program), rồi chương trình này tạo một tiến trình (process) để gởi trả lời. Mỗi truy vấn được trả lời trong một tiến trình riêng của một hiện thể (instance) riêng của một chương trình hay văn lệnh CGI. Servlet hoạt động tương tự như kĩ thuật CGI vừa trình bày, và khắc phục những nhược điểm của kĩ thuật này như :
- servlet không chạy trong một tiến trình riêng nhằm loại bỏ trội phí (overhead) của việc tạo một tiến trình mới cho mỗi truy vấn.
- Một khi được tải vào (load), servlet sẽ vẫn nằm trong bộ nhớ để chờ những truy vấn khác từ phía khách, trong khi một chương trình CGI cần được tải mỗi khi có truy vấn.
- Với những truy vấn trùng nhau, chỉ có duy nhất một hiện thể (instance) servlet trả lời cho chúng. Điều này giúp tiết kiệm bộ nhớ và giúp servlet dễ dàng quản lý dữ liệu tồn trữ (persistent data).
- Các servlet chạy trong một bộ chứa servlet (servlet container), giúp đơn giản trong việc quản lý các truy vấn, các phiên thực thi (session), bảo mật ...

Cũng cần nói thêm là sau này có một số kỹ thuật được phát triển để cải tiến và khắc phục nhược điểm của CGI như FastCGI (thường dùng cho PHP) hay WSGI (Web Server Gateway Interface : thường dùng cho Python).

3. Vòng đời của servlet

Một servlet là một chương trình Java, cụ thể hơn, nó là một hiện thể (instance) của một lớp, lớp này hiện dựng (implement) mặt giao (interface) javax.servlet.Servlet. Nói chung, lớp này không hiện dựng trực tiếp, nhưng nó mở rộng (extend) một lớp hiện dựng của mặt giao này : javax.servlet.GenericServlet, javax.servlet.http.HttpServlet. Nói cách khác, hầu hết Servlet là lớp con của GenericServlet, HttpServlet. Ở đây, ta chỉ bàn về HTTP Servlet, do đó bàn về lớp javax.servlet.http.HttpServlet

Đến đây, ta cần nói đến bộ chứa Servlet, nó có vai trò quản lý vòng đời (life cycle) của servlet. Bộ chứa tạo servlet, triệu gọi servlet và sau cùng cho servlet nghỉ. Khi nhận được truy vấn chuyển từ máy chủ HTTP, bộ chứa servlet sẽ xem xem có servlet nào đã đăng ký (registry) cho truy vấn này hay không. Nếu có, nó sẽ chuyển truy vấn này cho servlet được tìm thấy. Nếu không, nó gởi trả truy vấn này cho máy chủ HTTP

Khi bộ chứa tìm thấy servlet ứng với truy vấn gởi đến nó sẽ thực hiện các bước sau :
1. Nếu servlet chưa được tải vào bộ chứa, tức trong bộ chứa không có hiện thể (instance) nào của servlet này, thì bộ chứa sẽ :
   + tải lớp servlet vào.
   + tạo một hiện thể của lớp servlet này.
   + khởi tạo hiện thể servlet này bằng cách gọi hàm init. Khi viết servlet, ta có thể ghi đè (override) hàm init này để khởi tạo những tài nguyên (resource) cần thiết trước khi nhận truy vấn.
2. Gọi hàm service của servlet và truyền hai đối tượng truy vấn và trả lời (request, reponse objects) vào hàm này. Hàm service, sẽ coi xem truy vấn được gửi đến tương ứng với phương thức HTTP nào để từ đó phân bổ (dispatch) truy vấn này đến phương thức xử lý tương ứng của servlet, tức các phương thức doXXX đề cập dưới đây.
Ngoài ra khi muốn loại bỏ servlet, bộ chứa sẽ gọi phương thức destroy của servlet này.

Ta có thể quyết định hỗ trợ loại truy vấn HTTP gởi từ phía khách bằng cách hiển dựng phương thức tương ứng trong Servlet. Tên phương thức (method) của Servlet có dạng doMethod(), trong đó Method là tên phương thức HTTP. Các phương thức Servlet doPost(), doGet(), doHead(), doDelete(), doHead(), doOptions(), doPut(), doTrace() lần lượt tương ứng với các phương thức HTTP POST, GET, HEAD, DELETE, HEAD, OPTIONS, PUT, TRACE.

4. Viết các phương thức doXXX

Các phương thức này luôn được truyền vào hai đối tượng HttpServletRequest (hiện dựng mặt giao ServletRequest)  và HttpServletResponse (hiện dựng mặt giao ServletResponse).

* Truy vấn HTTP
HttpServletRequest đại diện cho một truy vấn HTTP và chứa nhiều thông tin, trong đó có URL truy vấn, phần đầu HTTP, phần thân HTTP, ... Một truy vấn URL gồm các phần sau :
http://[host]:[port][request-path]?[query-string]
Ví dụ :
http://localhost:8080/Servlet/logon?username=toan&password=servlet
URL này được cấu tạo từ nhiều thành phần :
+ Local Name : tên ứng với IP của máy chủ (host name). Phương thức getLocalName() trả về thông tin này, theo ví dụ giá trị đó là "localhost"
+ Local Host : cổng mà trên đó máy chủ nhận truy vấn. Phương thức getLocalPort() trả về thông tin này theo ví dụ giá trị đó là "8080"
+ Context Path : phần gốc của ứng dụng web. Phương thức getContextPath() trả về thông tin này, theo ví dụ giá trị đó là "/Servlet" vì tôi triển khai (deploy) servlet trong phạm vi (context) này.
+ Servlet Path : trả về phần tên ta đặt để ánh xạ tới servlet. Phương thức getServletPath() trả về thông tin này, theo ví dụ giá trị đó là "/logon". Phần cấu hình ánh xạ (mapping) đường dẫn để gọi servlet có thể được thực hiện thông qua chú giải (annotation) hay tập tin cấu hình web.xml
+ Request URI : bao gồm Context Path và Servlet Path. Phương thức getRequestURI() trả về thông tin này, theo ví dụ giá trị đó là "/Servlet/logon"
+ Request URL : URL của truy vấn, tức gồm Local Name, Local Host và Request URI. Phương thức getRequestURL() trả về thông tin này, theo ví dụ giá trị đó là "http://localhost:8080/Servlet/logon"
+ Các tham số của truy vấn nằm trong query string có thể dùng phương thức getParameter để lấy các tham số này. Chẳng hạn getParameter("username") cho giá trị "toan", getParameter("password") trả về giá trị "servlet".

* Trả lời HTTP
HttpServletResponse đại diện cho một trả lời HTTP. Ta có hai cách để xây dựng trả lời :
- Dùng PrintWriter trả về từ phương thức getWriter() để gửi dữ liệu kí tự (character data) trả lời.
- Dùng ServletOutputStream trả về từ phương thức getOutputStream() để gởi dữ liệu nhị phân (binary data) trong phần thân của trả lời Multipurpose Internet Mail Extensions (MIME).

Để chỉ định rõ nội dung trả về (content type) ta dùng phương thức setContentType. Chẳng hạn setContentType("text/html") xác định nội dung trả lời là html, hoặc setContentType("application/vnd.ms-excel;charset=UTF-8") cho biết nội dung trả lời là excel được mã hoá với chuẩn "UTF-8".

Để thêm phần đầu HTTP (HTTP headers), ta dùng phương thức addHeader. Chẳng hạn addHeader("Content-Disposition", "attachment;filename=Statistiques.xls") nhằm thêm vào header "Content-Disposition : attachment;filename=Statistiques.xls". Nó đề nghị tên mặc định "Statistiques.xls" khi người dùng muốn lưu thông tin trả về dưới dạng tập tin. Khi dùng kèm với content-type "application/...", nó ngầm ý yêu cầu lưu nội dung xuống máy hơn là hiển thị nội dung này.

5. Mô-đun web

Trong kiến trúc Java EE, mô-đun web (web module) là đơn vị triển khai web nhỏ nhất. Một mô-đun web tương ứng với một ứng dụng web trong đặc tả Java Servlet và nó có một cấu trúc đặc thù như sau :

document root    [thư mục ngoài nhất của mô-đun web]
   | static & dynamic resources (html, jsp, jpg, css,...)
   + WEB-INF/
        | web.xml
       + classes/ [chứa các tập tin .class]
       + lib/        [chứa các thư viện .jar]
       + tags/     [chứa các tập tin .tag]

 Thư mục ngoài cùng nhất của một mô-đun web được gọi là thư mục gốc (document root) của ứng dụng, trong đó chứa các tài nguyên động (các trang jsp, .xhtml, ...) hay các tài nguyên tĩnh (html, css, jpg,...). Thư mục gốc này chứa một thư mục con tên WEB-INF chứa các tập tin và thư mục sau :
- web.xml : tập tin mô tả triển khai ứng dụng web (web application deployment descriptor)
- classes : thư mục chứa các tập tin .class phía server : các servlet, lớp công cụ, các JavaBeans.
- lib : thư mục chứa các thư viện (.jar) được các lớp phía server dùng.
- tags : thư mục chứa các tập tin tag, là các hiện dựng của thư viện tag

Nếu mô-đun web không chứa servlet, phần lọc (filter), thành phần nghe (listener), thì ta không cần đến tập tin mô tả triển khai ứng dụng web web.xml; hoặc khi dùng dẫn giải (annotation) để thực hiện việc ánh xạ, ta cũng không cần đến web.xml

Một mô-đun web có thể được triển khai (deploy) dưới dạng cấu trúc không đóng gói (unpacked file structure) hoặc dưới dạng đóng gói trong một tập tin JAR được biết đến với tên tập tin lưu trữ web (web archive file : WAR), có phần mở rộng là .war.

6. Một số giải pháp thay thế

- CGI : như trình bày ở trên, được dùng chủ yếu khi lập trình với các ngôn ngữ thông dịch như Perl, PHP, Python...
- PHP : ta đề cập riêng ở đây vì PHP là ngôn ngữ lập trình được sử dụng phổ biến trong việc phát triển web phía máy chủ. Nó thường được dùng trong kiến trúc LAMP (Linux, Apache, MySQL, P được hiểu là PHP nhưng cũng có thể hiểu là Perl, Python) và các gói tương tự như WAMP, MAMP, ... cho Windows hay OS X. Nhiều hệ thống quản lý nội dung web (WCMS : Web Content Management System) được viết bằng PHP như Zoomla, eZ Publish, Drupal, Moodle, WordPress ...
- ASP.NET (Active Server Pages .NET): là bộ khung phát triển web phía máy chủ để tạo trang web động do Microsoft phát triển. Nó cho phép tạo các trang web (web sites), ứng dụng web (web application) và dịch vụ web (web service) bằng các ngôn ngữ .NET như C#, VB.NET ...

1 nhận xét:

  1. Video demo đơn giản
    https://www.youtube.com/watch?v=k9kyA_zlXF0&feature=youtu.be

    Trả lờiXóa