Professional Documents
Culture Documents
Dự án Struts được thiết kế với mục đích cung cấp một bộ khung mã nguồn mở để tạo các ứng
dụng Web, tách tầng trình bày (presentation layer) ra khỏi tầng giao tác (transaction layer) và
tầng dữ liệu (data layer). Từ khi ra đời, dự án Struts nhận được nhiều ủng hộ của các nhà phát
triển và nhanh chóng chiếm ưu thế trong cộng đồng mã nguồn mở. Quyển sách này đề cập phiên
bản 1.1 của Struts.
Một cuộc tranh luận nhỏ đã diễn ra trong cộng đồng những nhà phát triển về mẫu thiết kế mà dự
án Struts giống nhất. Theo tài liệu được cung cấp từ chính những nhà phát triển dự án Struts, nó
được thiết kế theo mẫu MVC; nhưng một số khác thì cho rằng nó giống mẫu thiết kế Front
Controller hơn (mẫu này được mô tả bởi Sun's J2EE Blueprints Program). Sự thật thì nó rất
giống mẫu Front Controller; nhưng trong quyển sách này, chúng ta thảo luận theo mẫu MVC.
Nếu muốn tìm hiểu về mẫu Front Controller, bạn có thể xem tại:
http://developer.java.sun.com/developer ... EE/despat/
View
Đóng vai trò là phần biểu diễn trên màn hình (screen representation) của thành phần Model.
Thành phần View là đối tượng trình bày trạng thái hiện tại của các đối tượng dữ liệu.
Controller
Định nghĩa cách thức giao diện người dùng tương tác lại dữ liệu đầu vào. Thành phần Controller
là đối tượng thao tác thành phần Model (hay đối tượng dữ liệu).
Dưới đây là một số lợi ích khi sử dụng mẫu thiết kế MVC:
Tính tin cậy—Tầng trình bày và tầng giao tác có sự phân chia rõ ràng, cho phép bạn thay đổi
cảm quan của ứng dụng mà không cần biên dịch lại mã lệnh của Model hay Controller.
Tính thích ứng và tái sử dụng cao—Mẫu MVC cho phép bạn sử dụng nhiều loại khung nhìn,
tất cả cùng truy xuất đến một mã nguồn phía server, từ trình duyệt web (HTTP) cho đến trình
duyệt không dây (WAP).
Các phí tổn trong vòng đời phát triển rất thấp—Mẫu MVC chỉ cần có người lập trình cấp
thấp phát triển và bảo trì các giao diện người dùng.
Triển khai nhanh chóng—Thời gian phát triển có thể được giảm đáng kể, bởi vì những người
lập trình cho thành phần Controller (nhà phát triển Java) chỉ tập trung vào phần giao tác, còn
những người lập trình cho thành phần View (nhà phát triển HTML và JSP) chỉ tập trung vào
phần trình bày.
Tính bảo trì—Việc tách phần trình bày và logic nghiệp vụ cũng khiến việc bảo trì và sửa đổi
một ứng dụng Web dựa trên Struts dễ dàng hơn.
Hình trên mô tả quy trình xử lý mà hầu hết các yêu cầu ứng dụng Struts cần tuân theo. Quy trình
này có thể được chia thành 5 bước cơ bản:
1. Một yêu cầu xuất phát từ một View đã được hiển thị trước đó.
2. Yêu cầu này được tiếp nhận bởi ActionServlet (đóng vai trò là một Controller), ActionServlet
tìm URI được yêu cầu trong một file XML (sẽ được mô tả trong chương 3, “Làm quen với
Struts”) và xác định tên lớp Action sẽ thực hiện logic nghiệp vụ cần thiết.
3. Lớp Action thực hiện logic của nó trên các thành phần Model của ứng dụng.
4. Khi đã hoàn tất quá trình xử lý, lớp Action trả quyền điều khiển cho ActionServlet, đồng thời
cung cấp một khóa (key) biểu thị các kết quả xử lý. ActionServlet sử dụng khóa này để xác định
các kết quả sẽ được chuyển đến đâu khi trình bày.
5. Yêu cầu kết thúc khi ActionServlet chuyển yêu cầu đến View được gắn với khóa trả về, và
View này trình bày các kết quả của Action.
Bạn có thể nhận ra những bước trên là một dạng biểu diễn đã được đơn giản hóa của một yêu cầu
Struts. Chúng ta sẽ đề cập chi tiết hơn về những bước này, bao gồm các thành phần khác, trong
phần tiếp theo.
Các thành phần Model của Struts Framework, như đã được giới thiệu ở phần trước, biểu diễn các
đối tượng dữ liệu của ứng dụng Struts. Chúng thường biểu diễn các đối tượng nghiệp vụ hay các
hệ thống backend khác và có thể được hiện thực là những JavaBean đơn giản, những Enterprise
JavaBean, những biểu diễn đối tượng của dữ liệu được lưu trữ trong một cơ sở dữ liệu quan hệ,
hoặc chỉ là những gì cần được thao tác hay biểu diễn trong một ứng dụng Web. Chúng ta sẽ thảo
luận chi tiết hơn về thành phần Model trong phần sau, “Tích hợp Jakarta Commons Database
Connection Pool”.
Thành phần View
Mỗi thành phần View trong Struts Framework được ánh xạ đến một trang JSP, trang này có thể
chứa bất kỳ sự kết hợp nào của các thẻ tùy biến Struts, JSP, và HTML. Các trang JSP trong Struts
Framework có hai chức năng chính. Thứ nhất, đóng vai trò là tầng trình bày của một Controller
Action đã được thực thi trước đó. Điều này thường được hoàn thành bằng cách sử dụng một tập
thẻ tùy biến để duyệt và thu lấy dữ liệu mà Controller Action chuyển đến JSP đích. Loại View
này không thể hiện đặc trưng của Struts và không được lưu tâm.
Chức năng thứ hai, thể hiện đặc trưng của Struts, là thu thập dữ liệu cần thiết để thực hiện một
Controller Action cụ thể. Điều này thường được hoàn thành bằng cách kết hợp các thư viện thẻ
Struts và các đối tượng ActionForm. Loại View này chứa một số lớp và thẻ đặc-trưng-Struts.
Đoạn mã sau là một ví dụ đơn giản về loại View này:
Code: Chọn hết
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html">
<html:form action="loginAction.do"
name="loginForm"
type="com.stock.loginForm" >
User Id: <html:text property="username"><br/>
Password: <html:password property="password"><br/>
<html:submit />
</html:form>
Chúng ta sẽ thảo luận chi tiết hơn về thành phần View trong phần sau, “Làm quen với Struts”, và
“Xây dựng tầng trình bày”.
Controller là thành phần quan trọng nhất của Struts Framework. Chúng ta sẽ thảo luận chi tiết
hơn về thành phần này trong phần sau, “Làm quen với Struts”, và “Action và ActionServlet”.
Java Servlet Specification 2.2 mô tả các ứng dụng Web Java như sau: “Một ứng dụng Web là tập
hợp các servlet, các trang HTML, các lớp, và các tài nguyên khác, chúng được đóng gói và chạy
trên nhiều container từ nhiều nhà cung cấp”. Nói một cách đơn giản hơn, một ứng dụng Web
Java là một tập hợp của một hay nhiều thành phần web được đóng gói cùng với nhau nhằm mục
đích tạo ra một ứng dụng hoàn chỉnh để được thực thi ở tầng web của một ứng dụng Enterprise.
Dưới đây là danh sách các thành phần có thể được đóng gói trong một ứng dụng Web:
- Các servlet
- Các trang JSP
- Các thư viện thẻ tùy biến JSP
- Các lớp tiện ích và các lớp ứng dụng
- Các tài liệu tĩnh, bao gồm HTML, hình ảnh, và JavaScript
- Thông tin mô tả ứng dụng Web (siêu thông tin)
/stockapp/WEB-INF/classes
Thư mục này chứa các lớp tiện ích và servlet.
/stockapp/WEB-INF/lib
Thư mục này chứa các file JAR (Java Archive) mà ứng dụng Web phụ thuộc vào đó.
Nếu bạn sử dụng Tomcat làm container, thư mục gốc mặc định là
<CATALINA_HOME>/webapps/. Hình sau cho thấy ứng dụng stockapp khi nó được host bởi
Tomcat container.
Ứng dụng web cho phép lưu trữ các lớp đã được biên dịch trong thư mục /WEB-INF/classes và
/WEB-INF/lib. Khi xử lý, các lớp trong thư mục /classes sẽ được nạp trước, sau đó đến các file
JAR trong thư mục /lib. Nếu có các lớp trùng nhau ở cả hai thư mục thì các lớp trong thư mục
/classes sẽ được ưu tiên.
Bộ mô tả triển khai dưới đây định nghĩa một servlet. Chúng ta sẽ khảo sát chi tiết hơn về file
web.xml trong các phần sau.
<web-app>
<servlet>
<servlet-name>SimpleServlet</servlet-name>
<servlet-class>com.stock.SimpleServlet</servlet-class>
</servlet>
</web-app>
Trước khi cài đặt và cấu hình Tomcat, bạn phải đảm bảo các khoản sau:
Các yêu cầu khi cài đặt Tomcat
Java SE Development Kit 5
http://java.sun.com/javase/downloads/index_jdk5.jsp
Sau khi đã cài đặt Tomcat và JDK xong, bước kế tiếp là thiết lập biến môi trường JAVA_HOME.
Thật ra, bước này không cần thiết, bạn có thể bỏ qua.
Để thiết lập biến môi trường JAVA_HOME, thực hiện như sau:
1. Mở Control Panel.
2. Mở hộp thoại System Properties, sau đó chọn thẻ Advanced.
3. Nhắp vào nút Environment Variables, bạn sẽ thấy màn hình tương tự như hình 1.3.
4. Nhắp vào nút New trong phần System variables của hộp thoại Environment Variables.
5. Thêm biến có tên là JAVA_HOME và thiết lập giá trị là đường dẫn của bản cài đặt JDK. Hình
1.4 cho thấy thiết lập ứng với bản cài đặt của chúng ta.
Tất cả đã xong, bây giờ bạn có thể qua phần kế tiếp để kiểm tra bản cài đặt Tomcat.
Thiết lập biến môi trường JAVA_HOME ứng với bản cài đặt của chúng ta
Sau khi Tomcat đã khởi động, mở trình duyệt theo địa chỉ:
http://localhost:8080
Bạn sẽ thấy trang chủ mặc định của Tomcat (xem hình dưới).
[img]Trang%20chủ%20mặc%20định%20của%20Tomcat[/img]
Bước kế tiếp là kiểm tra bản cài đặt JDK. Cách tốt nhất để thực hiện điều này là chạy thử một
trong các ví dụ do Tomcat server cung cấp. Để chạy một ví dụ JSP, từ trang chủ mặc định của
Tomcat, chọn JSP Examples. Bạn sẽ thấy trang tương tự như hình dưới.
Chọn ví dụ có tên là Snoop và nhắp vào liên kết Execute. Nếu mọi thứ được cài đặt đúng, bạn sẽ
thấy trang tương tự như hình dưới.
Một khi bạn đã nắm vững về servlet, chúng ta sẽ chuyển sang thảo luận về JSP, đóng vai trò là
thành phần View của Struts Framework. Ở đây, chúng ta định nghĩa JSP và mô tả các thành
phần của nó.
Mục đích của chương này là giới thiệu ngắn gọn về công nghệ servlet và JSP. Qua chương này,
bạn sẽ hiểu rõ về servlet và JSP, cũng như cách áp dụng chúng vào quá trình phát triển ứng
dụng Web Java.
Hai gói cấu thành nên kiến trúc servlet là javax.servlet và javax.servlet.http. Gói javax.servlet
chứa các lớp và các giao diện tổng quát, được hiện thực và kế thừa bởi tất cả các servlet. Gói
javax.servlet.http chứa tất cả các lớp servlet thể hiện đặc trưng của giao thức HTTP.
Phần cốt lõi của kiến trúc này là giao diện javax.servlet.Servlet. Đây là giao diện lớp cơ sở cho
tất cả các servlet. Giao diện Servlet định nghĩa năm phương thức, trong đó ba phương thức quan
trọng nhất là:
- Phương thức init()—khởi tạo một servlet
- Phương thức service()—nhận và đáp ứng các yêu cầu của client
- Phương thức destroy()—thực hiện dọn dẹp
Đây là các phương thức trong vòng đời của servlet. Chúng ta sẽ mô tả các phương thức này trong
phần sau. Tất cả các servlet phải hiện thực giao diện Servlet một cách trực tiếp hoặc thông qua kế
thừa. Hình 2.2 là một mô hình đối tượng, cho bạn cái nhìn mức cao về bộ khung servlet.
Hình: Một mô hình đối tượng đơn giản của bộ khung servlet
Khi kế thừa lớp GenericServlet, bạn phải hiện thực phương thức service(). Phương thức
GenericServlet.service() đã được định nghĩa là một phương thức trừu tượng cốt để buộc bạn tuân
theo bộ khung này. Nguyên mẫu của phương thức service() được định nghĩa như sau:
Code: Chọn hết
public abstract void service(ServletRequest request,
ServletResponse response) throws ServletException, IOException;
Hai tham số được truyền cho phương thức service() là đối tượng ServletRequest và
ServletResponse. Đối tượng ServletRequest chứa thông tin được gửi đến servlet, và đối tượng
ServletResponse là nơi đặt dữ liệu mà bạn muốn gửi về client.
Ngược với GenericServlet, khi kế thừa HttpServlet, bạn thường không hiện thực phương thức
service(); lớp HttpServlet đã hiện thực phương thức service() cho bạn. Nguyên mẫu sau chứa chữ
ký của phương thức HttpServlet.service():
Code: Chọn hết
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException;
Khi phương thức HttpServlet.service() được gọi, nó xét loại phương thức trong yêu cầu và xác
định các phương thức HTTP nào được gọi dựa vào giá trị này. Đây là các phương thức mà bạn có
thể chép đè. Nếu loại phương thức là GET, nó sẽ gọi phương thức doGet(). Nếu loại phương thức
là POST, nó sẽ gọi phương thức doPost(). Có năm loại phương thức đi cùng với phương thức
service(), nhưng doGet() và doPost() là hai phương thức thường được sử dụng nhất. Do đó,
chúng ta chỉ tập trung vào hai phương thức này.
1. Một servlet được nạp và khởi tạo bằng phương thức init(). Phương thức này được gọi khi một
servlet được nạp trước hoặc trong lần đầu tiên yêu cầu servlet này.
2. Sau đó, servlet sẽ phục vụ 0 hoặc nhiều yêu cầu. Servlet sử dụng phương thức service() để
phục vụ mỗi yêu cầu.
3. Sau đó, servlet bị hủy và dọn dẹp khi ứng dụng Web chứa servlet đó kết thúc. Phương thức
được gọi khi kết thúc là destroy().
Phương thức init() nhận một đối tượng ServletConfig làm tham số. Tham chiếu này nên được lưu
trữ trong một biến thành viên để có thể được sử dụng sau này. Cách thông thường để làm điều
này là cho init() gọi phương thức supper.init() và truyền đối tượng ServletConfig.
Phương thức init() cũng khai báo rằng nó có thể ném biệt lệ ServletException. Nếu vì một lý do
nào đó mà servlet không thể khởi tạo các tài nguyên cần thiết nhằm thụ lý các yêu cầu, nó sẽ
ném biệt lệ ServletException với một thông báo lỗi.
Bạn thường không hiện thực phương thức này một cách trực tiếp, trừ phi kế thừa lớp trừu tượng
GenericServlet. Bản hiện thực phổ biến nhất của phương thức service() là trong lớp HttpServlet.
Lớp này hiện thực giao diện Servlet bằng việc kế thừa lớp GenericServlet. Phương thức service()
của nó hỗ trợ các yêu cầu HTTP/1.1 chuẩn bằng cách xác định loại yêu cầu và gọi phương thức
phù hợp.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
doPost(request, response);
}
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Simple Servlet</title></head>");
out.println("<body>");
out.println("</body></html>");
out.close();
}
}
Bạn đã xem qua mã nguồn của SimpleServlet, bây giờ hãy xem kỹ hơn mỗi phần trong đó.
Chúng ta xét servlet này khớp với bộ khung Java Servlet Development Kit (JSDK) ở điểm nào,
các phương thức mà servlet hiện thực, và các đối tượng mà servlet sử dụng. Có ba phương thức
được chép đè trong SimpleServlet:
Trước hết, SimpleServlet định nghĩa một bản hiện thực đơn giản của phương thức init(). Nó nhận
đối tượng ServletConfig, rồi truyền cho phương thức init() cha để đối tượng này có thể được sử
dụng về sau. Dòng mã sau thực hiện điều này:
Code: Chọn hết
super.init(config);
Cha của SimpleServlet, thực sự nắm giữ đối tượng ServletConfig, chính là GenericServlet.
Bạn nên để ý rằng bản hiện thực này của phương thức init() không tạo ra bất cứ tài nguyên nào.
Đây là lý do khiến SimpleServlet không hiện thực phương thức destroy().
Cả hai phương thức doGet() và doPost() đều nhận đối tượng HttpServletRequest và
HttpServletResponse làm tham số. HttpServletRequest chứa thông tin được gửi từ client, và
HttpServletResponse chứa thông tin sẽ được trả về client.
Dòng mã được thực thi đầu tiên của phương thức doPost() là thiết lập loại nội dung của đáp ứng.
Điều này được thực hiện như sau:
Code: Chọn hết
response.setContentType("text/html");
Phương thức này thiết lập loại nội dung của đáp ứng. Bạn có thể thiết lập thuộc tính này chỉ một
lần, và phải được thiết lập trước khi ghi ra một Writer hay OutputStream. Trong ví dụ trên, chúng
ta thiết lập loại đáp ứng là text/html.
Việc kế tiếp chúng ta làm là thu lấy một PrintWriter. Điều này được thực hiện bằng cách gọi
phương thức getWriter() của ServletResponse. PrintWriter cho phép chúng ta ghi ra luồng đáp
ứng. Mọi thứ được ghi ra PrintWriter sẽ được hiển thị trong trình duyệt client. Bước này được
hoàn tất bằng dòng mã sau:
Code: Chọn hết
PrintWriter out = response.getWriter();
Khi đã có một tham chiếu đến đối tượng cho phép ghi văn bản đến client, chúng ta sử dụng đối
tượng này để ghi một thông điệp đến client. Thông điệp này được định dạng theo HTML, và sẽ
được trình bày trong trình duyệt client. Điều này được thực hiện bằng đoạn mã sau:
Code: Chọn hết
out.println("<html>");
out.println("<head><title>Simple Servlet</title></head>");
out.println("<body>");
out.println("</body></html>");
out.close();
SimpleServlet sử dụng một phương pháp rất đơn giản để gửi HTML đến client: truyền cho
phương thức println() của PrintWriter đoạn văn bản HTML mà chúng ta muốn đưa vào đáp ứng
và đóng luồng này lại. Có lẽ bạn quan tâm nhất đến dòng mã:
Code: Chọn hết
// Xuất địa chỉ của client
out.println("Your address is " + request.getRemoteAddr() + "\n");
Dòng mã này dựa vào thông tin nhận được từ client và gọi phương thức getRemoteAddr() của
HttpServletRequest, phương thức này trả về địa chỉ IP của client. Đối tượng HttpServletRequest
giữ nhiều thông tin đặc-trưng-giao-thức-HTTP về client. Nếu muốn tìm hiểu sâu hơn về các đối
tượng HttpServletRequest và HttpServletResponse, bạn có thể vào website của Sun:
http://java.sun.com/products/servlet/
<servlet-mapping>
<servlet-name>SimpleServlet</servlet-name>
<url-pattern>simple</url-pattern>
</servlet-mapping>
Khi đã hoàn tất các bước trên, bạn có thể thực thi SimpleServlet và xem kết quả. Để thực hiện
điều này, bạn hãy khởi động Tomcat và mở trình duyệt theo địa chỉ:
http://localhost:8080/ch02/simple
Bạn sẽ thấy kết quả tương tự như hình dưới (để ý rằng địa chỉ IP của client được định dạng theo
IPv6 trên Windows Vista, ở đây là 0:0:0:0:0:0:0:1—đối với IPv4 là 127.0.0.1).
Hình: Kết xuất của SimpleServlet (đây là IPv6)
ServletContext
Một ServletContext là một đối tượng được định nghĩa trong gói javax.servlet. Nó định nghĩa tập
hợp các phương thức được sử dụng bởi các thành phần phía server của một ứng dụng Web để
giao tiếp với Servlet container.
ServletContext thường được sử dụng làm vùng lưu trữ cho các đối tượng cần có hiệu lực với tất
cả các thành phần phía server trong một ứng dụng Web. Bạn có thể xem ServletContext như một
phân đoạn bộ nhớ dùng chung cho các ứng dụng Web. Khi một đối tượng được đặt trong
ServletContext, nó tồn tại cùng với một ứng dụng Web, trừ phi nó bị loại bỏ hay thay thế. Có bốn
phương thức được định nghĩa bởi ServletContext, chủ yếu cung cấp các chức năng của bộ nhớ
dùng chung. Bảng dưới mô tả các phương thức này.
Bảng: Các phương thức “bộ nhớ dùng chung” của ServletContext
setAttribute()
Gắn một đối tượng vào tên cho trước và lưu đối tượng này vào ServletContext hiện hành. Nếu
tên đã được sử dụng, phương thức này loại bỏ đối tượng cũ và gắn tên này vào đối tượng mới.
getAttribute()
Trả về đối tượng được tham chiếu bởi tên cho trước, hoặc trả về null nếu không có đối tượng nào
với tên này.
removeAttribute()
Loại bỏ một đối tượng với tên cho trước khỏi ServletContext.
getAttributeNames()
Trả về các chuỗi chứa tên của các đối tượng được lưu trữ trong ServletContext hiện hành.
Mối quan hệ giữa ứng dụng Web và ServletContext
ServletContext đóng vai trò là container (bộ chứa) cho một ứng dụng Web. Mỗi ứng dụng Web
chỉ có một thể hiện của ServletContext. Mối quan hệ này được quy định bởi Java Servlet
Specification và là bắt buộc đối với tất cả các Servlet container.
Để thấy được mối quan hệ này ảnh hưởng như thế nào đến các thành phần Web, chúng ta sử
dụng một servlet và một JSP. Thành phần Web đầu tiên mà chúng ta xét đến là một servlet,
servlet này lưu trữ một đối tượng trong ServletContext với mục đích làm cho đối tượng này có
hiệu lực với tất cả các thành phần phía server trong ứng dụng Web. Ví dụ 2.2 trình bày mã nguồn
của servlet:
Ví dụ: ContextServlet.java
Code: Chọn hết
package ch02;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
doPost(request, response);
}
// Nếu không có đối tượng userName thì tạo mới và thêm vào
ServletContext
if ( userName == null ) {
userName = new String("Bob Roberts");
context.setAttribute("USERNAME", userName);
}
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Context Servlet</title></head>");
out.println("<body>");
2. Khi đã có một tham chiếu đến ServletContext, nó thu lấy một tham chiếu đến đối tượng được
gắn tên USERNAME từ ServletContext bằng phương thức getAttribute():
Code: Chọn hết
String userName = (String)context.getAttribute("USERNAME");
3. Sau đó, nó kiểm tra tham chiếu trả về có hợp lệ hay không. Nếu getAttribute() trả về null thì
không một đối tượng nào được gắn tên USERNAME. Khi đó, đối tượng sẽ được tạo mới và
thêm vào ServletContext bằng phương thức setAttribute():
Code: Chọn hết
// Nếu không có đối tượng userName thì tạo mới và thêm vào
ServletContext
if ( userName == null ) {
userName = new String("Bob Roberts");
context.setAttribute("USERNAME", userName);
}
4. Sau đó, giá trị của tham chiếu này được in ra luồng xuất bằng phương thức PrintWriter.
println():
Code: Chọn hết
// Xuất giá trị hiện tại của đối tượng userName
out.println("<p>The current User is : " + userName + ".</p>");
Sau khi đã xem qua servlet này, bạn hãy hoàn tất các bước sau:
1. Biên dịch mã nguồn của ContextServlet.
2. Chép file .class vào thư mục <CATALINA_HOME>/webapps/ch02/WEB-INF/classes/ch02.
3. Thêm định nghĩa sau vào file web.xml:
Code: Chọn hết
<servlet>
<servlet-name>ContextServlet</servlet-name>
<servlet-class>ch02.ContextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ContextServlet</servlet-name>
<url-pattern>context</url-pattern>
</servlet-mapping>
JSP mà chúng ta sẽ sử dụng rất giống với servlet trên, tuy nhiên có hai điểm khác:
- Mã lệnh truy xuất ServletContext nằm trong một đoạn kịch bản JSP, sẽ được thảo luận trong
phần sau của chương này.
- Nếu không tìm thấy đối tượng nào được gắn tên USERNAME, JSP sẽ không tạo đối tượng
mới.
Phần mã lệnh còn lại thực hiện những hành động về cơ bản là giống nhau, nhưng thực hiện trong
một trang JSP. Bạn hãy xem mã nguồn JSP trong ví dụ dưới
Ví dụ: Context.jsp
Code: Chọn hết
<HTML>
<HEAD>
<TITLE>Context</TITLE>
</HEAD>
<BODY>
<%
// Thu lấy đối tượng userName từ ServletContext
String userName =
(String)application.getAttribute("USERNAME");
if ( userName == null ) {
// Không thêm mới, chỉ thông báo rằng không tìm thấy
out.println("<b>Could not find a reference to the
attribute USERNAME");
}
else {
out.println("<b>The current User is : " + userName +
"</b>");
}
%>
</BODY>
</HTML>
Trong Context.jsp, chúng ta sử dụng hai đối tượng JSP ngầm: đối tượng application tham chiếu
đến ServletContext, và đối tượng out tham chiếu đến luồng xuất. Chúng ta sẽ thảo luận chúng
trong phần sau của chương này.
Bây giờ, bạn hãy chép Context.jsp vào thư mục <CATALINA_HOME>/webapps/ch02/, khởi
động Tomcat và mở trình duyệt theo địa chỉ:
http://localhost:8080/ch02/Context.jsp
Bạn sẽ thấy trang tương tự như hình sau:
Hình: Kết quả của Context.jsp
Theo đó, Context.jsp không tìm thấy đối tượng nào được gắn tên USERNAME. Nó sẽ không thể
tìm thấy cho đến khi đối tượng này được tạo bởi ContextServlet. Để thực hiện điều này, bạn mở
trình duyệt theo địa chỉ:
http://localhost:8080/ch02/context
Bạn sẽ thấy kết quả tương tự như sau:
Sau khi thực thi servlet này, ứng dụng ch02 có một đối tượng được gắn tên USERNAME lưu
trong ServletContext. Để thấy nó ảnh hưởng như thế nào đến các thành phần Web khác trong ứng
dụng ch02, bạn hãy mở lại Context.jsp trong trình duyệt. Giờ đây, JSP có thể tìm thấy
USERNAME và in ra giá trị này.
Để loại bỏ một đối tượng khỏi ServletContext, bạn có thể khởi động lại JSP/Servlet container
hoặc sử dụng phương thức ServletContext.removeAttribute().
Trong phần này, chúng ta nghiên cứu cách thu lấy thông tin từ client của servlet. Có ba phương
thức có thể được sử dụng để thu lấy các tham số yêu cầu; đó là các phương thức getParameter(),
getParameterValues(), getParameterNames() của ServletRequest. Chữ ký của mỗi phương thức
như sau:
Code: Chọn hết
public String ServletRequest.getParameter(String name);
public String[] ServletRequest.getParameterValues(String name);
public Enumeration ServletRequest.getParameterNames();
Phương thức getParameter() trả về giá trị đơn của tham số được nêu tên (ở dạng chuỗi), hoặc trả
về null nếu tham số này không có trong yêu cầu. Bạn nên sử dụng phương thức này khi chắc
rằng yêu cầu chỉ chứa một giá trị cho tham số. Nếu tham số có nhiều giá trị, bạn nên sử dụng
phương thức getParameterValues().
Phương thức getParameterValues() trả về các giá trị của tham số được nêu tên (ở dạng mảng
chuỗi), hoặc trả về null nếu tham số này không có trong yêu cầu.
Phương thức getParameterNames() trả về tên của các tham số trong yêu cầu (ở dạng
Enumeration), hoặc trả về Enumeration rỗng nếu không có tham số nào. Phương thức này được
sử dụng làm phương thức hỗ trợ cho phương thức getParameter() và getParameterValues(). Danh
sách tên tham số có thể được duyệt qua bằng cách gọi phương thức getParameter() hay
getParameterValues() ứng với mỗi tên tham số trong danh sách đó.
Để thấy cách sử dụng các phương thức này để thu lấy dữ liệu, chúng ta hãy quan sát một servlet
phục vụ các yêu cầu POST: thu lấy các tham số gửi đến và trả về các tham số cùng giá trị của
chúng cho client. Servlet này được trình bày trong ví dụ sau:
Ví dụ: ParameterServlet.java
Code: Chọn hết
package ch02;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Parameter Servlet</title>");
out.println("</head>");
out.println("<body>");
// Duyệt qua tên của các tham số, thu lấy giá trị của các tham
số
while ( parameters.hasMoreElements() ) {
param = (String)parameters.nextElement();
out.println(param + " : " + request.getParameter(param) +
"<BR>");
}
out.println("</body></html>");
out.close();
}
}
Hành động đầu tiên được thực hiện bởi servlet này là lấy tất cả tên tham số được truyền trong
yêu cầu bằng phương thức getParameterNames(). Khi đã có danh sách này, nó thực hiện vòng
lặp while, thu lấy và in tất cả giá trị cùng với tên tham số bằng phương thức getParameter(). Bạn
có thể gọi ParameterServlet bằng cách mã hóa chuỗi URL với các tham số và giá trị, hoặc sử
dụng HTML form.
Ví dụ: Form.html
Code: Chọn hết
<HTML>
<HEAD>
<TITLE>Parameter Servlet Form</TITLE>
</HEAD>
<BODY>
<form action="parameter" method=POST>
<table width="400" border="0" cellspacing="0">
<tr>
<td>Name: </td>
<td>
<input type="text" name="name" size="20"
maxlength="20">
</td>
<td>SSN:</td>
<td>
<input type="text" name="ssn" size="11"
maxlength="11">
</td>
</tr>
<tr>
<td>Age:</td>
<td>
<input type="text" name="age" size="3"
maxlength="3">
</td>
<td>email:</td>
<td>
<input type="text" name="email" size="30"
maxlength="30">
</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td>
<input type="submit" name="Submit"
value="Submit">
<input type="reset" name="Reset" value="Reset">
</td>
</tr>
</table>
</FORM>
</BODY>
</HTML>
Tài liệu HTML này chứa một HTML form đơn giản, có thể được sử dụng để truyền dữ liệu cho
ParameterServlet. Để xem ví dụ này hoạt động thế nào, bạn hãy thực hiện các bước sau:
1. Biên dịch mã nguồn của ParameterServlet.
2. Chép file .class vào thư mục <CATALINA_HOME>/webapps/ch02/WEB-INF/classes/ch02.
3. Thêm định nghĩa sau vào file web.xml:
Code: Chọn hết
<servlet>
<servlet-name>ParameterServlet</servlet-name>
<servlet-class>ch02.ParameterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ParameterServlet</servlet-name>
<url-pattern>parameter</url-pattern>
</servlet-mapping>
Nhập dữ liệu vào form và nhắp nút Submit (xem hình dưới). Tất nhiên, đáp ứng mà bạn nhận
được tùy theo dữ liệu nhập vào, nhưng nó cũng gần giống như hình dưới
<Hết phần con Kiến trúc Java servlet, phần con tiếp theo là JavaServer Page>
Đọc bài tut này có 3 điểm còn mập mờ, nêu lên để mọi người cùng trao đổi :
1.Sự khác nhau giữa Servlet và Jsp. Tại sao người ta lại mở rộng Servlet thành jsp?
2.Sự khác nhau giữa 2 phuơng thức POST và GET trong thẻ <form>
3.Ví dụ trong bài viết chưa Demo rõ được chức năng của ServletContext.Phần lớn người ta hay
dùng HttpRequest và HttpResponse để lấy và thiết lập giá trị được gửi tới từ Client, em thấy rất
ít dùng ServletContext, có lẽ là do trong các ứng dụng nhỏ thì chưa đụng tới nó chăng
http://uit.edu.vn
Re: Tìm hiểu Java Struts
loga wrote:2.Sự khác nhau giữa 2 phuơng thức POST và GET trong thẻ <form>
method="POST" action="do sth" : gửi dữ liệu của các thẻ input đến Server xử lý
method=GET action="do sth" : Nhận dữ liệu trả về từ Server sau khi Server đã xử lý xong
method="POST" action="do sth" : gửi dữ liệu của các thẻ input đến Server xử lý
method=GET action="do sth" : Nhận dữ liệu trả về từ Server sau khi Server đã xử lý xong
Vdu:
<form action="xuly" method="get"> với lại <form action="xuly" method="post">
loga wrote:Đọc bài tut này có 3 điểm còn mập mờ, nêu lên để mọi người cùng trao đổi :
1.Sự khác nhau giữa Servlet và Jsp. Tại sao người ta lại mở rộng Servlet thành jsp?
2.Sự khác nhau giữa 2 phuơng thức POST và GET trong thẻ <form>
3.Ví dụ trong bài viết chưa Demo rõ được chức năng của ServletContext.Phần lớn người ta hay
dùng HttpRequest và HttpResponse để lấy và thiết lập giá trị được gửi tới từ Client, em thấy rất
ít dùng ServletContext, có lẽ là do trong các ứng dụng nhỏ thì chưa đụng tới nó chăng
1. jsp là file của java, Servlet là gói thư viện cho jsp, không phải là mở rộng servlet thành jsp
2. method GET sẽ cho các tham số xuất hiện trên URL, trong khi method POST các dữ liệu đính
kèm hidden so với user.
Method GET có kích thước nhỏ, không mang tính bảo mật, chỉ chấp nhận tham số dạng chuỗi
(do các tham số này xuất hiện trên URL)
Method POST có kích thước lớn, được qui định trong configuration của web server, và không
giới hạn về kiểu dữ liệu
3. ServletContext là object hỗ trợ bởi gói thư viện Servlet, còn HttpRequest, HttpResponse là
object của java jsp. Trong ServletContext nó vẫn sử dụng HttpRequest để lấy dữ liệu.
1. jsp là file của java, Servlet là gói thư viện cho jsp, không phải là mở rộng servlet thành jsp
2. method GET sẽ cho các tham số xuất hiện trên URL, trong khi method POST các dữ liệu đính
kèm hidden so với user.
Method GET có kích thước nhỏ, không mang tính bảo mật, chỉ chấp nhận tham số dạng chuỗi
(do các tham số này xuất hiện trên URL)
Method POST có kích thước lớn, được qui định trong configuration của web server, và không
giới hạn về kiểu dữ liệu
3. ServletContext là object hỗ trợ bởi gói thư viện Servlet, còn HttpRequest, HttpResponse là
object của java jsp. Trong ServletContext nó vẫn sử dụng HttpRequest để lấy dữ liệu.
loga wrote:mình có câu hỏi thế này: khi nào thì dùng GET và khi nào dùng POST
Câu hỏi này khó có thể trả lời hết loga ạ, đặt vào một trường hợp cụ thể ta mới có thể biết chính
xác nên dùng gì. Nnhư mình đã nói ở trên, những data có kích thước nhỏ, ở dạng chuỗi, không
cần che dấu user, có thể dùng GET
nếu không thì dùng POST
Thông thường data từ form thì dùng POST
Khi ta cần một URL ngắn gọn dễ nhớ cho user thì dùng GET (đây là 1 điểm lợi của GET so với
POST), ví dụ
Khi tôi cần chia xẻ bài viết "Tìm hiểu Java Struts" này cho bạn bè thì tôi chỉ cần past cho họ
đường link viewtopic.php?f=23&t=1403
vì page "_http://codeprovn.com/forums/viewtopic.php" của tôi đã chấp nhận và xử lý GET
message
nếu page đó chỉ nhận POST message thì mọi bài viết chỉ có 1 đường link duy nhất là
"_http://codeprovn.com/forums/viewtopic.php", và trong đó chỉ có một cái form chứa 1 textbox
cho người dùng chọn tên hoặc id bài viết
đó là cái được của GET
Em xin bổ sung sự khác nhau về POST vs GET mà em đọc được trong cuốn introduction to java
programing theo cách hiểu của em
Em post 1 bài mới luôn, và đây là link tới bài viết để mọi người cùng trao đổi
Tài liệu này giống như các tài liệu HTML khác, cùng với các thẻ chứa mã Java được thêm vào.
Mã nguồn được lưu trong file hello.jsp và được đặt vào thư mục tài liệu của ứng dụng Web (JSP
sẽ được triển khai vào đó). Khi một yêu cầu được tạo ra cho tài liệu này, server nhận dạng phần
mở rộng .jsp và thấy rằng cần xử lý đặc biệt. Sau đó, JSP được truyền đến bộ máy JSP (chỉ là
một servlet khác được ánh xạ đến phần mở rộng .jsp) để xử lý.
Khi file JSP được yêu cầu lần đầu tiên, nó được dịch thành một servlet, sau đó được biên dịch
thành một đối tượng và được nạp vào bộ nhớ. Servlet đó sẽ phục vụ yêu cầu và trả kết quả về
cho client. Với tất cả các yêu cầu về sau, server kiểm tra xem file JSP gốc có bị thay đổi hay
không. Nếu không thay đổi, server sẽ gọi đối tượng servlet đã được biên dịch trước đó. Nếu bị
thay đổi, bộ máy JSP sẽ phân tích lại mã nguồn JSP này. Hình dưới mô tả các bước của một yêu
cầu JSP:
Hình: Các bước của một yêu cầu JSP
Bạn nên nhớ rằng JSP là servlet được tạo ra từ sự kết hợp HTML và mã Java. Vì thế, chúng có
các tài nguyên và chức năng của một servlet.
Các chỉ thị JSP là các phần tử JSP cung cấp thông tin toàn cục về một trang JSP. Ví dụ, một chỉ
thị gồm một danh sách các lớp Java được import vào một trang JSP. Cú pháp của một chỉ thị JSP
như sau:
Code: Chọn hết
<%@ directive {attribute="value"} %>
Các chỉ thị được định nghĩa bởi JSP Specification v1.2 bao gồm: page, include, và taglib.
Chỉ thị page
Chỉ thị page định nghĩa thông tin sẽ ảnh hưởng đến toàn bộ trang JSP chứa chỉ thị này. Cú pháp
của một chỉ thị page như sau:
Code: Chọn hết
<%@ page {attribute="value"} %>
Bảng dưới định nghĩa các đặc tính của chỉ thị page.
language="scriptingLanguage"
Báo cho server biết ngôn ngữ nào sẽ được sử dụng để biên dịch file JSP này. Hiện tại Java là
ngôn ngữ duy nhất được hỗ trợ, nhưng chúng ta hy vọng trong tương lai sẽ có thêm những ngôn
ngữ khác.
extends="className"
Định nghĩa lớp cha mà JSP này sẽ kế thừa. Mặc dù bạn có thể kế thừa từ các servlet khác,
nhưng điều này sẽ hạn chế khả năng thực hiện tối ưu hóa của bộ máy JSP/Servlet, và vì thế,
không được khuyến khích.
import="importList"
Định nghĩa danh sách các gói Java sẽ được import vào JSP này (tên của các gói được phân
cách bởi dấu phẩy).
session="true | false"
Xác định dữ liệu phiên làm việc có hiệu lực với trang JSP này hay không. Mặc định là true. Nếu
không có ý sử dụng phiên làm việc trong trang JSP, bạn nên thiết lập đặc tính này là false để có
hiệu năng tốt hơn.
autoFlush="true | false"
Xác định vùng đệm của luồng xuất sẽ được flush một cách tự động hay sẽ ném một biệt lệ khi
vùng đệm đầy. Mặc định là true.
isThreadSafe="true | false"
Báo với bộ máy JSP rằng trang JSP này có thể phục vụ nhiều yêu cầu cùng một lúc. Mặc định là
true. Nếu đặc tính này được thiết lập là false, SingleThreadModel sẽ được sử dụng.
info="text"
Mô tả thông tin về trang JSP này, có thể được truy xuất bằng phương thức
Servlet.getServletInfo().
errorPage="error_url"
Mô tả địa chỉ tương đối của trang JSP sẽ thụ lý các biệt lệ JSP.
isErrorPage="true | false"
Cho biết trang JSP này có phải là một trang lỗi hay không. Mặc định là false.
contentType="ctinfo"
Mô tả loại MIME và bộ ký tự của đáp ứng.
Bởi tất cả các đặc tính bắt buộc đã được ngầm định, bạn không cần thiết phải chỉ định bất cứ chỉ
thị page nào.
Các đặc tính của chỉ thị taglib được mô tả trong bảng dưới
prefix
Tiền tố được sử dụng để phân biệt thư viện thẻ tùy biến.
Để hiểu rõ hơn về khai báo, chúng ta hãy lấy khai báo biến ở trên nhúng vào một tài liệu JSP:
Code: Chọn hết
<HTML>
<BODY>
<%! String name = new String("BOB"); %>
</BODY>
</HTML>
Khi tài liệu này được nạp lần đầu tiên, mã JSP được chuyển thành mã servlet và khai báo name
sẽ được đặt trong phần khai báo của servlet. Giờ đây, nó có hiệu lực với tất cả các thành phần
JSP khác trong trang JSP.
Chú ý rằng, tất cả các khai báo JSP được định nghĩa ở cấp độ lớp, trong servlet được sinh từ
trang JSP, và do đó, được đánh giá trước các biểu thức và đoạn kịch bản JSP.
Khi mã kịch bản JSP được chuyển sang mã servlet, nó được đặt trong phương thức service() của
servlet. Đoạn mã sau là một JSP đơn giản, nó sử dụng một phần tử kịch bản để in câu “Hello
Bob” ra trình duyệt client:
Code: Chọn hết
<HTML>
<BODY>
<% out.println("Hello Bob"); %>
</BODY>
</HTML>
Mặc dù mã kịch bản JSP có thể rất mạnh, nhưng soạn tất cả logic JSP bằng mã kịch bản có thể
khiến ứng dụng của bạn khó quản lý. Vấn đề này dẫn đến sự ra đời của các thư viện thẻ tùy biến.
Lỗi thường xảy ra nhất là lỗi thực thi (runtime error), chúng có thể phát sinh trong phần thân của
trang JSP hoặc trong đối tượng nào đó được gọi từ phần thân của trang JSP. Các lỗi trong lúc yêu
cầu, dẫn đến một biệt lệ bị ném, có thể được bắt và thụ lý trong phần thân của trang JSP, báo hiệu
đã hết lỗi. Các biệt lệ không được thụ lý trong trang JSP sẽ chuyển yêu cầu của client, bao gồm
biệt lệ chưa được bắt, đến một trang lỗi được chỉ định bởi trang JSP có lỗi.
Dòng mã JSP thứ nhất báo với bộ máy JSP rằng đây là trang lỗi.
Code: Chọn hết
<%@ page isErrorPage="true" %>
Dòng mã JSP thứ hai sử dụng đối tượng ngầm exception để xuất thông điệp lỗi chứa trong biệt lệ
bị ném.
Sử dụng một trang lỗi JSP
Để xem một trang lỗi làm việc thế nào, chúng ta hãy tạo một trang JSP sao cho trang này ném
một biệt lệ chưa được bắt. Trang JSP dưới đây sử dụng trang lỗi được tạo ở trên:
<%
if ( true ) {
// Chỉ ném một biệt lệ
throw new Exception("An uncaught Exception");
}
%>
Dòng đầu tiên trong đoạn mã này thiết lập đặc tính errorPage của chỉ thị page là errorpage.jsp,
đây là tên của trang lỗi. Phần mã còn lại ném một biệt lệ (biệt lệ này sẽ không được bắt).
Để xem ví dụ này hoạt động thế nào, chép các trang JSP vào thư mục <CATALINA_HOME>/
webapps/ch02/ và mở trình duyệt theo địa chỉ:
Đối tượng out đại diện cho một JspWriter (được dẫn xuất từ java.io.Writer), cung cấp một luồng
chảy về client. Phương thức phổ biến nhất của đối tượng này là out.println(), dùng để in văn bản
sẽ được hiển thị trong trình duyệt của client. Dưới đây là một ví dụ sử dụng đối tượng out:
<html>
<head>
<title>Use Out</title>
</head>
<body>
<%
// In một thông điệp đơn giản bằng đối tượng out
out.println("<center><b>Hello Reader!</b></center>");
%>
</body>
</html>
request
Đối tượng request đại diện cho javax.servlet.http.HttpServletRequest, được kết hợp với mỗi yêu
cầu HTTP. Đối tượng này thường được sử dụng để truy xuất các tham số của yêu cầu. Bạn có thể
thực hiện điều này bằng cách gọi phương thức getParameter() với tên tham số cần tìm. Nó sẽ trả
về chuỗi chứa giá trị của tham số đó. Dưới đây là một ví dụ sử dụng đối tượng request:
<html>
<head>
<title>UseRequest</title>
</head>
<body>
<%
out.println("<b>Welcome: " +
request.getParameter("user") + ''</b>");
%>
</body>
</html>
Trang JSP này gọi phương thức request.getParameter(), truyền cho nó tham số user. Phương thức
này tìm khóa user trong danh sách tham số và trả về giá trị nếu tìm thấy.
(còn tiếp)
response
Đối tượng response đại diện cho javax.servlet.http.HttpServletResponse, được sử dụng để truyền
dữ liệu về client. Tuy vậy, API (giao diện lập trình ứng dụng JSP) đã cung cấp chức năng truy
xuất luồng xuất với đối tượng out (đã được mô tả ở trên).
pageContext
Đối tượng pageContext cung cấp chức năng truy xuất đến các không gian tên kết giao với một
trang JSP. Nó cũng cho phép truy xuất đến các đối tượng ngầm JSP khác. Đối tượng pageContext
thường được sử dụng để thiết lập và thu lấy các đối tượng (với phương thức setAttribute() và
getAttribute()).
session
Đối tượng session đại diện cho javax.servlet.http.HttpSession, được sử dụng để lưu trữ các đối
tượng giữa các yêu cầu của client. Do vậy, nó cung cấp một dạng tương tác HTTP có trạng thái
(stateful). Dưới đây là một ví dụ sử dụng đối tượng session:
<html>
<head>
<title>Session Example</title>
</head>
<body>
<%
// Thu lấy đối tượng count từ HttpSession
Integer count = (Integer)session.getAttribute("COUNT");
if ( count == null ) {
// Nếu không tìm thấy đối tượng count thì tạo mới
count = new Integer(1);
// và đưa nó vào HttpSession
session.setAttribute("COUNT", count);
}
else {
Để xem ví dụ này hoạt động thế nào, chép session.jsp vào thư mục <CATALINA_HOME>/ch02/
và mở trình duyệt theo địa chỉ:
Nhắp vào nút Refresh vài lần để thấy biến count tăng dần. Hình dưới là kết quả của session.jsp.
Hình Kết quả của session.jsp
application
Đối tượng application đại diện cho javax.servlet.ServletContext (đã được thảo luận ở phần trước
của chương này). Đối tượng này thường được sử dụng để truy xuất các đối tượng được lưu trữ
trong ServletContext (được dùng chung giữa các thành phần Web ở tầm vực toàn cục). Đây là
nơi tốt nhất để chia sẻ các đối tượng giữa các trang JSP và servlet.
config
Đối tượng config giữ một tham chiếu đến ServletConfig, chứa thông tin cấu hình về bộ máy
JSP/Servlet (trang JSP thuộc về một ứng dụng Web nằm trong bộ máy này).
page
Đối tượng page chứa một tham chiếu đến thể hiện hiện hành của trang JSP đang được truy xuất.
Đối tượng page được sử dụng giống như đối tượng this—tham chiếu đến thể hiện hiện hành của
servlet đại diện cho JSP này.
exception
Đối tượng exception cho phép truy xuất đến một biệt lệ chưa được bắt (biệt lệ này bị ném bởi
một trang JSP). Nó có hiệu lực chỉ trong các trang JSP với một trang trong đó có đặc tính
isErrorPage là true.
Các hành động chuẩn của JSP được định nghĩa trước trong các thẻ tùy biến. Có hai loại hành
động chuẩn: loại thứ nhất liên quan đến chức năng JavaBean, loại thứ hai bao gồm tất cả các
hành động chuẩn khác. Chúng ta sẽ định nghĩa và sử dụng mỗi loại trong các phần sau.
Có ba hành động chuẩn liên quan đến việc sử dụng JavaBean: <jsp:useBean>, <jsp:setProperty>,
và <jsp:getProperty>. Sau khi định nghĩa các thẻ này, chúng ta sẽ tạo một ví dụ đơn giản.
<jsp:useBean>
Hành động chuẩn <jsp:useBean> tạo ra hoặc tìm kiếm một thể hiện của JavaBean với ID và tầm
vực cho trước. Bảng 2.4 mô tả các đặc tính của hành động <jsp:useBean>, và bảng 2.5 định
nghĩa các giá trị tầm vực. Hành động <jsp:useBean> rất linh hoạt. Khi một hành động
<jsp:useBean> xảy đến, nó sẽ tìm một đối tượng với ID và tầm vực như thế. Nếu không tìm thấy,
nó sẽ tạo một đối tượng với ID đó và lưu đối tượng này vào tầm vực tương ứng. Cú pháp của
hành động <jsp:useBean> như sau:
Code: Chọn hết
<jsp:useBean id="name" scope="page|request|session|application"
typeSpec>body</jsp:useBean>
typeSpec ::=class="className" |
class="className" type="typeName" |
type="typeName" class="className" |
beanName="beanName" type="typeName" |
type="typeName" beanName="beanName" |
type="typeName"
id
Khóa kết giao với một thể hiện của đối tượng trong tầm vực được chỉ định. Khóa này có phân
biệt chữ hoa thường. Đặc tính id được sử dụng trong phương thức page.getAttribute().
scope
Tầm vực của đối tượng được tham chiếu. Tầm vực này có thể là: page, request, session, hay
application.
class
Tên đầy đủ của lớp định nghĩa bản hiện thực của đối tượng. Tên lớp có phân biệt chữ hoa
thường.
beanName
Tên của JavaBean.
type
Kiểu biến kịch bản được định nghĩa. Nếu đặc tính này không được chỉ định thì giá trị của nó
giống như giá trị của đặc tính class.
Bảng Các giá trị tầm vực (scope) của hành động chuẩn <jsp:useBean>
page
Các bean với tầm vực page chỉ được truy xuất trong trang mà chúng được tạo ra. Tất cả các
tham chiếu đến một đối tượng với tầm vực page sẽ được giải phóng khi trang JSP hiện hành đã
hoàn tất việc đánh giá.
request
Các bean với tầm vực request chỉ được truy xuất trong các trang phục vụ cho yêu cầu mà đối
tượng đã được tạo trong đó. Tất cả các tham chiếu đến đối tượng sẽ được giải phóng khi yêu
cầu đã hoàn tất.
session
Các bean với tầm vực session chỉ được truy xuất trong các trang đang xử lý các yêu cầu trong
cùng một phiên làm việc. Tất cả các tham chiếu đến các bean với tầm vực session sẽ được giải
phóng khi phiên làm việc của chúng hết hiệu lực.
application
Các bean với tầm vực application chỉ được truy xuất trong các trang xử lý các yêu cầu trong
cùng một ứng dụng Web. Tất cả các tham chiếu đến các bean với tầm vực application sẽ được
giải phóng khi JSP/Servlet container bị đóng.
<jsp:setProperty>
Hành động chuẩn <jsp:setProperty> thiết lập giá trị cho một thuộc tính của bean. Đặc tính name
của nó biểu diễn một đối tượng đã được định nghĩa trong tầm vực nào đó. Cú pháp của hành
động <jsp:setProperty> như sau:
Code: Chọn hết
<jsp:setProperty name="beanName" propexpr />
Trong cú pháp trên, đặc tính name biểu diễn tên của bean (bạn cần thiết lập thuộc tính của bean
đó), và propexpr có thể là một trong các biểu thức sau:
Code: Chọn hết
property="*" |
property="propertyName" |
property="propertyName" param="parameterName" |
property="propertyName" value="propertyValue"
name
Tên của thể hiện bean được định nghĩa bởi một hành động <jsp:useBean> hay hành động nào
đó khác.
property
Thuộc tính mà bạn muốn thiết lập giá trị. Nếu bạn thiết lập propertyName là dấu * thì hành
động sẽ duyệt qua các tham số của ServletRequest hiện hành, so trùng tên tham số (cùng kiểu
giá trị) với tên thuộc tính (cùng kiểu phương thức thiết lập thuộc tính), và gán giá trị của tham
số vào mỗi thuộc tính trùng khớp. Nếu một tham số có giá trị là chuỗi rỗng thì thuộc tính tương
ứng sẽ giữ nguyên.
param
Tên của tham số yêu cầu, giá trị của tham số này sẽ là giá trị của thuộc tính. Hành động
<jsp:setProperty> không thể chứa đồng thời đặc tính param và value.
value
Giá trị được gán cho thuộc tính.
<jsp:getProperty>
Hành động chuẩn cuối cùng liên quan đến việc tích hợp JavaBean vào JSP là <jsp:getProperty>.
Nó lấy giá trị thuộc tính của thể hiện bean được tham chiếu, chuyển thành java.lang.String và đặt
vào luồng xuất. Thể hiện bean phải được định nghĩa trong tầm vực nào đó trước khi hành động
này có thể được sử dụng. Cú pháp của hành động <jsp:getProperty> như sau:
Code: Chọn hết
<jsp:getProperty name="name" property="propertyName" />
name
Tên của thể hiện bean được định nghĩa bởi một hành động <jsp:useBean> hay hành động nào
đó khác.
property
Thuộc tính mà bạn muốn lấy giá trị.
Để biết cách sử dụng các hành động chuẩn JavaBean, chúng ta sẽ tạo một ví dụ. Ví dụ này sử
dụng một JavaBean đơn giản, đóng vai trò là một bộ đếm. Bean Counter có thuộc tính count
(kiểu int) chứa số lần thuộc tính này được truy xuất. Bean này cũng có các phương thức lấy và
thiết lập giá trị cho thuộc tính count. Dưới đây là mã nguồn của bean Counter:
Ví dụ Counter.java
Code: Chọn hết
package ch02;
int count = 0;
public Counter() {
}
public int getCount() {
count++;
return count;
}
Chúng ta sẽ tích hợp JavaBean này vào một trang JSP bằng cách sử dụng các hành động chuẩn
JavaBean. Dưới đây là trang JSP sử dụng bean Counter:
<HTML>
<HEAD>
<TITLE>Bean Example</TITLE>
</HEAD>
<BODY>
<!-- Tạo một thể hiện của Counter với id là "counter" -->
<jsp:useBean id="counter" scope="session" class="ch02.Counter"
/>
<%
// Xuất giá trị hiện tại của thuộc tính count
out.println("Count from scriptlet code : "
+ counter.getCount() + "<BR>");
%>
<!-- Thu lấy thuộc tính count của bean, -->
<!-- sử dụng hành động jsp:getProperty -->
Count from jsp:getProperty :
<jsp:getProperty name="counter" property="count" /><BR>
</BODY>
</HTML>
Trang counter.jsp có bốn thành phần JSP. Thành phần thứ nhất báo với JSP container rằng ngôn
ngữ kịch bản là Java:
Code: Chọn hết
<%@ page language="java" %>
Bước tiếp theo sử dụng hành động chuẩn <jsp:useBean> để tạo một thể hiện của lớp Counter với
tầm vực là session và ID là counter. Giờ đây, bạn có thể tham chiếu bean này bằng tên counter
trong suốt phần còn lại của trang JSP. Dòng mã tạo bean như sau:
Code: Chọn hết
<jsp:useBean id="counter" scope="session" class="ch02.Counter" />
Hai hành động cuối cùng trình bày cách lấy giá trị hiện hành của một thuộc tính. Hành động thứ
nhất sử dụng một đoạn kịch bản để truy xuất thuộc tính. Nó truy xuất bean thông qua ID
(counter) và gọi phương thức getCount(). Đoạn kịch bản như sau:
Code: Chọn hết
<%
// Xuất giá trị hiện tại của thuộc tính count
out.println("Count from scriptlet code : "
+ counter.getCount() + "<BR>");
%>
Hành động thứ hai sử dụng hành động chuẩn <jsp:getProperty> với ID của bean và thuộc tính
cần được truy xuất. Hành động này sẽ gọi phương thức truy xuất thích hợp và nhúng kết quả vào
trang HTML:
Code: Chọn hết
<!-- Thu lấy thuộc tính count của bean -->
<!-- sử dụng hành động jsp:getProperty -->
Count from jsp:getProperty :
<jsp:getProperty name="counter" property="count" /><BR>
Khi bạn thực thi counter.jsp, tham chiếu thứ hai đến thuộc tính count cho kết quả lớn hơn 1 so
với tham chiếu thứ nhất. Đó là vì cả hai đều truy xuất đến thuộc tính count, khiến phương thức
getCount() được gọi, và phương thức này làm tăng giá trị của count.
Để xem trang JSP này hoạt động thế nào, bạn hãy biên dịch lớp Counter, chuyển nó vào thư mục
<CATALINA_HOME>/ch02/WEB-INF/classes/ch02/, và chép file counter.jsp vào thư mục
<CATALINA_HOME>/ch02/. Sau đó, mở trình duyệt theo địa chỉ:
(Còn tiếp)
Các hành động chuẩn còn lại được sử dụng cho các tác vụ chung, từ hành động tham số đến hành
động plug-in. Các hành động này sẽ được mô tả trong các phần tiếp theo.
<jsp:param>
Hành động <jsp:param> cung cấp tham số và giá trị cho các hành động JSP chuẩn:
<jsp:include>, <jsp:forward>, và <jsp:plugin>. Cú pháp của hành động <jsp:param> như sau:
Code: Chọn hết
<jsp:param name="name" value="value"/>
value
Giá trị của tham số.
<jsp:include>
Hành động chuẩn <jsp:include> cung cấp một phương cách đưa thêm các thành phần Web tĩnh
và động vào trang JSP. Cú pháp của hành động <jsp:include> như sau:
Code: Chọn hết
<jsp:include page="urlSpec" flush="true">
<jsp:param ... />
</jsp:include>
Một điều quan trọng cần lưu tâm là sự khác biệt giữa chỉ thị include và hành động chuẩn
<jsp:include>. Chỉ thị include chỉ được đánh giá một lần duy nhất lúc dịch, trong khi hành động
chuẩn <jsp:include> được đánh giá với mọi yêu cầu.
Ví dụ include.jsp
Code: Chọn hết
<html>
<head>
<title>Include Example</title>
</head>
<body>
<table width="100%" cellspacing="0">
<tr>
<td align="left">
<jsp:include page="header.jsp" flush="true">
<jsp:param name="user"
value='<%= request.getParameter("user") %>' />
</jsp:include>
</td>
</tr>
</table>
</body>
</html>
Ví dụ header.jsp
Code: Chọn hết
<%
out.println("<b>Welcome: </b>" + request.getParameter("user"));
%>
Hành động <jsp:include> trong trang include.jsp sẽ đưa kết quả của việc đánh giá header.jsp vào
include.jsp. Trang header.jsp tìm một tham số với tên là user và in ra lời chào.
Để xem ví dụ này hoạt động thế này, bạn hãy chép hai file JSP trên vào thư mục
<CATALINA_HOME>/webapps/ch02/ và mở trình duyệt theo địa chỉ:
http://localhost:8080/ch02/include.jsp?user=Bob
<jsp:forward>
Hành động chuẩn <jsp:forward> cho phép bộ máy JSP gửi yêu cầu hiện hành đến một tài nguyên
khác đang tồn tại trong ứng dụng Web hiện hành, bao gồm các tài nguyên tĩnh, servlet, hay JSP.
Sự hiện diện của <jsp:forward> thực sự chấm dứt quá trình thực thi của trang JSP hiện hành.
Một hành động <jsp:forward> có thể chứa các đặc tính con <jsp:param>. Các đặc tính con này
đóng vai trò là các tham số được chuyển đến tài nguyên đích.
Cú pháp của hành động <jsp:forward> như sau:
Code: Chọn hết
<jsp:forward page="relativeURL">
<jsp:param .../>
</jsp:forward>
Ví dụ dưới là một trang JSP sử dụng hành động <jsp:forward>. Ví dụ này kiểm tra một tham số
yêu cầu và chuyển yêu cầu đến một trong hai trang JSP khác dựa vào giá trị của tham số.
Ví dụ forward.jsp
Code: Chọn hết
<html>
<head>
<title>JSP Forward Example</title>
</head>
<body>
<%
if ( (request.getParameter("role")).equals("manager") ) {
%>
<jsp:forward page="management.jsp" />
<%
}
else {
%>
<jsp:forward page="welcome.jsp">
<jsp:param name="user"
value='<%=request.getParameter("user") %>' />
</jsp:forward>
<%
}
%>
</body>
</html>
Trang forward.jsp kiểm tra tham số role và chuyển yêu cầu, cùng các tham số yêu cầu, đến trang
JSP phù hợp dựa vào giá trị này. 2 ví dụ dưới là các tài nguyên đích.
Ví dụ welcome.jsp
Code: Chọn hết
<!-- Thiết lập ngôn ngữ kịch bản là Java -->
<%@ page language="java" %>
<HTML>
<HEAD>
<TITLE>Welcome Home</TITLE>
</HEAD>
<BODY>
<table>
<tr>
<td>
Welcome User: <%= request.getParameter("user") %>
</td>
</tr>
</table>
...
Ví dụ management.jsp
Code: Chọn hết
<!-- Thiết lập ngôn ngữ kịch bản là Java -->
<%@ page language="java" %>
<HTML>
<HEAD>
<TITLE>Management Console</TITLE>
</HEAD>
<BODY>
<table>
<tr>
<td>
Welcome Manager: <%= request.getParameter("user") %>
</td>
</tr>
</table>
...
Để xem kết quả, bạn chép ba file JSP trên vào thư mục <CATALINA_HOME>/webapps/ch02/
và mở trình duyệt theo địa chỉ:
http://localhost:8080/ch02/forward.jsp? ... r&user=Bob
Bạn cũng có thể đổi giá trị của tham số role là manager để đổi trang đích.
<jsp:plugin>
Hành động chuẩn cuối cùng mà chúng ta thảo luận là <jsp:plugin>. Hành động này cho phép bạn
sinh mã HTML cần thiết, sử dụng các cấu trúc độc-lập-trình-duyệt phù hợp, dẫn đến việc thực thi
thành phần JavaBean hay applet được chỉ định.
Khi đã được đánh giá, thẻ <jsp:plugin> được thay bằng thẻ <object> hay thẻ <embed>. Các đặc
tính của hành động <jsp:plugin> cung cấp dữ liệu cấu hình cho việc trình bày phần tử được
nhúng. Cú pháp của hành động <jsp:plugin> như sau:
Code: Chọn hết
<jsp:plugin type="pluginType" code="classFile"
codebase="relativeURLpath">
<jsp:params>
...
</jsp:params>
</jsp:plugin>