Tải bản đầy đủ (.pdf) (22 trang)

Ajax cho các nhà phát triển Java: Tuần tự hóa đối tượng Java cho Ajax Năm cách để tuần tự hóa dữ liệu trong các ứng dụng Ajax pptx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (221.76 KB, 22 trang )

Ajax cho các nhà phát triển Java: Tuần tự hóa đối tượng Java cho Ajax
Năm cách để tuần tự hóa dữ liệu trong các ứng dụng Ajax
Philip McCarthy, Nhà Phát triển, SmartStream Technologies Ltd
Tóm tắt: Nếu bạn đang tiến hành phát triển Web ™ bằng cách sử dụng
JavaScript và XML không đồng bộ (Ajax), thì việc phân phát dữ liệu từ máy chủ
cho máy khách có lẽ là mối quan tâm hàng đầu của bạn. Trong bài viết thứ hai
trong loạt bài Ajax for Java developers này, Philip McCarthy cùng bạn qua năm
cách tiếp cận để tuần tự hóa đối tượng Java và cung cấp cho bạn tất cả các thông
tin bạn cần để chọn định dạng và công nghệ dữ liệu thích hợp tốt nhất cho ứng
dụng của bạn.
Trong bài viết đầu tiên của loạt bài này, tôi đã giới thiệu cho bạn các khối tạo
dựng của Ajax:
 Cách sử dụng một đối tượng JavaScript XMLHttpRequest để gửi một yêu
cầu không đồng bộ tới một máy chủ từ một trang Web.
 Cách xử lý và trả lời yêu cầu đó bằng một Java servlet trả về một tài liệu
XML tới máy khách.
 Cách sử dụng tư liệu trả lời đó trên máy khách để cập nhật khung nhìn
trang của bạn.
Bây giờ, tôi sẽ tiếp tục thảo luận về các quy tắc cơ bản về phát triển của Ajax,
nhưng tôi sẽ tập trung vào những gì quan trọng nhất đối với nhiều nhà phát triển
Web với Java: tạo dữ liệu cho máy khách.
Hầu hết các nhà phát triển Java đã áp dụng mẫu Model-View-Controller (MVC-
Trình điều khiển-Khung nhìn-Mô hình) cho các ứng dụng Web của họ. Trong một
ứng dụng Web truyền thống, thành phần khung nhìn gồm các JSP hoặc có lẽ là
một công nghệ trình bày khác như các khuôn mẫu Velocity (Tốc độ). Những thành
phần trình bày này cập nhật giao diện người dùng bằng cách tạo một cách động
toàn bộ trang HTML mới để thay thế những gì mà người dùng đã thấy trước đó.
Trong trường hợp của ứng dụng Java Web với một giao diện người dùng Ajax, tất
nhiên mã khách JavaScript có trách nhiệm cuối cùng cập nhật những gì người
dùng thấy, dựa vào dữ liệu được thu nhận để trả lời một XMLHttpRequest. Từ góc
nhìn của máy chủ, khung nhìn này trở thành nơi biểu diễn dữ liệu mà nó sẽ gửi trả


lời các yêu cầu của máy khách.
Bài viết này tập trung vào các kỹ thuật mà bạn có thể dùng để tạo các khung nhìn
ở giữa dữ liệu của các đối tượng Java của bạn. Tôi sẽ giải thích nhiều phương thức
mà bạn có thể sử dụng để biến JavaBeans của bạn thành các tài liệu XML và bạn
sẽ tìm hiểu những ưu và khuyết điểm của mỗi phương thức. Bạn cũng sẽ thấy tại
sao XML không phải luôn luôn là cách thực hiện: chuyển văn bản thuần có thể là
một sự lựa chọn thích hợp cho các yêu cầu Ajax đơn giản. Cuối cùng, tôi sẽ giới
thiệu cho bạn về JavaScript Object Notation (JSON- Ký hiệu đối tượng
JavaScript). JSON cho phép dữ liệu được truyền đi dưới dạng các đồ thị đối tượng
JavaScript được tuần tự hóa, các đồ thị này rất dễ làm việc với mã phía máy
khách.
Về ví dụ này
Tôi sẽ sử dụng một ứng dụng ví dụ và một số các trường hợp sử dụng để trình bày
các tính năng và các kỹ thuật công nghệ được thảo luận tại đây. Hình 1 hiển thị mô
hình dữ liệu vô cùng đơn giản để minh họa các trường hợp sử dụng trong ví dụ
này. Mô hình này trình bày một tài khoản của khách hàng tại một cửa hàng trực
tuyến. Khách hàng có một bộ sưu tập của các đơn đặt hàng trước đó và mỗi đơn
hàng có một số mục.

Hình 1. Một mô hình đối tượng đơn giản

Mặc dù XMLHttpRequest không đặt ra bất kỳ các hạn chế nào về định dạng được
sử dụng để gửi dữ liệu yêu cầu, đối với hầu hết các mục đích nó thích hợp để gửi
các tham số biểu mẫu truyền thống, nên do đó, việc thảo luận của tôi tập trung vào
trả lời của máy chủ. Câu trả lời này cũng có thể có bất kỳ định dạng dựa trên văn
bản nào nhưng, như tên gọi của nó cho thấy, XMLHttpRequest có các khả năng
gắn sẵn để xử lý dữ liệu trả lời XML. Điều này làm cho XML là sự lựa chọn mặc
định cho các trả lời của Ajax, vì vậy nó là một nơi tốt để bắt đầu.



Tạo XML từ các lớp Java
Có rất nhiều lý do phân phát các trả lời của Ajax như XML: mỗi trình duyệt có
khả năng Ajax có các phương thức điều hướng các tài liệu XML và cũng có rất
nhiều công nghệ phía máy chủ làm việc với dữ liệu XML. Thật dễ dàng xác định
cam kết giữa máy khách và máy chủ Ajax của bạn bằng cách tạo một lược đồ mô
tả các kiểu tài liệu sẽ được trao đổi và nếu bạn có một cách tiếp cận hướng dịch vụ
tới kiến trúc phía máy chủ của bạn, việc sử dụng XML cho phép các khách hàng
không phải Ajax cùng dùng các nguồn cung cấp dữ liệu của bạn.
Tôi sẽ xem xét ba trong những cách mà bạn có thể tạo dữ liệu XML từ các đối
tượng Java của bạn và thảo luận về những ưu và khuyết điểm của mỗi cách.


Tự tuần tự hóa
Trước hết, bạn có thể tạo XML theo cách lập trình từ đồ thị đối tượng của bạn.
Cách tiếp cận này có thể đơn giản như việc thực hiện một phương thức toXml()
trong mỗi một trong các lớp JavaBean của bạn. Sau đó, bạn sẽ chọn một XML
API và có một bean phát ra các phần tử để thể hiện trạng thái của nó và gọi đồ thị
đối tượng xuống theo cách đệ quy tới các thành viên của nó. Rõ ràng, cách tiếp
cận này không mở rộng tốt với một số lượng lớn các lớp vì mỗi một lớp cần có mã
tạo XML riêng của mình được viết riêng cho nó. Ở phía trên, đó là một phương
thức đơn giản thực hiện, không có bất kỳ chi phí hoạt động nào về cấu hình tăng
thêm hay một quá trình xây dựng phức tạp hơn và bất kỳ đồ thị nào gồm
JavaBeans của bạn có thể được chuyển thành một tài liệu XML với cặp các cuộc
gọi.
Trong đoạn mã ví dụ cho bài viết trước trong loạt bài này, tôi đã thực hiện các
phương thức toXml() bằng cách gắn thêm chuỗi đánh dấu XML với nhau. Như tôi
đã đề cập lúc trước, đây là một cách tiếp cận xấu vì nó đặt gánh nặng nhằm bảo
đảm các thẻ được cân bằng, các thực thể được mã hóa v.v trên mỗi mã của phương
thức toXml(). Một số các XML API có sẵn trên nền Java thực hiện tất cả công
việc này cho bạn, cho phép tập trung vào nội dung của XML. Liệt kê 1 sử dụng

JDOM API để thực hiện toXml() trên lớp đang thể hiện một đơn đặt hàng trong ví
dụ cửa hàng trực tuyến (xem Hình 1).

Liệt kê 1. Thực hiện JDOM của toXml () cho lớp đơn hàng

public Element toXml()
{ Element elOrder = new Element("order");
elOrder.setAttribute("id",id);
elOrder.setAttribute("cost",getFormattedCost());
Element elDate = new Element("date").addContent(date);
elOrder.addContent(elDate);
Element elItems = new Element("items");
for (Iterator<Item> iter = items.iterator() ; iter.hasNext(); )
{ elItems.addContent(iter.next().toXml()); }
elOrder.addContent(elItems);
return elOrder;
}

Ở đây bạn có thể thấy để tạo các phần tử, thiết lập các thuộc tính và thêm nội dung
phần tử bằng cách sử dụng JDOM đơn giản như thế nào. Các cuộc gọi đệ quy đến
các phương thức toXml() của JavaBeans đã kết hợp lại được thực hiện để nhận
được các thể hiện Element (phần tử) của đồ thị con của chúng. Ví dụ, nội dung của
các phần tử items được tạo ở đây bằng cách gọi toXml() trên mỗi đối tượng Item
được tập hợp theo Order (đơn hàng) này.
Một khi tất cả các JavaBeans của bạn thực hiện một phương thức toXml(), nó chỉ
đơn giản là tuần tự hóa bất kỳ đồ thị tùy ý nào vào trong một tài liệu XML và trả
nó về tới một máy khách Ajax, như trong Liệt kê 2.

Liệt kê 2. Tạo một trả lời XML từ một phần tử JDOM


public void doGet(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException, ServletException {
String custId = req.getParameter("username");
Customer customer = getCustomer(custId);
Element responseElem = customer.toXml();
Document responseDoc = new Document(responseElem);
res.setContentType("application/xml");
new XMLOutputter().output(responseDoc,res.getWriter()); }

Một lần nữa JDOM lại khiến mọi việc ở đây thành đơn giản. Bạn chỉ cần bọc một
Document quanh phần tử XML được đồ thị đối tượng trả về và sau đó sử dụng
XMLOutputter để viết tài liệu đầy đủ cho trả lời servlet. Liệt kê 3 hiển thị một
mẫu XML được tạo theo cách này, được định dạng kỹ lưỡng bằng cách khởi tạo
XMLOutputter với Format.getPrettyFormat(). Trong ví dụ này, khách hàng chỉ có
một đơn hàng với hai mục.

Liệt kê 3. Tài liệu XML mẫu thể hiện một khách hàng

<?xml version="1.0" encoding="UTF-8"?>
<customer username="jimmy66">
<realname>James Hyrax </realname>
<orders>
<order id="o-11123" cost="$349.98">
<date>08-26-2005</date>
<items>
<item id="i-55768">
<name>Oolong 512MB CF Card</name>
<description>512 Megabyte Type 1 CompactFlash card.
Manufactured by Oolong Industries</description>
<price>$49.99</price>

</item>
<item id="i-74491">
<name>Fujak Superpix72 Camera</name>
<description>7.2 Megapixel digital camera
featuring six shooting modes and 3x optical zoom. Silver.</description>
<price>$299.99</price>
</item>
</items>
</order>
</orders>
</customer>

Nhược điểm của việc tự tuần tự hóa
Điều thú vị là, các mã trong Liệt kê 3 cho thấy một trong những hạn chế chính của
việc có JavaBeans tự tuần tự hóa thành XML. Giả sử tài liệu này đã được sử dụng
để giới thiệu một khung nhìn Order History (Lịch sử đơn hàng) cho khách hàng.
Trong trường hợp đó, không chắc là bạn sẽ muốn hiển thị mô tả đầy đủ về mọi
mục trong mỗi đơn hàng đã qua hoặc báo cho người sử dụng tên của họ. Nhưng
nếu ứng dụng có một lớp ProductSearch trả về các kết quả tìm kiếm của nó như là
một danh sách các bean Item, sẽ có ích nếu tính đến các mô tả có trong thể hiện
XML của các Item. Hơn nữa, một trường bổ sung trên lớp Item thể hiện mức cổ
phiếu hiện nay sẽ là thông tin có ích để hiển thị trong khung nhìn Product Search
(Tìm kiếm sản phẩm). Tuy nhiên, sau đó trường này sẽ được tuần tự hóa từ bất kỳ
đồ thị đối tượng nào có liên quan đến Item, dù có sự không thích hợp của mức cổ
phiếu hiện tại với Order History của khách hàng.
Từ một góc nhìn thiết kế, đây là một vấn đề kinh điển của mô hình dữ liệu đang
được kết hợp với việc tạo khung nhìn. Mỗi bean chỉ có thể tự tuần tự hóa theo một
chiều và cách tiếp cận một kích cỡ phù hợp cho tất cả có nghĩa là các tương tác
Ajax kết thúc trao đổi dữ liệu mà chúng không cần, làm cho công việc mã khách
hàng khó định vị các thông tin được yêu cầu từ tài liệu, cũng như làm tăng việc sử

dụng băng thông và thời gian phân tích cú pháp XML ở phía máy khách. Hệ quả
khác của việc kết hợp này là ngữ pháp XML không thể phát triển một cách độc lập
với các lớp Java. Ví dụ, việc thực hiện thay đổi lược đồ tài liệu khách hàng có thể
tác động đến một số lớp Java mà sau đó sẽ phải được sửa đổi và được biên dịch
lại.
Tôi sẽ tập trung vào các mối quan tâm này sau, nhưng trước tiên hãy xem xét một
giải pháp cho các vấn đề mở rộng cách tiếp cận tự tuần tự hóa: các khung công tác
liên kết XML.


Các khung công tác liên kết XML
Trong những năm gần đây, một số các Java API đã được phát triển để đơn giản
hóa quá trình liên kết các tài liệu XML với các thể hiện đồ thị đối tượng Java. Hầu
hết cung cấp cả hai cách sắp xếp theo thứ tự và không sắp xếp theo thứ tự XML,
nghĩa là chúng thực hiện các chuyển đổi hai chiều giữa các đồ thị đối tượng Java
và XML. Các khung công tác này chứa tất cả công việc xử lý XML, nghĩa là mã
ứng dụng chỉ phải xử lý với các đối tượng thuần Java. Chúng cũng có xu hướng
cung cấp các hàm phụ thuộc có ích như việc xác nhận tài liệu hợp lệ. Nói chung,
các khung công tác này có hai phương thức tiếp cận khác nhau: tạo mã và ánh xạ
đối tượng tới XML. Tôi sẽ giải thích cả hai.
Cách tiếp cận tạo mã
Các khung công tác liên kết sử dụng việc tạo mã gồm XMLBeans, JAXB, Zeus và
JBind. Castor cũng có thể sử dụng kỹ thuật này. Điểm khởi đầu cho bất kỳ các
khung công tác này là lược đồ XML mô tả các kiểu dữ liệu của các tài liệu của
bạn. Sử dụng các công cụ được khung công tác cung cấp, sau đó bạn tạo các lớp
Java để thể hiện các kiểu lược đồ được định nghĩa này. Cuối cùng, bạn viết ứng
dụng của bạn bằng cách sử dụng các lớp được tạo này để thể hiện dữ liệu mô hình
của bạn và tuần tự hóa chúng sang XML thông qua một số cơ chế thuận tiện do
khung công tác tạo ra.
Cách tiếp cận tạo mã là một cách tiếp cận tốt khi ứng dụng của bạn sử dụng một

ngữ pháp XML lớn. Vấn đề mở rộng cách viết các phương thức tuần tự hóa XML
tùy chỉnh qua hàng chục lớp biến mất. Mặt khác, bạn không còn bắt đầu định
nghĩa JavaBeans của riêng bạn. Các lớp Java của khung công tác được tạo thường
làm theo rất giống các cấu trúc của XML, có thể làm cho chúng hơi khó sử dụng
để tạo mã lại. Ngoài ra, các lớp được tạo trở thành các thùng chứa dữ liệu câm vì
bạn không thể thêm hành vi vào chúng. Nói chung, bạn cần phải thực hiện các
thỏa hiệp trong mã ứng dụng của bạn để xử lý với các kiểu lược đồ được tạo. Khó
khăn khác là một sự thay đổi trong lược đồ gây ra các thay đổi cho các lớp được
tạo ra, lần lượt có một phản ứng dây chuyền cho bất kỳ mã nào mà bạn đã viết
xung quanh chúng.
Các khung công tác liên kết XML của kiểu này có ích nhất trong việc không sắp
xếp dữ liệu theo thứ tự (ví dụ, sử dụng các tài liệu XML và chuyển đổi chúng
thành các đối tượng Java). Trừ khi bạn có một mô hình dữ liệu rất lớn và sẽ được
lợi từ các lớp đã tạo cho bạn, các khung công tác dựa trên việc tạo mã có thể phá
hỏng một ứng dụng Ajax.
Cách tiếp cận ánh xạ
Các khung công tác sử dụng ánh xạ gồm Castor và Apache Commons Betwixt
(Giữa các dữ liệu chia sẻ chung của Apache). Nói chung, việc ánh xạ thường là
giải pháp linh hoạt và đơn giản hơn so với việc tạo mã. Trước tiên, bạn tạo mã
JavaBeans của bạn như bạn thường làm gồm bất kỳ hành vi nào và mọi phương
thức tiện ích mà bạn muốn. Sau đó, trong thời gian chạy, bạn gọi trình sắp xếp thứ
tự (marshaler) dựa vào nội tại của khung công tác và nó tạo một tài liệu XML dựa
trên các kiểu, các tên và các giá trị của các bộ phận của đối tượng của bạn. Bằng
cách định nghĩa các tệp ánh xạ cho các lớp, bạn có thể ghi đè lên chiến lược liên
kết mặc định và báo cho trình sắp xếp thứ tự cách bạn muốn các lớp của bạn được
thể hiện trong XML.
Cách tiếp cận này là một sự thỏa hiệp tốt đẹp giữa khả năng mở rộng và tính linh
hoạt. Bạn bắt đầu viết các lớp Java của bạn theo cách bạn muốn chúng như thế và
trình sắp xếp thứ tự tiết kiệm cho bạn khỏi xử lý với XML. Tuy nhiên, mặc dù các
tệp định nghĩa ánh xạ chỉ đơn giản để viết và mở rộng hợp lý, các quy tắc ánh xạ

chỉ có thể thay đổi rất nhiều hành vi liên kết tiêu chuẩn và một số mức kết nối giữa
cấu trúc của các đối tượng của bạn và sự thể hiện XML của chúng sẽ luôn luôn giữ
nguyên. Cuối cùng, bạn có thể phải thỏa hiệp hoặc thể hiện Java của bạn hoặc định
dạng XML cho cách tiếp cận ánh xa tới công việc.
Tóm tắt liên kết dữ liệu
Dennis Sosnoski đã viết sâu về đề tài của các API liên kết dữ liệu XML với cả tính
chất độc đáo của việc tạo mã lẫn ánh xạ mã. Tôi muốn giới thiệu các bài viết xuất
xắc của ông trên Castor và trên các khung công tác tạo mã nếu bạn muốn nghiên
cứu kỹ hơn lĩnh vực này (xem Tài nguyên để có các liên kết).
Về tổng thể, cách tiếp cận tạo mã thỏa hiệp quá nhiều tính linh hoạt và sự thuận
tiện có ích cho ứng dụng Ajax điển hình. Mặt khác, các khung công tác dựa trên
ánh xạ có thể phục vụ tốt cho bạn, miễn là bạn có thể thay đổi các chiến lược ánh
xạ của mình đủ để tạo XML mong muốn từ các đối tượng của bạn.
Tất cả các API liên kết XML có chung một hạn chế lớn với kỹ thuật tuần tự hóa
thủ công: việc kết nối của mô hình và khung nhìn. Việc bị hạn chế với chỉ một thể
hiện XML của mỗi kiểu đối tượng có nghĩa là có khả năng luôn có một số dữ liệu
dư thừa dịch chuyển trên mạng. Một vấn đề quan trọng hơn là mã khách không thể
có một khung nhìn chuyên dụng khi tình hình đòi hỏi nó và có thể có một thời
gian khó khăn khi cố gắng đối phó với khung nhìn một kích cỡ phù hợp với tất cả
đã thỏa hiệp của đồ thị đối tượng cụ thể.
Trong việc phát triển ứng dụng Web truyền thống, các hệ thống tạo khuôn mẫu
trang được sử dụng để dễ dàng tách việc tạo khung nhìn khỏi logic của trình điều
khiển và dữ liệu mô hình. Đây là một cách tiếp cận cũng có thể trợ giúp trong một
kịch bản Ajax.


Các hệ thống tạo khuôn mẫu trang
Bất kỳ công nghệ tạo khuôn mẫu trang nào cũng có thể dùng để tạo XML, cho
phép các ứng dụng Ajax tạo bất kỳ tài liệu trả lời XML nào từ các mô hình dữ liệu
của chúng. Một lợi ích phụ là các khuôn mẫu có thể được viết bằng cách sử dụng

ngôn ngữ đánh dấu đơn giản và truyền cảm, trái với lần lượt từ dòng này sang
dòng khác của mã Java. Liệt kê 4 là một trang JSP có một bean Customer (khách
hàng) và trả lại một khung nhìn XML tùy chỉnh thích hợp với mã khách hàng để
tạo một thành phần Order History.

Liệt kê 4. Một trang JSP tạo một tài liệu lịch sử đơn hàng

<?xml version="1.0"?>
<%@ page contentType="application/xml" %>
<%@ taglib uri=" prefix="c" %>
<c:set var="cust" value="${requestScope.customer}"/>
<orderhistory username="${cust.username}">
<c:forEach var="order" items="${cust.orders}">
<order id="${order.id}" cost="${order.formattedCost}">
<date>${order.date}</date>
<items>
<c:forEach var="item" items="${order.items}">
<item id="${item.id}">
<name><c:out value="${item.name}" escapeXml="true"/></name>
<price>${item.formattedPrice}</price>
</item>
</c:forEach>
</items>
</order>
</c:forEach>
</orderhistory>

Khuôn mẫu ngắn gọn này chỉ cung cấp dữ liệu cần thiết cho một khung nhìn Order
History và không phải là những thứ thích hợp như là mỗi sự mô tả của mục. Nó sẽ
giống như việc dễ dàng để tạo XML tùy chỉnh cho khung nhìn Product Search,

gồm sự mô tả đầy đủ và mức cổ phiếu cho mỗi mục.
Các sự cố với khuôn mẫu
Mặt trái của vấn đề là ở chỗ bây giờ cần phải tạo một JSP mới cho mỗi khung nhìn
khác nhau mà tôi yêu cầu, trái với việc chỉ lắp ráp đồ thị đối tượng cần thiết và
tuần tự hóa nó. Từ một góc nhìn thiết kế, nhiều người cho rằng dù thế nào đi nữa
đây là một điều tốt vì nó có nghĩa là sự suy nghĩ chính thức về các kiểu tài liệu mà
máy chủ sẽ tạo. Ngoài ra, vì tôi bây giờ đang làm việc với một môi trường tạo
khuôn mẫu chung chung và không phải là một API XML cụ thể, đó là trách nhiệm
của tôi để đảm bảo chắc chắn các thẻ được cân bằng, thứ tự của phần tử và thuộc
tính là chính xác và bất kỳ các thực thể XML nào (ví dụ < hay &) được thoát khỏi
chương trình. Thẻ out của lõi JSP làm cho nhiệm vụ sau này dễ dàng, nhưng
không phải tất cả các công nghệ tạo khuôn mẫu cung cấp một cơ chế như vậy.
Cuối cùng, không có cách dễ dàng nào để xác nhận hợp lệ các tài liệu XML được
tạo so với một lược đồ ở phía máy chủ, nhưng dù thế nào đi nữa đây không phải là
điều mà bạn muốn làm trong một môi trường sản xuất và bạn có thể dễ dàng làm
việc xung quanh nó trong quá trình phát triển.


Dữ liệu trả lời không có XML
Cho đến nay, tôi đã trình bày tất cả các kỹ thuật tạo trả lời của máy chủ dưới dạng
một tài liệu XML. Tuy nhiên có một vài vấn đề với XML. Một trong những vấn đề
này liên quan đến độ trễ. Các trình duyệt không phân tích cú pháp các tài liệu
XML và tạo các mô hình DOM ngay lập tức và điều này có thể làm giảm cảm giác
"sống động" cần thiết bởi một số thành phần Ajax, đặc biệt là khi phân tích cú
pháp các tài liệu lớn trên máy tính chạy chậm hơn. Một ví dụ là "live search" (tìm
kiếm trực tiếp), ở đây các kết quả tìm kiếm được lấy từ máy chủ và được hiển thị
cho người dùng khi họ gõ vào các điều kiện tìm kiếm của họ. Đó là điều quan
trọng đối với một thành phần tìm kiếm trực tiếp để trả lời một cách nhanh chóng
cho đầu vào, nhưng đồng thời nó cần phải phân tích cú pháp các trả lời của máy
chủ một cách nhanh chóng và liên tục.

Độ trễ là một lý do quan trọng, nhưng lý do lớn nhất để tránh XML là một DOM
API phía máy khách rất rắc rối. Liệt kê 5 cho thấy các vòng mà bạn thường phải
nhảy qua để đạt tới một giá trị thông qua DOM, theo cách tương thích của trình
duyệt giao nhau.

Liệt kê 5. Chuyển hướng một tài liệu trả lời XML trong JavaScript

// Find name of first item in customer's last
order var orderHistoryDoc = req.responseXML;
var orders = orderHistoryDoc.getElementsByTagName("order");
var lastOrder = orders[orders.length - 1];
var firstItem = lastOrder.getElementsByTagName("item")[0];
var itemNameElement = firstItem.firstChild;
var itemNameText = itemNameElement.firstChild.data;

Những điều trở nên phức tạp hơn khi có khoảng trống giữa các thành phần, vì lúc
nào mỗi firstChild của phần tử sẽ là một nút văn bản khoảng trống. Các thư viện
JavaScript sẵn sàng xử lí các tài liệu XML ít khó khăn hơn. Chúng gồm Sarissa
(xem Tài nguyên), và Google-ajaXSLT, cả hai đều thêm các khả năng XPath cho
hầu hết các trình duyệt.
Tuy nhiên, thật đáng suy nghĩ về các sự lựa chọn. Ngoài responseXML, đối tượng
XMLHttpRequest cung cấp một đặc tính có tên là responseText, đặc tính này chỉ
cung cấp phần thân trả lời của máy chủ như là một chuỗi.
Đặc tính responseText
Đặc tính responseText đặc biệt thuận tiện khi máy chủ cần gửi các giá trị rất đơn
giản cho máy khách, tránh các chi phí băng thông và các chi phí xử lý XML. Ví
dụ, một trả lời đúng/sai đơn giản có thể được máy chủ trả về như là văn bản thuần,
có thể là một danh sách có phân tách dấu phẩy đơn giản của các số hay các tên.
Nói chung, tuy nhiên, tốt nhất là không trộn lẫn và phối hợp các trả lời XML và
các trả lời văn bản thuần trong cùng ứng dụng; việc bám chặt vào chỉ một định

dạng dữ liệu làm cho mã trừu tượng và việc tái sử dụng đơn giản hơn.
responseText cũng có thể có ích về dữ liệu trả lời XML. Trong một kịch bản ở đó
bạn chỉ cần lấy một giá trị từ một tài liệu trả lời, nó có thể thuận tiện hơn cho "sự
lừa đảo", xử lý XML như là một chuỗi các văn bản chứ không phải là một tài liệu
có cấu trúc. Ví dụ, Liệt kê 6 cho thấy cách một biểu thức chính quy có thể được sử
dụng để lấy ra ngày tháng của đơn hàng đầu tiên trong Order History của khách
hàng. Điều này thực sự chỉ là một nỗ lực thành công, mặc dù nhìn chung bạn
không nên dựa vào sự thể hiện từ vựng của một tài liệu XML.

Liệt kê 6. Sử dụng một biểu thức chính quy với đối tượng responseText của
XMLHttpRequest

var orderHistoryText = req.responseText;
var matches = orderHistoryText.match(/<date>(.*?)<\/date>/);
var date = matches[1];

Sử dụng responseText trong mẫu đặc biệt này có thể thuận tiện trong một số
trường hợp. Tất nhiên, lý tưởng là có một cách để thể hiện dữ liệu có cấu trúc,
phức tạp trong một định dạng có thể dễ dàng được chuyển hướng trong JavaScript
và không có các chi phí xử lý của XML. Như vận may sẽ có nó, giống như một
định dạng tồn tại.


Ký hiệu đối tượng JavaScript
Dưới vỏ đậy này, các đối tượng JavaScript cho hầu hết các phần gồm các mảng
kết hợp, các mảng được lập chỉ mục theo số lượng, các chuỗi, các số hoặc các kết
hợp lồng nhau của các kiểu này. Vì tất cả các kiểu có thể được khai báo theo dạng
chữ trong JavaScript, có thể định nghĩa tĩnh một đồ thị đối tượng trong một câu
lệnh. Liệt kê 7 khai báo một đối tượng khi sử dụng cú pháp JSON và chỉ ra cách
truy cập nó. Các dấu ngoặc móc biểu thị một mảng kết hợp (tức là một đối tượng),

với cặp giá trị quan trọng của nó được phân tách bằng dấu phẩy. Các dấu ngoặc
vuông biểu thị một mảng được lập chỉ mục theo số lượng.

Liệt kê 7. Khai báo một đối tượng đơn giản theo dạng chữ trong JavaScript,
khi sử dụng JSON

var band = { name: "The Beatles",
members: [{ name: "John", instruments: ["Vocals","Guitar","Piano"] },
{ name: "Paul", instruments :["Vocals","Bass","Piano","Guitar"] },
{ name: "George", instruments: ["Guitar","Vocals"] },
{ name: "Ringo", instruments: ["Drums","Vocals"] } ] };
// Interrogate the band object
var musician = band.members[3];
alert( musician.name + " played " + musician.instruments[0] + "with " +
band.name );

Do JSON là một tính năng ngôn ngữ thú vị, nhưng với Ajax nó phải làm gì? Phần
cuối của câu chuyện là bạn có thể sử dụng JSON để gửi một đồ thị đối tượng
JavaScript qua mạng dưới dạng trả lời của máy chủ Ajax. Điều này có nghĩa là
một sự thoát ra khỏi chuyển hướng XML trên máy khách thông qua DOM API
bạn chỉ cần đánh giá câu trả lời JSON và bạn ngay lập tức có một đồ thị đối tượng
JavaScript có thể truy cập. Tất nhiên, trước tiên cần chuyển JavaBeans của bạn
thành JSON.
Tạo JSON từ các lớp Java
Những ưu điểm và nhược điểm giống nhau áp dụng cho các kỹ thuật tạo XML
khác nhau cũng áp dụng để tạo JSON. Người ta cho rằng, có một trường hợp để sử
dụng các công nghệ tạo lại khuôn mẫu trình bày. Tuy nhiên, việc sử dụng JSON
kỹ hơn để chuyển các đối tượng được tuần tự hóa giữa các tầng ứng dụng hơn là
để tạo một khung nhìn trạng thái của ứng dụng. Tôi sẽ chỉ cho bạn cách sử dụng
Java API org.json để tạo các phương thức toJSONObject() trên các lớp Java của

bạn. Rồi các JSONObject của bạn có thể được tuần tự hóa đơn giản tới JSON. Liệt
kê 8 kiểm tra lại Liệt kê 1 từ cuộc thảo luận XML, hiển thị việc thực hiện
toJSONObject() cho lớp Order.

Liệt kê 8. Thực hiện phương thức toJSONObject () cho lớp Order

public JSONObject toJSONObject()
{ JSONObject json = new JSONObject();
json.put("id",id);
json.put("cost",getFormattedCost());
json.put("date",date);
JSONArray jsonItems = new JSONArray();
for (Iterator<Item> iter = items.iterator() ; iter.hasNext() ; )
{ jsonItems.put(iter.next().toJSONObject()); }
json.put("items",jsonItems); return json;
}

Như bạn có thể thấy, API org.json rất đơn giản. JSONObject thể hiện một đối
tượng JavaScript (tức một mảng kết hợp) và có các phương thức put() khác nhau
lấy một khoá String và giá trị là một kiểu nguyên thủy, một kiểu String, hoặc một
kiểu JSON khác. JSONArray thể hiện một mảng có lập chỉ mục, để cho phương
thức put() của nó chỉ có một giá trị. Lưu ý rằng trong Liệt kê 8, một sự lựa chọn
cho việc tạo mảng jsonItems và sau đó gắn nó vào đối tượng json với put() sẽ gọi
json.accumulate("items",iter.next().toJSONObject()); cho mỗi mục. Phương thức
accumulate() giống như put() trừ việc nó gắn thêm giá trị của mình cho một mảng
có lập chỉ mục được xác định bằng khoá.
Liệt kê 9 cho thấy cách để tuần tự hóa một JSONObject và viết nó vào một trả lời
của servlet.

Liệt kê 9. Tạo một trả lời JSON được tuần tự hóa từ một JSONObject


public void doGet(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException, ServletException
{ String custId = req.getParameter("username");
Customer customer = getCustomer(custId);
res.setContentType("application/x-json");
res.getWriter().print(customer.toJSONObject());
}

Như bạn thấy, thực sự không có gì với nó. Phương thức toString() trên
JSONObject, được gọi ngầm ở đây, thực hiện tất cả công việc. Lưu ý rằng kiểu nội
dung application/x-json ít tin cậy tại thời điểm của bài viết này không có sự nhất
trí nào về những gì mà kiểu MIME của JSON sẽ có. Tuy nhiên, application/x-json
là một lựa chọn nhạy cảm trong lúc này. Liệt kê 10 hiển thị một ví dụ trả lời từ mã
servlet này.

Liệt kê 10. Thể hiện JSON của một bean Customer

{ "orders":
[ { "items":
[ { "price": "$49.99",
"description": "512 Megabyte Type 1 CompactFlash card.
Manufactured by Oolong Industries",
"name": "Oolong 512MB CF Card",
"id": "i-55768" },
{ "price": "$299.99",
"description": "7.2 Megapixel digital camera featuring
six shooting modes and 3x optical zoom. Silver.",
"name": "Fujak Superpix72 Camera",
"id": "i-74491" }

],

"date": "08-26-2005",
"cost": "$349.98",
"id": "o-11123" }
],

"realname": "James Hyrax",
"username": "jimmy66"
}

Sử dụng JSON trên máy khách
Bước cuối cùng trong tiến trình là chuyển dữ liệu JSON thành các đối tượng
JavaScript trên máy khách. Điều này có thể được thực hiện bằng một cuộc gọi đơn
giản tới eval(), hàm diễn giải các chuỗi có chứa các biểu thức JavaScript đang hoạt
động. Liệt kê 11 chuyển đổi một trả lời của JSON thành đồ thị đối tượng
JavaScript và sau đó thực hiện nhiệm vụ của Liệt kê 5 về việc nhận được tên của
mục đầu tiên từ đơn hàng cuối cùng của khách hàng.

Liệt kê 11. Đánh giá một trả lời của JSON

var jsonExpression = "(" + req.responseText + ")";
var customer = eval(jsonExpression);
// Find name of first item in customer's last order
var lastOrder = customer.orders[customer.orders.length-1];
var name = lastOrder.items[0].name;

So sánh với Liệt kê 11 với Liệt kê 5 minh họa sự thuận lợi cho máy khách khi sử
dụng JSON. Nếu dự án Ajax của bạn liên quan đến rất nhiều việc chuyển hướng
của các trả lời máy chủ phức tạp trên máy khách, thì JSON cũng hấp dẫn với bạn.

Việc đặt JSON và XMLHttpRequest với nhau cũng tạo một sự khởi đầu tương tác
Ajax trông giống như một cuộc gọi RPC hơn là một yêu cầu SOA, có thể có sự
liên quan đến việc thiết kế ứng dụng của bạn. Trong bài viết tiếp theo, tôi sẽ xem
xét các khung công tác được thiết kế rõ ràng để cho phép mã JavaScript thực hiện
các cuộc gọi phương thức từ xa trên các đối tượng phía máy chủ.
Nhược điểm của JSON
JSON có nhược điểm của nó. Việc sử dụng cách tiếp cận JSON minh họa ở đây,
không có cách nào để điều chỉnh sự tuần tự hóa của đối tượng trên cơ sở cho mỗi
yêu cầu, vì vậy các trường không cần thiết thường có thể được gửi qua mạng.
Ngoài ra, việc bổ sung thêm phương thức toJSONObject() cho mỗi JavaBean
không mở rộng hơn, mặc dù nó sẽ hoàn toàn dễ hiểu để viết JavaBean chung cho
một trình tuần tự hóa (serializer) JSON khi sử dụng xem xét nội tại và các chú
thích. Cuối cùng, nếu mã phía máy chủ của bạn theo hướng dịch vụ và không biến
đổi chỉ để xử lý các yêu cầu từ một máy khách Ajax, thì XML là một lựa chọn tốt
hơn do sự hỗ trợ phổ biến của nó.


So sánh các kỹ thuật tuần tự hóa
Bây giờ bạn đã thấy năm kỹ thuật khác nhau để chuyển trạng thái phía máy chủ
Java cho một máy khách Ajax. Tôi đã thảo luận sự tuần tự hóa XML với mã hóa
thủ công riêng của bạn, liên kết XML qua việc tạo mã, liên kết XML thông qua
một cơ chế ánh xạ, việc tạo XML dựa trên khuôn mẫu và cuối cùng tuần tự hóa
mã hóa thủ công tới JSON. Mỗi cái có những lợi thế và bất lợi riêng của nó và phù
hợp tốt nhất với các kiến trúc ứng dụng khác nhau.
Trong một nỗ lực tổng kết những lợi ích và hạn chế của từng cách tiếp cận, Bảng 1
gán các điểm số gần đúng theo sáu loại:
Khả năng mở rộng
Mô tả cách tiếp cận thích nghi với một số lượng lớn các kiểu dữ liệu tốt như
thế nào. Liệu khối lượng công việc mã hóa và cấu hình của bạn sẽ tăng theo
mỗi kiểu bổ sung không?

Dễ dàng tích hợp
Đánh giá cách đơn giản để tích hợp công nghệ vào dự án của bạn. Nó có
đòi hỏi quy trình xây dựng phức tạp hơn không? Liệu nó làm tăng tính phức
tạp triển khai không?
API của lớp Java
Mô tả cách dễ dàng làm việc với các đối tượng Java phía máy chủ được sử
dụng trong cách tiếp cận này. Bạn có bắt đầu viết các bean thông thường
không hoặc bạn sẽ phải làm việc với các thể hiện tài liệu rắc rối không?
Kiểm soát đầu ra
Mô tả bạn có thể kiểm soát việc thể hiện tuần tự hóa của các lớp của bạn
chính xác như thế nào.
Tính linh hoạt của khung nhìn
Đánh giá xem sự tuần tự hóa dữ liệu có tùy chỉnh, khác nhau có thể được
tạo từ cùng một tập các đối tượng.
Truy cập dữ liệu khách
Mô tả mã JavaScript làm việc với dữ liệu trả lời của máy chủ dễ dàng như
thế nào.
Bảng 1. Các hành động có liên quan của các kỹ thuật tạo dữ liệu

Tự
XML

Liên kết
XML qua
việc tạo mã
Liên kết
XML qua
ánh xạ
XML tạo
khuôn mẫu

trang
Tuần tự hóa
JSSON mã hóa
thủ công
Khả năng mở
rộng
Kém Tốt Trung bình Trung bình Kém
Dễ tích hợp Tốt Kém Trung bình Trung bình Tốt
API của lớp
Java
Tốt Kém Tốt Tốt Tốt
Kiểm soát
đầu ra
Tốt Tốt Trung bình Tốt Tốt
Tính linh ho
ạt
của khung
nhìn
Kém Kém Kém Tốt Kém
Truy cập dữ
liệu khách
Kém Kém Kém Trung bình Tốt


Kết luận
Dữ liệu được biên dịch trong Bảng 1 không có ý muốn nói rằng bất kỳ trong số
các công nghệ tuần tự hóa nào tốt hơn so với các công nghệ khác. Xét cho cùng,
tầm quan trọng tương đối của mỗi một trong sáu loại phụ thuộc vào các chi tiết
của dự án của bạn. Ví dụ, nếu bạn đang làm việc với hàng trăm kiểu dữ liệu, bạn
muốn có khả năng mở rộng, vì thế việc tạo mã có lẽ là suy nghĩ tốt nhất của bạn.

Nếu bạn cần phải tạo các khung nhìn khác nhau cho cùng một mô hình dữ liệu,
việc tạo khuôn mẫu trang là cách thực hiện. Nếu bạn đang làm việc với một dự án
quy mô nhỏ và muốn giảm bớt số lượng mã JavaScript mà bạn sẽ phải viết, hãy
xem JSON.
Hy vọng rằng bài viết này đã cho bạn những thông tin cần thiết để chọn một công
nghệ tuần tự hóa phù hợp với ứng dụng của bạn. Xem phần Tài nguyên để tìm
hiểu thêm về các công nghệ đã thảo luận tại đây. Bạn cũng nên để ý đến các phần
tiếp theo của loạt bài này, ở đây tôi sẽ cho bạn thấy cách viết một ứng dụng Java
Ajax bằng cách sử dụng Direct Web Remoting (DWR-Truy cập Web trực tiếp từ
xa). Khung công tác DWR cho phép bạn gọi các phương thức trên các lớp Java
của bạn trực tiếp từ mã JavaScript. Nói cách khác, nó sẽ giữ gìn công việc tuần tự
hóa dữ liệu cho bạn để cho bạn có thể sử dụng Ajax ở một mức độ trừu tượng cao
hơn.

Mục lục

 Tạo XML từ các lớp Java
 Tự tuần tự hóa
 Các khung công tác liên kết XML
 Các hệ thống tạo khuôn mẫu trang
 Dữ liệu trả lời không có XML
 Ký hiệu đối tượng JavaScript
 So sánh các kỹ thuật tuần tự hóa
 Kết luận

×