PDF:

Ajax cho các nhà phát triển Java: Ajax với Direct Web
Remoting
Sự tuần tự hóa dữ liệu không dễ dàng hơn điều này!
Philip McCarthy ([email protected])
Nhà Phát triển
SmartStream Technologies Ltd
04 12 2009
Thật thú vị như nó có, việc thêm chức năng Ajax cho các ứng dụng của bạn có thể mang lại
nhiều việc khó khăn. Trong bài viết thứ ba của loạt bài Ajax cho các nhà phát triển Java™ này,
Philip McCarthy cho bạn thấy cách sử dụng Direct Web Remoting (DWR-Truy cập Web trực tiếp
từ xa) để trực tiếp đặt các phương thức JavaBeans vào mã JavaScript của bạn và tự động hóa
công việc đòi hỏi sự nỗ lực của Ajax.
Xem thêm bài trong loạt bài này
Hiểu biết những điều căn bản về lập trình Ajax (fundamentals of Ajax programming) là điều cần
thiết, nhưng nếu bạn đang xây dựng các giao diện người dùng (UI) Ajax phức tạp, điều quan trọng
là có thể làm việc ở một mức độ trừu tượng cao hơn. Trong bài viết thứ ba của loạt bài Ajax cho
các nhà phát triển Java này, tôi thêm phần giới thiệu của số trước vào các kỹ thuật tuần tự hóa dữ
liệu cho Ajax (data serialization techniques for Ajax), giới thiệu một kỹ thuật cho phép bạn tránh
những chi tiết thực dụng của việc tuần tự hóa các đối tượng Java.
Trong bài trước, tôi đã chỉ cho bạn cách sử dụng JavaScript Object Notation (JSON- Ký hiệu đối
tượng JavaScript) để tuần tự hóa dữ liệu theo một định dạng dễ dàng được chuyển đổi thành các
đối tượng JavaScript trên máy khách. Với thiết lập này, bạn có thể gọi các cuộc gọi dịch vụ từ xa
khi sử dụng mã JavaScript và nhận các đồ thị đối tượng JavaScript trả lời, không giống như việc
thực hiện một cuộc gọi thủ tục từ xa. Bây giờ, bạn sẽ tìm hiểu cách tiến thêm một bước nữa, bằng
cách sử dụng một khung công tác chính thức hóa khả năng của bạn để thực hiện cuộc gọi thủ tục
từ xa trên các đối tượng Java phía máy chủ từ mã máy khách JavaScript.
DWR là một giải pháp được cấp phép Apache, mã nguồn mở gồm các thư viện Java phía máy chủ,
một servlet DWR và các thư viện JavaScript. Trong khi DWR không chỉ là bộ công cụ Ajax-RPC
có sẵn cho nền tảng Java, mà nó còn là một trong những giải pháp hoàn thiện nhất và cung cấp rất
nhiều chức năng có ích. Xem Tài nguyên để tải về DWR trước khi tiếp tục các ví dụ.
© Copyright IBM Corporation 2009
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Nhẫn hiệu đăng ký
Trang 1 của 16
developerWorks®
ibm.com/developerWorks/vn/
DWR là gì?
Theo các thuật ngữ đơn giản nhất, DWR là một công cụ đặt các phương thức của các đối tượng
Java phía máy chủ theo mã JavaScript. Thực tế, với DWR, bạn có thể loại bỏ tất cả máy theo chu
trình yêu cầu-trả lời của Ajax ra khỏi mã ứng dụng của bạn. Điều này có nghĩa là mã phía máy
khách của bạn không bao giờ phải xử lý trực tiếp một đối tượng XMLHttpRequest hoặc xử lý trả lời
của máy chủ. Bạn không cần phải viết mã tuần tự hóa đối tượng hoặc sử dụng các công cụ của bên
thứ ba để chuyển các đối tượng của bạn sang XML. Bạn thậm chí không cần phải viết mã servlet để
dàn xếp các yêu cầu Ajax thành các cuộc gọi trên các đối tượng miền Java của bạn.
DWR được triển khai như là một servlet trong ứng dụng Web của bạn. Được xem như hộp đen,
servlet này thực hiện hai vai trò chính: Thứ nhất, với mỗi lớp được trưng ra, DWR tự động tạo
Javascript để có trong trang Web của bạn. JavaScript được tạo có chức năng stub để thể hiện các
phương thức tương ứng trên lớp Java và cũng thực hiện các XMLHttpRequest ở hậu trường. Các
yêu cầu này được gửi tới servlet DWR, mà servlet DWR, trong vai trò thứ hai của mình, dịch chuyển
yêu cầu đó thành một cuộc gọi phương thức trên một đối tượng Java phía máy chủ và gửi các giá
trị trả về tới phía máy khách theo dạng trả lời servlet của nó, được mã hóa thành JavaScript. DWR
cũng cung cấp các hàm tiện ích JavaScript giúp thực hiện các nhiệm vụ UI chung.
Về ví dụ này
Trước khi giải thích DWR chi tiết hơn, tôi sẽ giới thiệu một kịch bản ví dụ đơn giản. Như trong các
bài viết trước đây, tôi sẽ sử dụng một mô hình tối thiểu dựa trên một cửa hàng trực tuyến, lúc này
có một thể hiện sản phẩm cơ bản, một giỏ mua hàng của người dùng có thể chứa các mục và một
đối tượng truy cập dữ liệu (DAO) để tìm kiếm các chi tiết sản phẩm từ một kho dữ liệu. Lớp Item
là một lớp giống như được sử dụng trong bài viết trước, nhưng nó không còn thực hiện bất kỳ các
phương thức tuần tự hóa nào bằng thủ công. Hình 1 mô tả thiết lập đơn giản này:
Hình 1. Biểu đồ lớp mô tả các giỏ hàng, CatalogDAO và các lớp Item
Tôi sẽ trình diễn hai trường hợp sử dụng rất đơn giản trong kịch bản này. Trước tiên, người dùng có
thể thực hiện tìm kiếm văn bản trên danh mục và xem các mục phù hợp. Thứ hai, người sử dụng có
thể thêm các mục vào giỏ mua hàng và xem tổng chi phí của các mục trong giỏ hàng.
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 2 của 16
ibm.com/developerWorks/vn/
developerWorks®
Thực hiện danh mục
Điểm khởi đầu của một ứng dụng DWR là viết mô hình đối tượng phía máy chủ của bạn. Trong
trường hợp này, tôi bắt đầu bằng cách viết một DAO để cung cấp các khả năng tìm kiếm trên kho
dữ liệu (datastore) danh mục sản phẩm. CatalogDAO.java là một lớp không trạng thái, đơn giản với
một số hàm tạo không-đối số. Liệt kê 1 cho thấy các điểm đặc trưng của các phương thức Java mà
tôi muốn để trưng ra cho các máy khách Ajax:
Liệt kê 1. Các phương thức CatalogDAO để trưng ra qua DWR
/**
* Returns a list of items in the catalog that have
* names or descriptions matching the search expression
* @param expression Text to search for in item names
* and descriptions
* @return list of all matching items
*/
public List<Item> findItems(String expression);
/**
* Returns the Item corresponding to a given Item ID
* @param id The ID code of the item
* @return the matching Item
*/
public Item getItem(String id);
Tiếp theo, tôi cần cấu hình DWR, cho nó biết các máy khách Ajax nên có khả năng xây dựng một
CatalogDAO và gọi các phương thức này. Tôi thực hiện việc này với tệp cấu hình dwr.xml được hiển
thị trong Liệt kê 2:
Liệt kê 2. Cấu hình để trưng ra các phương thức CatalogDAO
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
<allow>
<create creator="new" javascript="catalog">
<param name="class"
value="developerworks.ajax.store.CatalogDAO"/>
<include method="getItem"/>
<include method="findItems"/>
</create>
<convert converter="bean"
match="developerworks.ajax.store.Item">
<param name="include"
value="id,name,description,formattedPrice"/>
</convert>
</allow>
</dwr>
Phần tử gốc của tài liệu dwr.xml là dwr. Bên trong nó là phần tử allow (cho phép), cho phép xác
định các lớp mà DWR sẽ truy cập từ xa. Hai phần tử con của allow là create (tạo) và convert
(chuyển đổi).
Phần tử create
Phần tử create báo cho DWR biết một lớp phía máy chủ nên được trưng ra cho các yêu cầu Ajax
và định nghĩa cách DWR nhận được một cá thể của lớp đó từ xa. Thuộc tính creator ở đây được
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 3 của 16
developerWorks®
ibm.com/developerWorks/vn/
đặt tới giá trị new, có nghĩa là DWR sẽ gọi hàm tạo mặc định của lớp để nhận được một cá thể.
Các khả năng khác là tạo một cá thể thông qua một đoạn kịch bản lệnh bằng cách sử dụng Bean
Scripting Framework (BSF-Khung công tác tạo kịch bản lệnh Bean) hoặc để nhận được một cá thể
thông qua việc tích hợp với thùng chứa IOC, Spring. Theo mặc định, khi yêu cầu Ajax với DWR gọi
creator, đối tượng cụ thể được đặt trong phạm vi trang và do đó không còn tồn tại sau khi yêu cầu
hoàn tất. Trong trường hợp của CatalogDAO không trạng thái, điều này là tốt.
Thuộc tính javascript của phần tử create xác định tên mà đối tượng sẽ có thể truy cập từ mã
JavaScript. Được lồng bên trong phần tử create , phần tử param xác định lớp Java mà phần tử
creator sẽ tạo ra. Cuối cùng, các phần tử, include xác định các tên của các phương thức sẽ được
trưng ra. Việc bắt đầu các phương thức để trưng ra là thực tế tốt để tránh vô tình cho phép truy cập
chức năng có thể gây hại -- nếu phần tử này được bỏ qua, tất cả các phương thức của lớp sẽ được
trưng ra các cuộc gọi từ xa. Lần lượt, bạn có thể sử dụng các phần tử exclude (loại trừ) để xác định
chỉ những phương thức nào bạn muốn ngăn chặn truy cập vào.
Phần tử convert
Trong khi các creator có liên quan tới việc trưng ra các lớp và các phương thức của chúng cho
việc truy cập Web từ xa, các convertor (trình chuyển đổi) có liên quan đến các kiểu tham số và kiểu
trả về của các phương thức đó. Vai trò của phần tử convert là để nói cho DWR biết cách chuyển
đổi các kiểu dữ liệu giữa việc thể hiện đối tượng Java phía máy chủ của chúng và việc thể hiện
JavaScript được tuần tự hóa và ngược lại.
DWR tự động dàn xếp các kiểu dữ liệu đơn giản giữa các thể hiện Java và JavaScript. Các kiểu này
gồm các gốc Java, cùng với các thể hiện lớp tương ứng của chúng, cũng như các kiểu Strings và
Dates, Mảng và các kiểu bộ sưu tập. DWR cũng có thể chuyển đổi JavaBeans thành các thể hiện
JavaScript, nhưng vì lý do bảo mật, việc thực hiện như vậy cần cấu hình rõ ràng.
Phần tử convert trong Liệt kê 2 báo cho DWR sử dụng trình chuyển đổi bean dựa trên phản chiếu
của nó cho các Item được trả về bằng các phương thức đã cho biết của CatalogDAO và chỉ định các
bộ phận của Item nào cần có trong tuần tự hóa. Các bộ phận được xác định bằng cách sử dụng quy
ước đặt tên JavaBean, vì thế DWR sẽ gọi các phương thức get tương ứng. Trong trường hợp này,
tôi đang bỏ qua trường price (giá cả) bằng số và thay vào đó có trường formattedPrice, có sẵn
định dạng tiền tệ để hiển thị.
Lúc này tôi đã sẵn sàng triển khai dwr.xml của tôi sang thư mục WEB-INF của ứng dụng Web của
mình, ở đó DWR servlet sẽ chọn nó. Tuy nhiên, trước khi tiếp tục, để đảm bảo rằng tất cả mọi thứ
đang làm việc như mong đợi là một ý tưởng tốt.
Thử nghiệm triển khai
Nếu định nghĩa web.xml của DWRServlet đặt init-paramdebug là true (đúng), thì sau đó chế độ thử
nghiệm vô cùng có ích của DWR được kích hoạt. Việc chuyển hướng tới /{your-web-app}/dwr/ sẽ
đưa ra một danh sách các lớp của bạn đã được DWR đặt cấu hình truy cập từ xa. Việc nhấn chuột
sẽ đưa bạn tới màn hình trạng thái cho một lớp cụ thể. Trang thử nghiệm DWR cho CatalogDAO
được hiển thị trong Hình 2. Cũng như việc cung cấp một thẻ script để dán vào các trang Web của
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 4 của 16
ibm.com/developerWorks/vn/
developerWorks®
bạn, việc trỏ tới JavaScript được tạo của DWR cho lớp đó, màn hình này cũng cung cấp một danh
sách các phương thức của lớp. Danh sách này gồm các phương thức được thừa kế từ các siêu kiểu
của lớp, nhưng chỉ những có các phương thức nào mà tôi xác định rõ ràng để truy cập từ xa trong
dwr.xml được đánh dấu là có thể truy cập được.
Hình 2. Trang thử nghiệm DWR cho CatalogDAO
Có thể nhập các giá trị tham số vào các hộp văn bản bên cạnh các phương thức được phép truy
cập và nhấn nút Execute (Thực hiện) để gọi chúng. Trả lời của máy chủ sẽ được hiển thị bằng cách
sử dụng ký hiệu của JSON trong một hộp cảnh báo, trừ khi nó là một giá trị đơn giản; trong trường
hợp này nó được hiển thị nội tuyến dọc theo các phương thức. Các trang thử nghiệm này rất có ích.
Không chỉ chúng cho phép bạn dễ dàng kiểm các lớp và phương thức nào được trưng ra để truy
cập từ xa, mà bạn cũng có thể thử nghiệm xem mỗi phương thức có đang hoạt động như mong đợi
không.
Một khi bạn đã hài lòng rằng các phương thức được truy cập từ xa của bạn đang hoạt động đúng,
bạn có thể sử dụng các stub (nhánh rẽ) JavaScript được tạo của DWR để gọi các đối tượng phía
máy chủ của bạn từ mã phía máy khách.
Gọi một đối tượng được truy cập từ xa
Việc ánh xạ giữa các phương thức đối tượng Java được truy cập từ xa và các hàm stub JavaScript
tương ứng của chúng là đơn giản. Dạng chung là JavaScriptName.methodName(methodParams ...,
callBack), ở đây JavaScriptName là bất kỳ tên đã được xác định như là thuộc tính javascript
của creator, methodParams thể hiện các tham số n của phương thức Java và callback (gọi lại) là
một hàm JavaScript, nó sẽ được gọi với giá trị trả về của phương thức Java. Nếu bạn quen với
Ajax, bạn sẽ nhận ra cơ chế gọi lại như là cách tiếp cận thông thường cho sự không đồng bộ của
XMLHttpRequest.
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 5 của 16
developerWorks®
ibm.com/developerWorks/vn/
Trong kịch bản ví dụ này, tôi sử dụng các hàm JavaScript trong Liệt kê 3 để thực hiện tìm kiếm và
cập nhật giao diện người dùng theo các kết quả tìm kiếm. Danh sách này cũng sử dụng các hàm
tiện ích từ util.js của DWR. Có chú ý đặc biệt là hàm JavaScript có tên là $(), nó có thể được
dùng như một phiên bản được cải tiến của document.getElementById(). Tất nhiên là dễ dàng định
kiểu hơn. Nếu bạn đã sử dụng thư viện JavaScript nguyên mẫu, bạn sẽ quen thuộc với hàm này.
Liệt kê 3. Gọi phương thức findItems remoted () từ máy khách
/*
* Handles submission of the search form
*/
function searchFormSubmitHandler() {
// Obtain the search expression from the search field
var searchexp = $("searchbox").value;
// Call remoted DAO method, and specify callback function
catalog.findItems(searchexp, displayItems);
// Return false to suppress form submission
return false;
}
/*
* Displays a list of catalog items
*/
function displayItems(items) {
// Remove the currently displayed search results
DWRUtil.removeAllRows("items");
if (items.length == 0) {
alert("No matching products found");
$("catalog").style.visibility = "hidden";
} else {
DWRUtil.addRows("items",items,cellFunctions);
$("catalog").style.visibility = "visible";
}
}
Trong hàm searchFormSubmitHandler() ở trên, tất nhiên mã quan tâm là
catalog.findItems(searchexp, displayItems);. Một dòng mã này là tất cả những thứ cần thiết
để gửi một XMLHttpRequest qua mạng tới DWR servlet và gọi hàm displayItems() với trả lời của
đối tượng được truy cập từ xa.
Hàm gọi lại displayItems() tự nó được gọi với một mảng của các thể hiện Item. Mảng này được
được chuyển qua tới hàm tiện ích DWRUtil.addRows() cùng với mã nhận dạng (ID) của bảng cần
điền vào và một mảng các hàm. Càng có nhiều hàm trong mảng này thì càng có nhiều ô trong mỗi
hàng của bảng. Mỗi hàm được gọi lần lượt với một Item từ mảng đó và sẽ trả về nội dung để điền
vào ô tương ứng.
Trong trường hợp này, tôi muốn mỗi hàng trong bảng các mục hiển thị tên của mục, mô tả và giá
cả, cũng như một nút Add to Cart (Thêm vào giỏ hàng) cho mục đó trong cột cuối. Liệt kê 4 cho
thấy mảng các hàm của ô thực hiện việc này:
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 6 của 16
ibm.com/developerWorks/vn/
developerWorks®
Liệt kê 4. Mảng các hàm của ô để điền vào bảng các mục
/*
* Array of functions to populate a row of the items table
* using DWRUtil's addRows function
*/
var cellFunctions = [
function(item) { return item.name; },
function(item) { return item.description; },
function(item) { return item.formattedPrice; },
function(item) {
var btn = document.createElement("button");
btn.innerHTML = "Add to cart";
btn.itemId = item.id;
btn.onclick = addToCartButtonHandler;
return btn;
}
];
Ba dòng đầu tiên của các hàm này chỉ đơn giản trả về nội dung của các trường có trong convertor
của Item trong dwr.xml. Hàm cuối tạo ra một nút nhấn, gắn các mã nhận dạng của Item tới nút đó
và xác định rằng một hàm có tên là addToCartButtonHandler sẽ được gọi khi nút đó được nhấn.
Hàm này là điểm nhập vào cho trường hợp sử dụng thứ hai: thêm một Item vào giỏ mua hàng.
Triển khai thực hiện giỏ mua hàng
An ninh trong DWR
DWR đã được thiết kế luôn tính đến an ninh. Sử dụng dwr.xml để chỉ lập danh sách trắng
các lớp và các phương thức nào đó mà bạn muốn truy cập từ xa tránh vô tình để lộ ra các
chức năng có thể được khai thác với chủ tâm phá hoại. Thêm vào đó, sử dụng Chế độ kiểm tra
(Test Mode) gỡ rối, rất dễ dàng để kiểm tra tất cả các lớp và các phương thức đã trưng ra cho
Web
DWR cũng hỗ trợ an ninh theo vai trò. Bạn có thể xác định vai trò J2EE mà một người sử
dụng đang truy cập một bean cụ thể thông qua cấu hình creator của nó. Bằng cách triển
khai nhiều cá thể URL được bảo mật của DWRServlet, mỗi cá thể có tệp cấu hình dwr.xml
riêng của nó, bạn cũng có thể cung cấp các tập hợp khác nhau của người dùng với chức năng
được truy cập từ xa khác nhau.
Thể hiện Java của giỏ mua hàng của người dùng được dựa trên Map. (Bản đồ). Khi một Item được
thêm vào giỏ hàng này Item tự nó được chèn vào trong Map như là khoá. Giá trị tương ứng trong
Map là một Integer (số nguyên) thể hiện số lượng của Item cụ thể trong giỏ hàng này. Vì vậy
Cart.java có một trường, contents (các nội dung), được khai báo như là Map<Item,Integer>.
Việc sử dụng các kiểu phức tạp như là các khóa băm (hash key ) đặt ra vấn đề cho DWR -- trong
JavaScript, các khóa mảng phải là các chữ. Kết quả là contentsMap có thể không được DWR
chuyển đổi như nó có. Tuy nhiên, với các mục đích của giao diện người dùng của giỏ mua hàng, tất
cả những thứ mà người sử dụng cần phải thấy là tên và số lượng của mỗi mục trong giỏ hàng này. Vì
vậy, tôi có thể thêm một phương thức có tên là getSimpleContents() vào Cart, có contentsMap và
xây dựng một Map<String,Integer> đơn giản từ nó, thể hiện chỉ có tên và số lượng của mỗi Item.
Việc thể hiện bản đồ chuỗi có khóa này có thể đơn giản được các trình biến đổi gắn sẵn của DWR
chuyển đổi thành JavaScript.
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 7 của 16
developerWorks®
ibm.com/developerWorks/vn/
Một trường khác của Cart mà máy khách có quan tâm đến là totalPrice, thể hiện tổng số của
tất cả mọi thứ trong giỏ hàng. Như với Item, tôi đã cung cấp một bộ phận tổng hợp có tên là
formattedTotalPrice là một thể hiện String (Chuỗi) được định dạng sẵn của tổng số.
Chuyển đổi giỏ hàng
Thay vì có mã khách hàng thực hiện hai cuộc gọi vào Cart, một để nhận được các nội dung và một
cho giá tổng, tôi muốn gửi tất cả các dữ liệu này đến máy khách hàng cùng một lúc. Để thực hiện
điều này tôi đã thêm một phương thức mới lạ, hiển thị trong Liệt kê 5::
Liệt kê 5. Phương thức Cart.getCart ()
/**
* Returns the cart itself - for DWR
* @return the cart
*/
public Cart getCart() {
return this;
}
Trong khi phương thức này sẽ hoàn toàn dư thừa trong mã Java chuẩn (vì bạn đã có một tham
chiếu đến Cart nếu bạn đang gọi phương thức đó), thì nó cho phép một máy khách DWR có Cart
tự sắp xếp thứ tự theo JavaScript.
Ngoài getCart(), phương thức khác mà cần được truy cập từ xa là addItemToCart(). Phương thức
này có một thể hiện String của mã nhận dạng (ID) của mục của danh mục, thêm mục đó vào Cart,
và cập nhật tổng giá. Phương thức này cũng trả về Cart, để cho mã máy khách có thể được cập
nhật các nội dung Cart và nhận trạng thái mới của nó chỉ trong một hoạt động.
Liệt kê 6 là tệp cấu hình dwr.xml được mở rộng gồm các thông tin cấu hình thêm để truy cập từ xa
lớp Cart:
Liệt kê 6. dwr.xml đã thay đổi kết hợp lớp Cart
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
<allow>
<create creator="new" javascript="catalog">
<param name="class"
value="developerworks.ajax.store.CatalogDAO"/>
<include method="getItem"/>
<include method="findItems"/>
</create>
<convert converter="bean" match="developerworks.ajax.store.Item">
<param name="include"
value="id,name,description,formattedPrice"/>
</convert>
<create creator="new" scope="session" javascript="Cart">
<param name="class" value="developerworks.ajax.store.Cart"/>
<include method="addItemToCart"/>
<include method="getCart"/>
</create>
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 8 của 16
ibm.com/developerWorks/vn/
developerWorks®
<convert converter="bean" match="developerworks.ajax.store.Cart">
<param name="include" value="simpleContents,formattedTotalPrice"/>
</convert>
</allow>
</dwr>
Trong phiên bản này của dwr.xml, tôi đã thêm cả một creator lẫn một convertor cho Cart. Phần tử
create xác định rằng các phương thức addItemToCart() và getCart() cần được truy cập từ xa và
quan trọng là, cá thể Cart được tạo sẽ được đặt trong phiên giao dịch của người dùng. Kết quả là,
nội dung của giỏ hàng sẽ vẫn còn giữa các yêu cầu của người sử dụng.
Phần tử convert cho Cart là cần thiết vì các phương thức Cart được truy cập từ xa tự trả về Cart.
Ở đây tôi đã xác định rằng các bộ phận trong Cart nên được trình bày dưới dạng JavaScript được
tuần tự hóa của nó, là bản đồ simpleContents và String formattedTotalPrice.
Nếu bạn thấy hơi khó hiểu, hãy nhớ rằng create xác định các phương thức phía máy chủ trên Cart
có thể được một máy khách DWR gọi và phần tử convert xác định các bộ phận có trong việc sắp
xếp theo thứ tự JavaScript của Cart.
Bây giờ tôi có thể triển khai thực hiện mã phía máy khách để gọi các phương thức Cart được truy
cập từ xa của tôi.
Gọi các phương thức Cart được truy cập từ xa
Trước hết, khi trang Web cửa hàng nạp vào lần đầu, tôi muốn kiểm tra trạng thái của Cart được lưu
giữ trong phiên giao dịch, nếu có. Điều này là cần thiết vì người sử dụng có thể đã thêm các mục
vào Cart và sau đó đã làm mới trang này hoặc đã chuyển hướng đi và sau đó quay lại một lần nữa.
Trong những trường hợp này, trang đã nạp lại cần phải tự đồng bộ với dữ liệu Cart trong phiên này.
Tôi có thể thực hiện việc này bằng một cuộc gọi được thực hiện trong hàm onload của trang, như
sau: Cart.getCart(displayCart). Lưu ý rằng displayCart() là một hàm gọi lại được gọi với các dữ
liệu trả lời Cart từ máy chủ.
Nếu một Cart đã có trong phiên giao dịch, thì sau đó creator sẽ lấy nó ra và gọi phương thức
getCart() của nó. Nếu không có Cart nào trong phiên giao dịch này, thì sau đó creator sẽ tạo một
cái mới, đặt nó trong phiên giao dịch, và gọi phương thức getCart().
Liệt kê 7 cho thấy việc thực hiện hàm addToCartButtonHandler(), nó được gọi khi nhấn nút Add to
Cart (Thêm vào giỏ hàng) của mục đó:
Liệt kê 7. Thực hiện addToCartButtonHandler ()
/*
* Handles a click on an Item's "Add to Cart" button
*/
function addToCartButtonHandler() {
// 'this' is the button that was clicked.
// Obtain the item ID that was set on it, and
// add to the cart.
Cart.addItemToCart(this.itemId,displayCart);
}
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 9 của 16
developerWorks®
ibm.com/developerWorks/vn/
Với DWR đang giữ tất cả các giao tiếp, hành vi thêm vào giỏ hàng trên máy khách đúng là một
hàm một dòng. Liệt kê 8 cho thấy đoạn mã cuối cùng của trò chơi ghép hình này -- thực hiện cuộc
gọi lại displayCart(), cập nhật giao diện người dùng với trạng thái của Cart:
Liệt kê 8. Thực hiện displayCart ()
/*
* Displays the contents of the user's shopping cart
*/
function displayCart(cart) {
// Clear existing content of cart UI
var contentsUL = $("contents");
contentsUL.innerHTML="";
// Loop over cart items
for (var item in cart.simpleContents) {
// Add a list element with the name and quantity of item
var li = document.createElement("li");
li.appendChild(document.createTextNode(
cart.simpleContents[item] + " x " + item
));
contentsUL.appendChild(li);
}
// Update cart total
var totalSpan = $("totalprice");
totalSpan.innerHTML = cart.formattedTotalPrice;
}
Điều quan trọng cần nhớ là simpleContents một mảng JavaScript ánh xạ các String tới các số. Mỗi
chuỗi có tên của một mục và số tương ứng trong mảng kết hợp là số lượng của mục hàng đó trong
giỏ hàng này. Vì vậy biểu thức cart.simpleContents[item] + " x " + item đánh giá theo, ví dụ,
"2 x Oolong 128MB CF Card".
Ứng dụng kho DWR
Hình 3 cho thấy ứng dụng Ajax dựa trên DWR của tôi đang hoạt động, hiển thị các mục được lấy ra
bằng một việc tìm kiếm với giỏ mua hàng của người dùng ở bên phải:
Hình 3. Ứng dụng kho Ajax dựa trên DWR đang hoạt động
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 10 của 16
ibm.com/developerWorks/vn/
developerWorks®
Ưu và nhược điểm của DWR
Xử lý cuộc gọi theo khối
Trong DWR, một vài cuộc gọi từ xa có thể được gửi đến máy chủ với một yêu cầu HTTP. Việc
gọi DWREngine.beginBatch() báo cho DWR biết để không gửi các cuộc gọi từ xa tiếp
theo ngay lập tức, mà để thay thế hãy kết hợp chúng thành một yêu cầu được xử lý theo khối.
Một cuộc gọi đến DWREngine.endBatch() gửi yêu cầu được xử lý theo khối đến máy chủ.
Các cuộc gọi từ xa được thực hiện theo thứ tự trên phía máy chủ và sau đó mỗi cuộc gọi lại
JavaScript được gọi.
Việc xử lý theo khối có thể giúp làm giảm độ trễ theo hai cách: thứ nhất, bạn tránh chi phí
hoạt động của việc tạo một đối tượng XMLHttpRequest và thiết lập kết nối HTTP có liên
quan cho mỗi cuộc gọi. Thứ hai, trong một môi trường sản xuất, máy chủ Web sẽ không phải
đối phó với rất nhiều yêu cầu HTTP đồng thời, cải thiện thời gian trả lời.
Bạn đã thấy cách dễ dàng để thực hiện một ứng dụng Ajax có Java ở phía sau khi sử dụng DWR.
Mặc dù kịch bản ví dụ là một ứng dụng đơn giản và tôi đã có một cách tiếp cận gần như tối thiểu
để triển khai thực hiện các trường hợp sử dụng, bạn không nên đánh giá thấp số lượng công việc
mà công cụ DWR có thể tiết kiệm cho bạn hơn một cách tiếp cận Ajax được tạo tại chỗ. Trong khi
ở bài viết trước tôi đi qua tất cả các bước thiết lập bằng tay một yêu cầu và trả lời Ajax và chuyển
đổi một đồ thị đối tượng Java thành một thể hiện JSON, ở đây DWR đã làm tất cả các công việc
đó cho tôi. Tôi đã viết ít hơn 50 dòng mã JavaScript để triển khai thực hiện máy khách và ở phía
máy chủ, tất cả những thứ mà tôi đã làm đã tăng thêm JavaBeans thông thường của tôi bằng một
cặp các phương thức bổ sung.
Tất nhiên, mỗi công nghệ có nhược điểm của nó. Cũng như bất kỳ cơ chế RPC nào, trong DWR có
thể dễ quên rằng mỗi cuộc gọi mà bạn thực hiện trên các đối tượng được truy cập từ xa tốn kém
hơn nhiều so với một cuộc gọi hàm cục bộ. DWR thực hiện nhiều công việc về ẩn bộ máy Ajax,
nhưng điều quan trọng cần nhớ rằng mạng không trong suốt, có độ trễ liên quan đến việc thực hiện
cuộc gọi DWR và ứng dụng của bạn phải được kiến trúc để cho các phương thức được truy cập từ
xa có độ chi tiết thô. Đối với mục đích này addItemToCart() tự trả về Cart. Mặc dù nó đã có sẵn để
tạo cho addItemToCart() một phương thức trống, mỗi cuộc gọi DWR tới nó sau đó sẽ phải được
tiếp theo bằng một cuộc gọi đến getCart() để lấy ra trạng thái Cart đã thay đổi.
DWR có giải pháp riêng của mình cho vấn đề độ trễ trong việc xử lý theo khối cuộc gọi (xem phần
bên cạnh Xử lý cuộc gọi theo khối). Nếu bạn không thể cung cấp giao diện Ajax có độ chi tiết thô
thích hợp cho ứng dụng của bạn, thì hãy sử dụng xử lý theo khối cuộc gọi bất cứ ở đâu có thể để kết
hợp nhiều cuộc gọi từ xa vào trong một yêu cầu HTTP.
Tách mối quan tâm
Do tính chất của mình, DWR tạo một sự kết hợp chặt chẽ giữa mã phía máy khách và mã phía
máy chủ, với một số các hàm ý. Trước hết, các thay đổi với API của các phương thức được truy
cập từ xa cần phải được phản ánh trong JavaScript để gọi vào các nhánh DWR. Thứ hai (và đáng
kể hơn), sự kết hợp này làm cho các mối quan tâm phía máy khách lọt vào trong mã phía máy
chủ. Ví dụ, vì không phải tất cả các kiểu Java có thể được chuyển đổi thành JavaScript, đôi khi cần
thiết thêm các phương thức bổ sung cho các đối tượng Java để cho chúng có thể được truy cập
từ xa dễ dàng hơn. Trong kịch bản ví dụ, tôi giải quyết điều này bằng cách thêm một phương thức
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 11 của 16
developerWorks®
ibm.com/developerWorks/vn/
vào Cart. Tôi cũng đã thêm phương thức getCart(), nó có ích trong một
kịch bản DWR nhưng nếu không thì hoàn toàn thừa. Căn cứ vào sự cần thiết cho một API có độ chi
tiết thô trên các đối tượng được truy cập từ xa và vấn đề chuyển đổi các kiểu Java nào đó thành
JavaScript, bạn có thể thấy cách JavaBeans được truy cập từ xa có thể trở nên bị hỏng với các
phương thức chỉ có ích cho một máy khách Ajax.
getSimpleContents()
Để bắt đầu việc này, bạn có thể sử dụng các lớp của trình bao bọc (wrapper) để thêm các phương
thức DWR cụ thể cho JavaBeans cũ của bạn. Điều này có nghĩa là các máy khách Java của các
lớp JavaBean sẽ không nhìn thấy những điều sai lầm tăng thêm có liên kết với việc truy cập từ xa
và nó cũng sẽ cho phép bạn đưa ra các tên thân thiện hơn cho các phương thức được truy cập từ
xa -- ví dụ getPrice() thay cho getFormattedPrice(). Hình 4 hiển thị một lớp RemoteCart bao bọc
Cart để bổ sung chức năng DWR phụ:
Hình 4. RemoteCart bao bọc Cart cho chức năng truy cập từ xa
Cuối cùng, bạn cần phải nhớ rằng các cuộc gọi DWR Ajax là không đồng bộ và không nên dự kiến
trả về theo thứ tự mà chúng đã được gửi đi. Tôi bỏ qua rào cản nhỏ này trong mã ví dụ, nhưng
trong bài viết đầu tiên của loạt bài này, tôi đã giải thích cách đánh dấu thời gian các trả lời như là
một việc bảo vệ đơn giản dựa vào dữ liệu đến không theo thứ tự.
Kết luận
Như bạn đã thấy, DWR có rất nhiều thứ xảy ra -- nó cho phép bạn tạo một giao diện Ajax tới các
đối tượng miền phía máy chủ của bạn nhanh chóng và đơn giản, không cần phải viết bất kỳ mã
servlet nào, mã tuần tự hóa đối tượng hoặc mã XMLHttpRequest phía máy khách. Vô cùng đơn giản
để triển khai ứng dụng Web của bạn khi sử dụng DWR và các tính năng an ninh của DWR có thể
được tích hợp với một hệ thống xác thực dựa trên vai trò J2EE. Tuy nhiên DWR không thể áp dụng
cho mọi kiến trúc ứng dụng và nó yêu cầu bạn phải cung cấp một số ý tưởng cho việc thiết kế các
API của đối tượng miền của bạn.
Nếu bạn muốn tìm hiểu thêm về những ưu và nhược điểm của Ajax với DWR, điều tốt nhất là tải nó
cho chính mình và bắt đầu thử nghiệm. Trong khi DWR có nhiều tính năng mà tôi đã không trình
bày, mã nguồn bài viết này là một điểm khởi đầu tốt đẹp để có DWR cho một công việc. Xem Tài
nguyên để tìm hiểu thêm về Ajax, DWR và các công nghệ liên quan.
Một trong những điểm quan trọng nhất lấy ra từ loạt bài này là cho các ứng dụng Ajax, không có
giải pháp một kích cỡ phù hợp cho tất cả. Ajax là một lĩnh vực phát triển nhanh với các công nghệ
và các kỹ thuật mới đang nổi lên trong suốt thời gian qua. Trong ba bài viết của loạt bài này, tôi đã
tập trung vào việc bạn bắt đầu sử dụng các công nghệ Java trong tầng Web của ứng dụng Ajax -Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 12 của 16
ibm.com/developerWorks/vn/
developerWorks®
cho dù bạn chọn một cách tiếp cận dựa trên XMLHttpRequest với một khung công tác tuần tự hóa
đối tượng hay trừu tượng mức độ cao hơn của DWR. Hãy theo dõi các bài viết tiếp theo khám phá
Ajax cho các nhà phát triển Java trong những số tháng tới.
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 13 của 16
developerWorks®
ibm.com/developerWorks/vn/
Các tải về
Mô tả
Tên
Kích thước
DWR source code
j-ajax3dwr.zip
301 KB
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 14 của 16
ibm.com/developerWorks/vn/
developerWorks®
Tài nguyên
Học tập
• "Gọi các dịch vụ Web SOAP với AJAX, Phần 1: Xây dựng máy khách các dịch vụ
Web" (James Snell, developerWorks, 10.2005): Thực hiện một máy khách các dịch vụ Web
SOAP bằng cách sử dụng Ajax.
• "Ajax cho các nhà phát triển Java: Tuần tự hóa đối tượng Java cho Ajax " (Philip McCarthy,
developerWorks, 10.2005):" Tìm hiểu các cách tiếp cận tới sự tuần tự hóa dữ liệu trong các
ứng dụng Ajax.
• "Ajax cho các nhà phát triển Java: Xây dựng các ứng dụng Java năng động" (Philip McCarthy,
developerWorks, 09. 2005): Các bước đầu tiên với Ajax.
• Sổ tay DWR: Một giới thiệu về Ajax và DWR
• "Phát triển các ứng dụng AJAX Easy Way" (Java.net, 08. 2005): Người tạo DWR Joe Walker
đang viết một máy chủ trò chuyện Ajax đơn giản.
• Xem hướng dẫn Một khả năng lựa chọn tạo mã Ajax với Java là Bộ công cụ Ajax (Sajax) đơn
giản để tìm hiểu cách để bắt đầu với Sajax.
• Vùng công nghệ Java: Tìm các bài viết về mọi khía cạnh của lập trình Java.
Lấy sản phẩm và công nghệ
• Tải về DWR: Nhận phân phối DWR jar mới nhất.
• JSON-RPC-Java: Một máy Ajax-RPC thay thế cho Java.
Thảo luận
• Trang Java.net của DWR: Đăng ký danh sách gửi thư của DWR.
• developerWorks blogs: Dành tâm trí cho cộng đồng developerWorks.
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 15 của 16
developerWorks®
ibm.com/developerWorks/vn/
Đôi nét về tác giả
Philip McCarthy
Philip McCarthy là nhà tư vấn phát triển phần mềm chuyên về các công nghệ Java
và Web. Ông hiện đang làm việc trong dự án nền tảng phương tiện kỹ thuật số của
Hewlett Packard tại HP Labs, Bristol. Trong những năm gần đây Phil đã phát triển một
số các khách hàng Web phong phú sử dụng truyền dẫn máy chủ không đồng bộ và
kịch bản lệnh DOM. Ông vui mừng vì chúng ta có một tên cho chúng. Bạn có thể liên
lạc với Phil tại [email protected].
© Copyright IBM Corporation 2009
(www.ibm.com/legal/copytrade.shtml)
Nhẫn hiệu đăng ký
(www.ibm.com/developerworks/vn/ibm/trademarks/)
Ajax cho các nhà phát triển Java: Ajax với Direct Web Remoting
Trang 16 của 16