JSP là một công nghệ cho phép thực hiện dễ dàng việc viết các trang web động (dĩ nhiên ta cũng có thể viết các trang web tĩnh với JSP). Cụ thể, một trang JSP là một trang HTML (hay XML) trong đó có trộn lẫn các mã Java, tức các thành phần JSP, cho phép thực hiện nội dung động. Các trang JSP có phần mở rộng .jsp. Một trang jsp có thể là một bao gồm nhiều tập tin, mà các tập tin này có thể là một trang jsp hoàn chỉnh hay những đoạn (fragment) của một trang jsp. Những đoạn jsp này có phần mở rộng là .jspf
Như ta đã biết, việc viết nội dung html trả lời trong servlet bằng cách dùng các lệnh out.println() là một việc tốn nhiều công sức, đặc biệt khi nội dung html trả lời càng phức tạp. Việc này còn tệ hơn khi ta muốn bảo trì hay thay đổi nội dung trả lời. JSP đem lại một giải pháp tiện lợi hơn khi cho phép chèn nội dung động vào trang web, nó còn cho phép việc tách bạch phần trình bày và logic xử lý nội dung. Với servlet thì ta chèn mã html để phát sinh trong lớp java còn JSP thì ngược lại, ta chèn mã java trong trang html.
2. Vòng đời JSP
Có thể xem JSP là một mức trừu tượng cao hơn Java servlet vì thực chất khi chạy (runtime) một trang JSP sẽ được chuyển thành một servlet. Cụ thể như sau : khi một truy vấn được ánh xạ vào một trang JSP, vì mỗi servlet của một trang JSP được trữ (cache) và được tái sử dụng lại chừng nào mà trang JSP gốc không thay đổi, bộ chứa web sẽ xem xem servlet của trang JSP đó có cũ hơn trang JSP đó không. Nếu servlet cũ hơn thì bộ chứa web sẽ dịch trang JSP ra một lớp servlet và biên dịch lớp này.
Cụ thể khi ta dùng Tomcat, các trang jsp sẽ được dịch thành các lớp servlet và được lưu trong thư mục work; và các biên dịch của chúng cũng nằm cùng thư mục.
Sau khi trang jsp được dịch (translate) và được biên dịch (compile), thì servlet của jsp này có vòng đời như được trình bày tại Vòng đời Servlet.
a. Nếu trong bộ chứa chưa có một hiện thể (instance) nào của servlet của trang jsp thì bộ chứa sẽ :
i. Tải lớp servlet của trang jsp vào
ii. Tạo một hiện thể của lớp servlet này.
iii. Khởi tạo hiện thể của lớp này bằng cách gọi hàm jspInit.
b. Bộ chứa gọi hàm _jspService, và truyền vào tham số là hai đối tượng truy vấn và trả lời.
Nếu bộ chứa muốn loại bỏ servlet của trang jsp này, nó sẽ gọi hàm jspDestroy.
Khởi tạo và kết thúc một trang JSP
Ta có thể cá nhân hoá (customize) việc khởi tạo và kết thúc một trang jsp bằng cách ghi đè (override) các hàm jspInit và jspDestroy của mặt giao javax.servlet.jsp.JspPage . Chẳng hạn khởi tạo (initialize) một tài nguyên trong hàm jspInit để dùng trong toàn bộ trang jsp, rồi giải phóng (release) tài nguyên này trong hàm jspDestroy. Việc ghi đè này ta thực hiện trong thẻ khai báo, sẽ được trình bày dưới đây.
Hàm _jspService() tương ứng với nội dung trang jsp, được tự động định nghĩa bởi trình xử lý JSP (JSP processor) và người viết trang jsp đừng bao giờ định nghĩa hàm này.
3. Các thành phần JSP
a. Chỉ thị JSP (JSP directives)
Chỉ thị JSP có dạng sau :
<%@ directive attribute=value ...%>Ví dụ :
<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.List, java.util.Date" language="java" %>
<%@ page import="java.io.IOException" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ include file="../includes/header.jspf"%>
* Chỉ thị page có nhiều tuỳ chọn, trong đó có :
- import : nhập một gói (package) java. Chỉ thị này sẽ được chuyển thành chỉ dẫn import trong servlet.
- contentType : định nghĩa loại nội dung của trang sẽ được phát sinh.
- pageEncoding : định nghĩa chuẩn mã hoá trang phát sinh sử dụng.
- language : định nghĩa ngôn ngữ sử dụng.
...
Cách khai báo khác (JSP 2.0):
<jsp:directive.page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.List, java.util.Date" language="java" />
* Chỉ thị include : chỉ định cho trình biên dịch gộp tập tin vào trang. Cách khai báo khác (JSP 2.0) bằng cách dùng hành động include (action include):
<jsp:include page="../includes/header.jspf" />Hai cách này tuy đưa lại kết quả như nhau nhưng chúng có sự khác biệt tế nhị sau :
- chỉ thị include <%@ include ...%> sẽ gộp tập tin khi trang jsp được chuyển thành servlet. Nếu tập tin được gộp không hay thay đổi thì ta nên dùng phương pháp này vì nó sẽ nhanh hơn về mặt hiệu năng (performance).
- hành động include <jsp:include ... /> sẽ thêm tập tin phát sinh vào trang jsp sau khi trang này được phát sinh. Ta nên dùng chọn lựa này nếu nội dung tập tin được gộp hay thay đổi.
Một cơ chế khác thự hiện việc gộp là việc dùng thẻ <c:import> của Thư Viện Thẻ Chuẩn JSTL (JavaServer pages Standard Tag Library)
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <c:import url="../includes/header.jspf" />
* Chỉ thị taglib : khai báo việc dùng một thư viện thẻ trong trang. Cách khai báo khác (JSP 2.0):
<jsp:root xmlns:c="http://java.sun.com/jsp/jstl/core" />
b. Có thể chèn mã Java vào trang JSP bằng cách dùng các thẻ sau:
* Thẻ khai báo (declaration) : cho phép thêm trực tiếp mã vào lớp servlet, định nghĩa các biến toàn cục hay tạo các phương thức. Ta ghi đè hai hàm jspInit và jspDestroy trong thẻ khai báo này.
<%! ResourceBundle rb; public void jspInit() { rb = ResourceBundle.getBundle("messages"); }%>hay
<jsp:declaration> ResourceBundle rb; public void jspInit() { rb = ResourceBundle.getBundle("messages"); } </jsp:declaration>
* Thẻ văn lệnh con (scriptlet) : được dùng để chèn mã vào phương thức _jspService() của servlet. Nói chung là thành phần được sử dụng để chèn mã Java ngoại trừ các biến chung và phương thức.
<% session.setAttribute("user", null); String sucessPath = rb.getString("process.logoff"); %>hay
<jsp:scriptlet> session.setAttribute("user", null); String sucessPath = rb.getString("process.logoff"); </jsp:scriptlet>
* Thẻ biểu thức (expression) : dùng để hiển thị kết quả của một biểu thức. Biểu thức này sẽ được chuyển làm tham số của một gọi hàm out.print() bên trong phương thức _jspService()
<title><%=rb.getString("logoff.title")%></title>hay
<title><jsp:expression>rb.getString("logoff.title")</jsp:expression></title>
c. Các biến ngầm:
Trong một trang jsp ta có thể sử dụng các biến khai báo sẵn sau :
- request : đối tượng javax.servlet.http.HttpServletRequest
- response : đối tượng javax.servlet.http.HttpServletResponse
- out : đối tượng javax.servlet.jsp.JspWriter
- session : đối tượng javax.servlet.http.HttpSession
- application : đối tượng javax.servlet.ServletContext
- config : đối tượng avax.servlet.ServletConfig
- pageContext : đối tượng javax.servlet.jsp.PageContext
- page : là chính servlet
d. Các hành động của JSP (JSP actions) :
- jsp:include : đã trình bày phía trên
- jsp:param : có thể được sử dụng trong jsp:include, jsp:forward, jsp:params. Nhằm xác định một thông số gởi kèm
- jsp:forward : chuyển truy vấn sang một servlet hay trang jsp khác.
<jsp:forward page="<%=sucessPath%>" />- jsp:plugin : thực thi hay hiển thị một đối tượng, đối tượng này có thể là một applet hay bean. Trong trả lời dưới dạng HTML, thì thẻ này được chuyển thành thẻ <object> hay <embed>
- jsp:fallback : nội dung hiển thị nếu phía khách không hỗ trợ applet, dùng kèm với jsp:plugin
- jsp:getProperty : lấy giá trị một thuộc tính của một JavaBean.
<jsp:getProperty property="username" name="userBean" />
- jsp:setProperty : gán giá trị cho một thuộc tính của một JavaBean.
<jsp:setProperty property="*" name="userBean" />
- jsp:useBean : khởi tạo hay tái sử dụng một JavaBean đã tồn tại để dùng trong trang jsp.
<jsp:useBean id="userBean" class="com.openspace.UserService" scope="session" />
4. Chú ý khi dùng JSP
Để phát triển các ứng dụng web dùng Servlet và JSP có chất lượng, có thể tái sử dụng và dễ dàng bảo trì ta cần lưu ý các điều sau :
- Không lạm dụng chèn nhiều mã Java trong trang HTML. Ta nên viết những tính toán, xử lý ... trong các lớp Java và ta sẽ gọi đến chúng trong trang jsp khi dùng.
- Khi lập trình dùng JSP, ta thường dùng đến mẫu thiết kế MVC (Model-View-Control : Mô hình - Mặt nhìn - Điều khiển) nên khi lập trình ta nên tách bạch 3 phần sau : phần mã trình bày (presentation) hay thiết kế (design), phần logic công việc hay dữ liệu và phần xử lý yêu cầu.
Không có nhận xét nào:
Đăng nhận xét