Ứng dụng đơn giản hoặc đội ngũ phát triển nhỏ
Ứng dụng phức tạp hoặc đội ngũ phát triển lớn
(1) Gọi Java code trực tiếp: đặt tất cả Java code vào file JSP.
(2) Gọi Java code gián tiếp: cài đặt các utility class riêng biệt. Chỉ chèn vào file JSP những đoạn Java code cần thiết để gọi các utility class. (3) Sử dụng bean: cài đặt riêng các utility class có
cấu trúc như bean. Sử dụng: jsp:useBean, jsp:getProperty, và jsp:setProperty để gọi Java code.
(4) Sử dụng kiến trúc MVC: có một servlet để trả lời các request gốc, tìm kiếm dữ liệu, lưu trữ dữ liệu trong bean. Chuyển tiếp đến trang JSP khác để hiển thị kết quả.
(5) Sử dụng JSP expression: sử dụng các cú pháp ngắn để truy xuất và xuất thuộc tính của đối tượng. Thường sử dụng kết hợp với bean.
(6) Sử dụng custom tag. Cài đặt các class tag handler. Gọi tag handler cùng với các XML-like custom tag.
9.3. GIỚI HẠN SỐ LƯỢNG JAVA CODE TRONG TRANG JSP
Giả sử có 25 dòng code cần chèn vào trang JSP. Khi đó, có hai lựa chọn: (1) chèn trực tiếp 25 dòng vào trang JSP; (2) chèn 25 dòng vào một class Java riêng biệt, rồi đặt class đó vào WEB- INF/classes/directoryMatchingPackageName, và sử dụng một hoặc hai dòng Java code dựa trên JSP (JSP-based Java code) để gọi class đó. Cách thứ hai là lựa chọn tốt hơn hẳn, do một số nguyên nhân sau:
(1) Cài đặt: Chúng ta thường viết code Java trong môi trường hướng Java (Java-oriented environment) (các IDE như JBuilder, Eclipse) và viết file JSP trong môi trường hướng HTML (như Dreamweaver). Môi trường hướng Java thường tốt hơn trong việc kiểm tra đóng, mở dấu ngoặc đơn, cung cấp các tooltip, kiểm tra lỗi cú pháp, tô màu các dòng code để dễ nhìn,…
(2) Biên dịch: Để biên dịch một class Java thông thường, nhấn nút Build trên IDE hoặc gọi javac. Để biên dịch trang JSP, đặt file JSP
vào thư mục thích hợp, khởi động server, mở browser và nhập URL tương ứng vào thanh địa chỉ trên browser.
(3) Gỡ lỗi: Nếu có lỗi cú pháp trong định nghĩa class, trình biên dịch sẽ thông báo ngay lập tức đồng thời chỉ rõ dòng code chứa lỗi. Nếu có lỗi trong trang JSP, server sẽ thông báo dòng nào trong servlet (servlet mà trang JSP chuyển thành) chứa lỗi. Để bắt output trong lúc runtime, với class thông thường, có thể sử dụng lệnh System.out.println nếu IDE không chỉ lỗi rõ ràng. Trong JSP, thỉnh thoảng cũng có thể sử dụng lệnh print nhưng không thấy được điểm khác nhau trong kết quả hiển thị từ server này đến server khác. (4) Phân công công việc: Nhiều team phát triển web là sự kết hợp giữa
một vài chuyên gia trong lĩnh vực ngôn ngữ Java với một số khác là chuyên gia về HTML (có ít hoặc không có kiến thức về Java code). Do đó, càng nhiều java code đặt trực tiếp trong trang JSP sẽ càng gây khó khăn cho các Web developer (chuyên gia HTML) sử dụng nó.
(5) Kiểm thử: Nếu đặt java code trực tiếp trong trang JSP, mỗi lần muốn kiểm thử một hàm nào đó trong Java code, chúng ta phải gọi trang JSP, sau đó lại reload để kiểm tra kết quả. Khi đó, việc kiểm thử nếu đặt code java trong một class Java riêng sẽ thuận tiện hơn. (6) Tái sử dụng: Khi có nhiều trang JSP cần sử dụng một đoạn java
code giống nhau thì việc đặt đoạn java code trong một class riêng sẽ thuận tiện hơn rất nhiều.
Lưu ý: Luôn đặt class Java trong package.
9.4. JSP EXPRESSIONS
JSP expression được dùng để chèn giá trị trực tiếp vào output. Cú pháp: <%= Java Expression %>
Expression được kiểm tra, chuyển sang định dạng chuỗi (string) rồi chèn vào trang JSP. Việc kiểm tra được thực hiện trong lúc runtime (khi trang JSP được request) nên có thể truy xuất hoàn toàn đến thông tin của request.Ví dụ sau đây hiển thị ngày/giờ mà trang JSP được request:
Giờ hiện tại:<%= new java.util.Date() %>
9.4.1. Biến được định nghĩa trước
Để đơn giản hóa expression, có thể sử dụng các biến đã được định nghĩa trước (predifined variable) (còn gọi là đối tượng ngầm – implicit object) sau đây:
requesttrong HttpServletRequest.
responsetrong HttpServletResponse.
sessiontrong HttpSession.
out trong Writer: gửi output đến cho client.
application trong ServletContext: lưu trữ dữ liệu được chia sẻ. Ví dụ: <%= request.getRemoteHost() %>
9.4.2. Cú pháp XML cho JSP expression
<jsp:expression>Java Expression</jsp:expression>
Lưu ý rằng, không giống với HTML element, XML element có phân biệt hoa thường, nên phải chắc chắn rằng jsp:expression đang được sử dụng với các ký tự viết thường.
9.4.3. Ví dụ JSP expression Bảng 9.2 - Expression.jsp Bảng 9.2 - Expression.jsp <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE>JSP Expressions</TITLE> <META NAME="keywords"
CONTENT="JSP,expressions,JavaServer Pages,servlets"> <META NAME="description"
CONTENT="A quick example of JSP expressions."> <LINK REL=STYLESHEET HREF="JSP-Styles.css" TYPE="text/css"> </HEAD> <BODY> <H2>JSP Expressions</H2> <UL>
<LI>Current time: <%= new java.util.Date() %> <LI>Server: <%= application.getServerInfo() %> <LI>Session ID: <%= session.getId() %>
<LI>The <CODE>testParam</CODE> form parameter: <%= request.getParameter("testParam") %> </UL>
Trên đây là ví dụ về một trang JSP tên là Expression.jsp. Chúng ta đặt tập tin này trong thư mục tên jsp-scripting, sau đó copy toàn bộ thư mục này sang thư mục xây dựng của ứng dụng web mặc định và sử dụng URL http://host/jsp-scripting/Expressions.jsp.
Lưu ý rằng chúng ta đã đặt thẻ META và link style sheet trong phần HEAD của trang JSP.
Hình 9.1 - Kết quả của Expression.jsp dùng Jrun và bỏ qua tham số request testParam
Hình 9.2 - Kết quả của Expression.jsp dùng Resin và chỉ định giá trị cho tham số request testParam là “testing”
9.5. SO SÁNH SERVLET VỚI JSP
Có thể nói rằng, trong một số trường hợp thì code JSP ngắn gọn, dễ sửa chữa hơn code servlet. JSP hoạt động tốt nhất khi cấu trúc các file HTML là cố định nhưng các values (giá trị) ở các nơi khác nhau
phải được tính toán linh động. Trong trường hợp cấu trúc trang là động, JSP sẽ hoạt động kém hiệu quả. Khi trang HTML chứa dữ liệu nhị phân hoặc có ít nội dung tĩnh thì servlet rõ ràng là vượt trội hơn. Mặt khác, đôi khi câu trả lời không phải là JSP hay servlet mà là sự kết hợp của cả JSP và servlet.
9.6. JSP SCRIPTLETS
Nếu muốn làm điều gì đó phức tạp hơn việc chỉ xuất ra giá trị của một expression thì JSP scriptlet sẽ cho phép chèn các arbitrary code vào phương thức _jspService của servlet (phương thức được gọi bởi hàm service). Sriptlet có dạng như sau:
<% Java Code %>
Scriptlet có quyền truy xuất vào các biến được khai báo tự động giống nhau như thực hiện các expression (request, response, session, out..). Ví dụ, nếu muốn gửi tường minh output tới trang kết quả, chúng ta có thể sử dụng biến out như trong ví dụ sau:
<% String queryData = request.getQueryString(); out.println("Attached GET data: " + queryData); %> Trong trường hợp đặc biệt này, chúng ta có thể thực hiện các tác dụng (effect) tương tự một cách dễ dàng hơn bằng cách kết hợp scriptlet và JSP expression:
<% String queryData = request.getQueryString(); %> Attached GETdata: <%= queryData %>
Hoặc cũng có thể sử dụng JSP expression một mình: Attached GETdata:<%= request.getQueryString() %> So sánh JSP và Servlet
Tổng quát mà nói thì scriptlet có thể thực hiện một số tác vụ mà không thể thực hiện với một mình jsp expression như là: thiết lập các header cho response, thiết lập status code, hoặc gọi các side effect chẳng hạn như viết vào server log hoặc cập nhật CSDL, hoặc thực thi code có chứa các vòng lặp, điều kiện, hoặc các cấu trúc phức tạp khác. Ví dụ, gửi trang kết quả tới client dưới dạng một file word, chứ không phải HTML. Bởi vì Microsoft Word có thể import các file HTML, nên kỹ thuật này khá hữu ích cho các ứng dụng trên thực tế:
9.6.1. Sự tương ứng giữa JSP/Servlet
Xét sự tương ứng giữa JSP và servlet thì có thể nói rằng JSP expression sẽ chứa Java value còn JSP scriptlet thì chứa các Java statement. Bảng 9.3 - Ví dụ về JSP Expression/Scriptlet <H2>foo</H2> <%= bar() %> <% baz(); %> Bảng 9.4 - Ví dụ về servlet Expression/Scriptlet
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { response.setContentType("text/html");
HttpSession session = request.getSession(); JspWriter out = response.getWriter();
out.println("<H2>foo</H2>"); out.println(bar()); baz(); ... } 9.6.2. Cú pháp XML cho scriptlet
Cú pháp XML tương đương với dòng<% Java Code %> là: <jsp:scriptlet>Java Code</jsp:scriptlet>
9.6.3. Ví dụ Scriptlet
Ví dụ này cho thấy sự phức tạp khi dùng một mình JSP expression. Ví dụ tạo một trang JSP, sử dụng tham số request bgColor để đặt màu nền của trang. Nếu chỉ dùng đơn giản dòng lệnh sau:
<BODY BGCOLOR="<%= request.getParameter("bgColor") %>">
thì sẽ dẫn đến vi phạm các nguyên tắc của việc đọc form data là phải luôn luôn kiểm tra sai sót dữ liệu hoặc thay đổi dữ liệu. Vì vậy, chúng ta sẽ sử dụng scriptlet.
Bảng 9.5 - BCCorlor.jsp <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE>Color Testing</TITLE> </HEAD> <%
String bgColor = request.getParameter("bgColor");
if ((bgColor == null) || (bgColor.trim().equals(""))) { bgColor = "WHITE";
} %>
<BODY BGCOLOR="<%= bgColor %>">
<H2 ALIGN="CENTER">Testing a Background of "<%= bgColor %>"</H2>
</BODY></HTML>
Hình 9.3 - Kết quả mặc định của BGColor.jsp
Hình 9.4 - Kết quả BGCorlor.jsp khi gán giá trị c0c0c0 cho tham số bgColor
Hình 9.5 - Kết quả BCColor.jsp khi gán giá trị màu X11 với tên gọi papaywhip cho tham số bgColor
9.7. JSP DECLARATIONS
JSP declaration cho phép định nghĩa các phương thức hoặc các field được chèn vào mainbody của class servlet. JSP declaration có dạng sau:
<%! Field or Method Definition %>
JSP declaration không tạo ra output và thường được dùng kết hợp với JSP expression/scriptlet. JSP declaration có thể chứa định nghĩa field, định nghĩa phương thức, định nghĩa inner class hay thậm chí là các initializer block tĩnh. Tuy nhiên trên thực tế thì JSP declaration thường chứa định nghĩa field và method.
Lưu ý là không sử dụng JSP declaration để ghi đè các phương thức servlet life-cycle chuẩn (service, doGet, init…) bởi vì servlet (do JSP chuyển đổi thành) sử dụng những phương thức này. Tuy nhiên khi khởi tạo hoặc cleanup trang JSP thì nên dùng JSP declaration để ghi đè các phương thức jspInit, jspDestroyhoặc init, destroy.
9.7.1. Sự tương ứng giữa JSP/Servlet
JSP declaration đặt bên trong servlet class nhưng bên ngoài phương thức _jspService. Do field và method có thể khai báo ở bất cứ đâu nên không có vấn đề gì nếu đặt khai báo ở đầu hay cuối servlet class.
Bảng 9.6 - Ví dụ về JSP declaration
<H1>Some Heading</H1> <%!
private String randomHeading() {
return("<H2>" + Math.random() + "</H2>"); }
%>
Bảng 9.7 - Ví dụ về Servlet code: declarationpublic class xxxx implements HttpJspPage { public class xxxx implements HttpJspPage {
private String randomHeading() {
return("<H2>" + Math.random() + "</H2>"); }
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
HttpSession session =
request.getSession();
JspWriter out = response.getWriter();
out.println("<H1>Some Heading</H1>"); out.println(randomHeading()); ... } ... } 9.7.2. Cú pháp XML cho JSP declaration
Cú pháp XML cho dòng khai báo tương đương <%! Field or Method Definition %> được viết như sau:
<jsp:declaration>Field or Method
Definition</jsp:declaration>
9.7.3. Ví dụ về JSP declaration
Ví dụ này in số lần mà trang web hiện tại được request khi boot server (hoặc khi servlet class thay đổi hoặc reload). Dòng code đếm sẽ có dạng thế này:
<%! private int accessCount = 0; %> Accesses to page since server reboot: <%= ++accessCount %> Bảng 9.8 - AccessCounts.jsp <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE>JSP Declarations</TITLE> <LINK REL=STYLESHEET HREF="JSP-Styles.css" TYPE="text/css"> </HEAD>
<BODY>
<H1>JSP Declarations</H1>
<%! private int accessCount = 0; %>
<H2>Accesses to page since server reboot:
<%= ++accessCount %></H2> </BODY></HTML>
Hình 9.6 - Vào trang AccessCounts.jsp sau khi nó được request 9 lần trước đó bởi cùng một client
Chương 10 WEB SERVICE WEB SERVICE
Chương này giới thiệu về web service và cách sử dụng Eclipse để tạo và kiểm thử một web service đơn giản.
10.1. SƠ LƯỢC VỀ WEB SERVICE 10.1.1.Các thành phần của Web service 10.1.1.Các thành phần của Web service
Dưới góc nhìn thực thi, web service thường được chia thành hai phần riêng biệt:
Các “logic” thực hiện các công việc thực sự cần thiết để cung cấp các chức năng dịch vụ, hoặc bất cứ việc gì nó có thể làm. Ví dụ, một dịch vụ đơn giản để tính thuế GTGT gồm một đoạn code chứa giá trị đơn vị tiền tệ bảng Anh (ví dụ: £10) nhân với 17,5 % để tính thuế GTGT (£1,75), cuối cùng trả về giá trị mới bao gồm cả VAT (£11,75).
Một giao diện, được cài đặt bằng XML. Giao diện này mô tả cách để đưa một yêu cầu vào dịch vụ và mô tả phản hồi và kết quả mong muốn.
Ngoài ra, để có thể sử dụng bất kỳ web service nào, chúng ta cũng cần phải triển khai một Client được xây dựng theo yêu cầu (dựa trên giao diện XML) và hiển thị các kết quả trả về bởi các web service.
10.1.2.Các phương pháp cài đặt
Có hai phương pháp cơ bản được sử dụng để cài đặt web service:
Phương pháp thứ nhất có tên là “bottom-up”. Đây là nơi chứa code cài đặt các hoạt động được thi hành bởi các dịch vụ được viết trước đó. Sau đó, mô tả XML (WSDL) của dịch vụ được tạo ra và công bố trong UDDI. Service code được đặt bên trong một “Container” cung cấp giao diện cần thiết cho việc nhắn tin (chẳng hạn như SOAP hoặc tương tự).
Phương pháp thứ hai là tạo ra các mô tả XML của dịch vụ trước khi thực hiện nó. Các dịch vụ được mô tả đầy đủ những gì nó thực hiện, cách gọi nó và kết quả trả về nhưng không thực sự được cài đặt. Đặc điểm kỹ thuật này (WSDL) được dùng như
một hướng dẫn để viết code cài đặt dịch vụ. Cách tiếp cận này có tên là “top-down”.
Hình 10.1 - Hai phương pháp cài đặt web service
10.2. CÀI ĐẶT ECLIPSE
Để có thể tạo một web service bằng Eclipse thì trước hết cần cài đặt Eclipse và một số plug-in của Eclipse.
10.2.1.Axis2 plug-in
Có hai axis2 plug-in được dùng trong phần này:
Service Archive Generator Wizard và Code Generator Wizard. Plug-in Code Generator Wizard được dùng hỗ trợ cho phương pháp cài đặt “top-down” hoặc “bottom-up”.
10.2.2.WTP plug-in
WTP (Web Tools Platform) là một project Eclipse. WTP mở rộng (extend) Eclipse bằng một chuỗi các công cụ cho việc phát triển, chạy và kiểm thử web service.
10.2.3.soapUI plug-in
Plug-in này có một chuỗi các function, trong đó có một vài function tương tự như các tính năng của WTP. Trong phần này, chúng ta sử dụng soapUI plug-in để kiểm thử khả năng tương tác của web-service (WTP không hỗ trợ tính năng này).
10.3. TẠO WEB SERVICE
10.3.1.Các bước để tạo một web service
Bước 1: Tạo một project trong Eclipse workspace, chọn loại project là “Dynamic Web project”. Project này giữ nhiệm vụ host (tổ chức) web service.
Bước 2: Viết Java code để cài đặt các tính năng của web service. Bước 3: Sử dụng Eclipse để tự động sinh ra các component (ví dụ như WSDL) chuyển Java code sang web service, sau đó yêu cầu Eclipse chạy web service.
Bước 4: Tạo một project khác, loại “Dynamic Web Project”. Project này giữ nhiệm vụ host ứng dụng phía client (client application), dùng để truy xuất và kiểm thử web service.
Bước 5: Sử dụng Eclipse để tự động tạo một tập các trang web có chức năng như một giao diện khách hàng (client interface) để gọi web service.
Bước 6: Sử dụng các trang web phía client (web page client) để gửi request đến các web service và quan sát phản hồi (response) của web service.
10.3.2.Thiết lập máy chủ ứng dụng (application server)
Trước khi có thể tạo và chạy một ứng dụng như một web service, cần phải thiết lập một application server bên trong Eclipse. Để thiết lập server Tomcat, chỉ cần làm theo các hướng dẫn Configuring an Application Server trong Eclipse.
Sau khi đã cài đặt application server, chúng ta có thể bắt đầu làm việc thông qua các hướng dẫn nêu trong các phần tiếp theo.
10.3.3.Tạo một project
Sau khi mở Eclipse lên, vào mục Project Explore (được mở trong mục Java EE). Tạo một project để chứa code và các phần khác của web service.
Hình 10.2 - Project Explore – Java EE perspective
Chọn File> New> Project ..., mở thư mục “Web” và chọn “Dynamic Web Project”, chọn “Next”. Khi đó, một New Dynamic Web Project sẽ được tạo.