11.1.3 试用DWR
上一节的介绍中,Java自带类java.util.Date被用来示范如何将服务器端Java类暴露给浏览器端Javascript远程调用。这一节将使用自定义的类来展示DWR框架的具体应用。
接下来的例子采用了基于网上商店的模型,包含一个基本的产品表示类Item和一个数据存储查询访问对象CatalogDAO类。Item是一个普通的Java类,包含id,name,description,price四个属性及相应的geter,setter方法;CatalogDAO则包含getItem,findItems两个方法,getItem方法通过输入id参数取得特定的Item,findItems则以List形式返回当前全部的Item。在实际案例中,CatalogDAO的getItem和findItems方法所取得的数据一般来自持久化介质,如数据库。这里仅为示范及测试所需,所以返回硬编码,其大致代码如例程11-4所示。
例程11-4 Item
package com.ajaxlab.ajax;
public class Item {
private String id = "";
private String name = "";
private String description = "";
private int price = 0;
public Item() {
}
public Item(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getFormattedPrice() {
return "$"+String.valueOf(price);
}
}
例程11-5 CatalogDAO
package com.ajaxlab.ajax;
import java.util.List;
import java.util.ArrayList;
public class CatalogDAO {
public CatalogDAO() {
}
public Item getItem(String id) {
Item item = new Item("产品-"+id);
item.setName("新品-"+id);
item.setPrice(100);
item.setDescription("中国制造.");
return item;
}
public List findItems(String expression) {
List list = new ArrayList();
Item item1 = new Item("产品-001");
item1.setName("新品-001");
item1.setDescription(expression);
item1.setPrice(10);
Item item2 = new Item("产品-002");
item2.setName("新品-002");
item2.setDescription(expression);
item2.setPrice(15);
Item item3 = new Item("产品-003");
item3.setName("新品-003");
item3.setDescription(expression);
item3.setPrice(35);
list.add(item1);
list.add(item2);
list.add(item3);
return list;
}
}
由于要将Item和CatalogDAO暴露给浏览器端Javascript远程调用,所以Item和CatalogDAO都提供了无参数的构造方法。这个例子将演示两个简单的用例:一是在文本框中输入产品ID,搜索对应的产品;二是单击“浏览产品”按钮,返回当前全部库存产品。
接下来设置DWR部署描述文件dwr.xml。create元素部分将CatalogDAO类的getItem,findItems方法暴露出来,convert元素则将Item类转化为普通的Javascript对象。DWR自动在Java和Javascript表示之间调整简单数据类型。这些类型包括Java基本类型及其各自的类表示,比如int和Integer,以及String、Date、数组和集合类型。在Item类中,为了显示格式化后的产品价格,增加了getFormattedPrice方法。dwr.xml的代码如例程11-6所示。
例程11-6 dwr.xml
<!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="CatalogDAO">
<param name="class" value="com.ajaxlab.ajax.CatalogDAO"/>
<include method="getItem"/>
<include method="findItems"/>
</create>
<convert converter="bean" match="com.ajaxlab.ajax.Item">
<param name="include" value="id,name,description,formatted- Price" />
</convert>
</allow>
</dwr>
确保Web应用程序下的web.xml已经按照12.4.3节第二步添加了相应的Servlet映射,将dwr.xml拷贝到{APPLICATION_WEB_HOME}\WEB-INF目录下。启动Tomcat,打开浏览器,导航到http://localhost:8080/ajaxlab/dwr/index.html就能够看到CatalogDAO暴露出来的方法了,如图11-5和图11-6所示。

图11-5 暴露给Javascript的Java类

图11-6 CatalogDAO供Javascript远程调用的方法
在getItem,findItems两个方法后面的文本框的双引号中输入任何字符,单击“Execute”按钮。服务器返回的数据以弹出对话框的形式显示出来。getItem返回一个Javascript对象,findItems则返回一个数组直接量,如图11-7和图11-8所示。
Java类方法已经按照预定设想暴露给Javascript了,按照DWR的设计思想,在Web页面中,可以使用CatalogDAO.methodName(parameter1,parameter2…,callback)的方式调用CatalogDAO的方法。其中,callback是回调函数的名称。DWR并未严格的检查是否传送parameter参数给CatalogDAO方法。

图11-7 CatalogDAO返回的Javascript对象 图11-8 CatalogDAO返回的数组直接量
本例的Web页面包含两个文本框和两个按钮。文本框分别用来输入产品编号和产品描述,两个普通按钮则用来根据输入显示单个产品细节和全部产品列表。页面中还包括两个事件响应函数和两个回调函数,分别用来响应按钮单击事件和处理响应数据。
事件响应函数doSearch将输入框item_id的值连同回调函数showItem的名称作为参数传递给CatalogDAO.getItem方法。而事件响应函数doList则将输入框item_description的值连同回调函数showList的名称作为参数传递给CatalogDAO.findItems方法。
在回调函数showItem和showList中,使用到了名为$()的Javascript函数。这个函数是在DWR的util.js定义的,其功能与“document.getElementById()”相当。util.js中还定义了大量方便开发人员操作的便捷函数,具体可以参考util.js源码。sample12_2.jsp的Javascript部分代码如下所示,相应的运行效果如图11-9所示。

图11-9 使用DWR实现产品搜索
例程11-7 sample12_2.jsp
<script language="javascript">
function doSearch() {
var item_id = document.form1.item_id.value;
if(item_id!="") CatalogDAO.getItem(item_id,showItem);
else document.getElementById("item_detail").innerHTML = "请输入产品编号。";
}
function showItem(data) {
var element = $("item_detail");
var str = "";
str = "<table width='600' cellspacing='0' cellpadding='4' border= '1'>";
str = str + "<caption>产品信息</caption>";
str = str + "<thead><td width='100'>编号</td><td width='100'>名称</td><td width='100'>价格</td><td width='300'>描述</td></thead>\r\n";
str = str + "<tbody><td width='100'>"+data.id+"</td><td width= '100'>"+data.name+"</td><td width='100'>"+data.formattedPrice+"</td><td width='300'>"+data.description+"</td></tbody>\r\n";
str = str + "</table>";
element.innerHTML = str;
}
function doList() {
CatalogDAO.findItems("中国制造。",showList);
}
function showList(data) {
var root = $("item_list");
var str = "<table width='600' cellspacing='0' cellpadding='4' border='1'>";
str = str + "<caption>全部产品</caption>";
str = str + "<thead><td width='100'>编号</td><td width='200'>名称</td><td width='100'>价格</td><td width='200'>描述</td></thead>\r\n";
str = str + "<tbody>\r\n";
for(var i=0;i<data.length;i++) {
str = str + "<thead><td width='100'>"+data[i].id+"</td><td width='200'>"+data[i].name+"</td><td width='100'>"+data[i].formattedPrice+"</td><td width='200'>"+data[i].description+"</td></thead>\r\n";
}
str = str + "</tbody></table>";
root.innerHTML = str;
}
</script>







