- 浏览: 422865 次
- 性别:
文章分类
最新评论
-
wrw_ahut:
你这个怎么停下来?怎么跳转activity
Android启动界面实现 -
huiqoo:
高仿UC半透明MENU菜单(有图有真相) -
wenzhixin:
多谢分享~
Android启动界面实现 -
orange9711:
学习学习
Android启动界面实现 -
qinweiping:
问下楼主 好像这个反编译 只能看到程序的主体结构吧 还是和源程 ...
APK反编译利器Apktool下载及用法介绍
DWR 是一个开放源码的使用 Apache 许可协议的解决方案,它包含服务器端 Java 库、一个 DWR servlet 以及 JavaScript
库。虽然 DWR 不是 Java 平台上唯一可用的 Ajax-RPC 工具包,但是它是最成熟的,而且提供了许多有用的功能。请参阅
参考资料,在继续学习之前下载 DWR。
从最简单的角度来说,DWR 是一个引擎,可以把服务器端 Java 对象的方法公开给 JavaScript 代码。使用 DWR 可以有效
地从应用程序代码中把 Ajax 的全部请求-响应循环消除掉。这意味着客户端代码再也不需要直接处理 XMLHttpRequest
对
象或者服务器的响应。不再需要编写对象的序列化代码或者使用第三方工具才能把对象变成 XML。甚至不再需要编写
servlet 代码把 Ajax 请求调整成对 Java 域对象的调用。
DWR 是作为 Web 应用程序中的 servlet 部署的。把它看作一个黑盒子,这个 servlet 有两个主要作用:首先,对于公开的
每个类,DWR 动态地生成包含在 Web 页面中的 JavaScript。生成的 JavaScript 包含存根函数,代表 Java 类上的对应方
法并在幕后执行 XMLHttpRequest
。这些请求被发送给 DWR,这时它的第二个作用就是把请求翻译成服务器端 Java 对象
上的方法调用并把方法的返回值放在 servlet 响应中发送回客户端,编码成 JavaScript。DWR 还提供了帮助执行常见的用户
界面任务的 JavaScript 工具函数。
在更详细地解释 DWR 之前,我要介绍一个简单的示例场景。像在前一篇文章中一样,我将采用一个基于在线商店的最小模
型,这次包含一个基本的产品表示、一个可以包含产品商品的用户购物车以及一个从数据存储查询产品的数据访问对象
(DAO)。Item
类与前一篇文章中使用的一样,但是不再实现任何手工序列化方法。图 1 说明了这个简单的设置:
图 1. 说明 Cart、CatalogDAO 和 Item 类的类图
在这个场景中,我将演示两个非常简单的用例。第一,用户可以在目录中执行文本搜索并查看匹配的商品。第二,用户可以
添加商品到购物车中并查看购物车中商品的总价。
DWR 应用程序的起点是编写服务器端对象模型。在这个示例中,我从编写 DAO 开始,用它提供对产品目录数据存储的搜索
功能。CatalogDAO.java
是一个简单的无状态的类,有一个无参数的构造函数。清单 1 显示了我想要公开给 Ajax 客户的
Java 方法的签名:
清单 1. 通过 DWR 公开的 CatalogDAO 方法
/** |
接下来,我需要配置 DWR,告诉它 Ajax 客户应当能够构建
CatalogDAO
并调用这些方法。我在清单 2 所示的 dwr.xml 配置文件中做这些事:
清单 2. 公开 CatalogDAO 方法的配置
<!----> <dwr></dwr> <allow></allow> <create creator="new" javascript="catalog"></create> <include method="getItem"></include> <include method="findItems"></include> |
dwr.xml 文档的根元素是
dwr
。在这个元素内是 allow
元素,它指定 DWR 进行远程的类。allow
的两个子元素是 create
和 convert
。
create
元素告诉 DWR 应当公开给 Ajax 请求的服务器端类,并定义 DWR 应当如何获得要进行远程的类的实例。这里的
creator
属性被设置为值 new
,这意味着 DWR 应当调用类的默认构造函数来获得实例。其他的可能有:通过代码段用
Bean 脚本框架(Bean Scripting Framework,BSF)创建实例,或者通过与 IOC 容器 Spring 进行集成来获得实例。默认
情况下,到 DWR 的 Ajax 请求会调用 creator
,实例化的对象处于页面范围内,因此请求完成之后就不再可用。在无状态
的 CatalogDAO
情况下,这样很好。
create
的 javascript
属性指定从 JavaScript 代码访问对象时使用的名称。嵌套在 create
元素内的 param
元素指定
creator
要创建的 Java 类。最后,include
元素指定应当公开的方法的名称。显式地说明要公开的方法是避免偶然间允许
访问有害功能的良好实践 —— 如果漏了这个元素,类的所有方法都会公开给远程调用。反过来,可以用 exclude
元素指定
那些想防止被访问的方法。
creator
负责公开用于 Web 远程的类和类的方法,convertor
则负责这些方法的参数和返回类型。convert
元素的作用
是告诉 DWR 在服务器端 Java 对象表示和序列化的 JavaScript 之间如何转换数据类型。
DWR 自动地在 Java 和 JavaScript 表示之间调整简单数据类型。这些类型包括 Java 原生类型和它们各自的类表示,还有
String、Date、数组和集合类型。DWR 也能把 JavaBean 转换成 JavaScript 表示,但是出于安全性的原因,做这件事要求
显式的配置。
清单 2 中的 convert
元素告诉 DWR 用自己基于反射的 bean 转换器处理 CatalogDAO
的公开方法返回的 Item
,并指定
序列化中应当包含 Item
的哪个成员。成员的指定采用 JavaBean 命名规范,所以 DWR 会调用对应的 get
方法。在这个示
例中,我去掉了数字的 price
字段,而是包含了 formattedPrice
字段,它采用货币格式进行显示。
现在,我准备把 dwr.xml 部署到 Web 应用程序的 WEB-INF
目录,在那里 DWR servlet 会读取它。但是,在继续之前,
确保每件事都按照希望的那样运行是个好主意。
如果 DWRServlet
的 web.xml
定义把 init-param
debug
设置为 true
,那么就启用了 DWR 非常有帮助的测试模式。
导航到 /{your-web-app}/dwr/
会把 DWR 配置的要进行远程的类列表显示出来。在其中点击,会进入指定类的状态屏幕。
CatalogDAO
的 DWR 测试页如图 2 所示。除了提供粘贴到 Web 页面的 script
标记(指向 DWR 为类生成的 JavaScript)
之外,这个屏幕还提供了类的方法列表。这个列表包括从类的超类继承的方法,但是只有在 dwr.xml
中显式地指定为远程
的才标记为可访问。
可以在可访问的方法旁边的文本框中输入参数值并点击 Execute 按钮调用方法。服务器的响应将在警告框中用 JSON 标注
显示出来,如果是简单值,就会内联在方法旁边直接显示。这个测试页非常有用。它们不仅允许检查公开了哪个类和方法用
于远程,还可以测试每个方法是否像预期的那样工作。
如果对远程方法的工作感到满意,就可以用 DWR 生成的 JavaScript 存根从客户端代码调用服务器端对象
远程 Java 对象方法和对应的 JavaScript 存根函数之间的映射很简单。通用的形式是
JavaScriptName.methodName(methodParams ..., callBack)
,其中 JavaScriptName
是 creator
的 javascript
属性指定的名称,methodParams
代表 Java 方法的 n 个参数,callback
是要用 Java 方法的返回值调用的
JavaScript 函数。如果熟悉 Ajax,可以看出这个回调机制是 XMLHttpRequest
异步性的常用方式。
在示例场景中,我用清单 3 中的 JavaScript 函数执行搜索,并用搜索结果更新用户界面。这个清单还使用来自 DWR 的
util.js
的便捷函数。要特别说明的是名为 $()
的 JavaScript 函数,可以把它当作 document.getElementById()
的
加速版。录入它当然更容易。如果您使用过 JavaScript 原型库,应当熟悉这个函数。
清单 3. 从客户机调用远程的 findItems()
/* |
在上面的 searchFormSubmitHandler()
函数中,我们感兴趣的代码当然是 catalog.findItems(searchexp,
。这一行代码就是通过网络向 DWR servlet 发送
displayItems);XMLHttpRequest
并用远程对象的响应调用
displayItems()
函数所需要的全部内容。
displayItems()
回调本身是由一个 Item
数组表示调用的。这个数组传递给 DWRUtil.addRows()
便捷函数,同时还有
要填充的表的 ID 和一个函数数组。表中每行有多少单元格,这个数组中就有多少个函数。按照顺序使用来自数组的 Item
逐个调用每个函数,并用返回的内容填充对应的单元格。
在这个示例中,我想让商品表中的每一行都显示商品的名称、说明和价格,并在最后一列显示商品的 Add to Cart 按钮。
清单 4 显示了实现这一功能的单元格函数数组:
清单 4. 填充商品表的单元格函数数组
/* |
前三个函数只是返回 dwr.xml 中 Item
的 convertor
包含的字段内容。最后一个函数创建一个按钮,把 Item
的 ID 赋给
它,并指定在点击按钮时应当调用名为 addToCartButtonHandler
的函数。这个函数是第二个用例的入口点:向购物车中
添加 Item
。
DWR 的安全性 DWR 设计时就考虑了安全性。使用 dwr.xml 明确地列出那些想做远程处理的类和方法,可以避免意外地把那些可能被恶意 DWR 也支持基于角色的安全性。通过 bean 的 |
用户购物车的 Java 表示基于 Map
。当 Item
添加到购物车中时,Item
本身作为键被插入 Map
。 Map
中对应的值是一个
Integer
,代表购物车中指定 Item
的数量。所以 Cart.java
有一个字段 contents
,声明为Map
。
使用复杂类型作为哈希键给 DWR 带来一个问题 —— 在 JavaScript 中,数组的键必须是标量的。所以,DWR 无法转换
contents
Map
。但是,对于购物车用户界面来说,用户需要查看的只是每个商品的名称和数量。所以我向 Cart
添加了一
个名为 getSimpleContents()
的方法,它接受 contents
Map
并根据它构建一个简化的 Map
,只代表每个 Item
的名称
和数量。这个用字符串作为键的 map 表示可以由 DWR 的转换器转换成 JavaScript。
客户对 Cart
感兴趣的其他字段是 totalPrice
,它代表购物车中所有商品的金额汇总。使用 Item
,我还提供了一个合成
的成员叫作formattedTotalPrice
,它是金额汇总的格式化好的 String
表示。
为了不让客户代码对 Cart
做两个调用(一个获得内容,一个获得总价),我想把这些数据一次全都发给客户。为了做到这一
点,我添加了一个看起来有点儿怪的方法,如清单 5 所示:
清单 5. Cart.getCart() 方法
/** |
虽然这个方法在普通的 Java 代码中可能完全是多余的(因为在调用这个方法时,已经有对 Cart
的引用),但它允许 DWR
客户让 Cart
把自己序列化成 JavaScript。
除了 getCart()
,需要远程化的另一个方法是 addItemToCart()
。这个方法接受目录 Item 的 ID 的 String
表示,把这
个商品添加到 Cart
中并更新总价。方法还返回 Cart
,这样客户代码在一个操作中就能更新 Cart
的内容并接收购物车的新
状态。
清单 6 是扩展的 dwr.xml 配置文件,包含 Cart
类进行远程所需要的额外配置:
清单 6. 修改过的 dwr.xml 包含了 Cart 类
<!----> <dwr></dwr> |
在这个版本的 dwr.xml
中,我添加了 Cart
的 creator
和 convertor
。create
元素指定应当把 addItemToCart()
和
getCart()
方法远程化,而且重要的是,生成的 Cart
实例应当放在用户的会话中。所以,购物车的内容在用户的请求之间
会保留。
Cart
的 convert
元素是必需的,因为远程的 Cart
方法返回的是 Cart
本身。在这里我指定在 Cart
的序列化 JavaScript
形式中应当存在的成员是 simpleContents
这个图和 formattedTotalPrice
这个字符串。
如果对这觉得有点儿不明白,那么只要记住 create
元素指定的是 DWR 客户可以调用的 Cart
服务器端方法,而 convert
元素指定在 Cart
的 JavaScript 序列化形式中包含的成员。
现在可以实现调用 Cart
的远程方法的客户端代码了。
首先,当商店的 Web 页首次装入时,我想检查保存在会话中的 Cart
的状态,看是否已经有一个购物车了。这是必需的,
因为用户可能已经向 Cart
中添加了商品,然后刷新了页面或者导航到其他地方之后又返回来。在这些情况下,重新载入的
页面需要用会话中的 Cart
数据对自己进行同步。我可以在页面的 onload 函数中用一个调用做到这一点,就像这样:
Cart.getCart(displayCart)
。请注意 displayCart()
是一个回调函数,由服务器返回的 Cart
响应数据调用。
如果 Cart
已经在会话中,那么creator
会检索它并调用它的 getCart()
方法。如果会话中没有 Cart
,那么 creator
会实例化一个新的,把它放在会话中,并调用 getCart()
方法。
清单 7 显示了 addToCartButtonHandler()
函数的实现,当点击商品的 Add to Cart 按钮时会调用这个函数:
清单 7. addToCartButtonHandler() 实现
/* |
由 DWR 负责所有通信,所以客户上的添加到购物车行为就是一个函数。清单 8 显示了这个示例的最后一部分 ——
displayCart()
回调的实现,它用 Cart
的状态更新用户界面:
/* |
在这里重要的是要记住,simpleContents
是一个把 String
映射到数字的 JavaScript 数组。每个字符串都是一个商品的名
称,关联数组中的对应数字就是购物车中该商品的数量。所以表达式 cart.simpleContents[item] + " x " + item
可
能就会计算出 “2 x Oolong 128MB CF Card
” 这样的结果。
图 3 显示了这个基于 DWR 的 Ajax 应用程序的使用情况:显示了通过搜索检索到的商品,并在右侧显示用户的购物车:
图 3. 基于 DWR 的 Ajax 商店应用程序的使用情况
调用批处理 在 DWR 中,可以在一个 HTTP 请求中向服务器发送多个远程调用。调用 批处理在两方面有助于降低延迟:第一,避免了为每个调用创建 |
现在可以看出用 DWR 实现由 Java 支持的 Ajax 应用程序有多么容易了。虽然示例场景很简单,我实现用例的手段也尽可能
少,但是不应因此而低估 DWR 引擎相对于自己设计 Ajax 应用程序可以节约的工作量。在前一篇文章中,我介绍了手工设计
Ajax 请求和响应、把 Java 对象图转化成JSON 表示的全部步骤,在这篇文章中,DWR 替我做了所有这些工作。我只编写了
不到 50 行 JavaScript 就实现了客户机,而在服务器端,我需要做的所有工作就是给常规的 JavaBean 加上一些额外方法。
当然,每种技术都有它的不足。同任何 RPC 机制一样,在 DWR 中,可能很容易忘记对于远程对象进行的每个调用都要比本
地函数调用昂贵得多。DWR 在隐藏 Ajax 的机械性方面做得很好,但是重要的是要记住网络并不是透明的 —— 进行 DWR
调用会有延迟,所以应用程序的架构应当让远程方法的粒度比较粗。正是为了这个目的,addItemToCart()
才返回Cart
本
身。虽然让 addItemToCart()
作为一个 void 方法可能更自然,但是这样的话对它的每个 DWR 调用后面都必须跟着一个
getCart()
调用以检索修改后的 Cart
状态。
对于延迟,DWR 在调用的批处理中有自己的解决方案(请参阅侧栏的调用批处理)。如果不能为应用程序提供适当粗粒度的
Ajax 接口,那么只要有可能把多个远程调用组合到一个 HTTP 请求中,就请使用调用批处理。
从实质上看,DWR 在客户端和服务器端代码间形成了紧密的耦合,这有许多含义:首先,远程方法 API 的变化需要在
DWR 存根调用的 JavaScript 上反映出来。第二(也是最明显的),这种耦合会造成对客户端的考虑会渗入服务器端代码。
例如,因为不是所有 Java 类型都能转化成 JavaScript,所以有时有必要给 Java 对象添加额外方法,好让它能够更容易
地远程化。在示例场景中,我通过把 getSimpleContents()
方法添加到 Cart
来解决这个问题。我还添加了
getCart()
方法,它在 DWR 场景中是有用的,但在其他场景中则完全是多余的。由于远程对象粗粒度 API 的需要以
及把某些 Java 类型转化成 JavaScript 的问题,所以可以看到远程 JavaBean 会被那些只对 Ajax 客户有用的方法
“污染”。
为了克服这个问题,可以使用包装器类把额外的特定于 DWR 的方法添加到普通 JavaBean。这意味着 JavaBean 类的
Java 客户可能看不到与远程相关联的额外的毛病,而且也允许给远程方法提供更友好的名称 —— 例如用 getPrice()
代替 getFormattedPrice()
。图 4 显示的 RemoteCart
类对 Cart
进行了包装,添加了额外的 DWR 功能:
图 4. RemoteCart 为远程功能对 Cart 做了包装
最后,需要记住:DWR Ajax 调用是异步的,所以不要期望它们会按照分派的顺序返回。在示例代码中我忽略了这个小问题,
但是在这个系列的第一篇文章中,我演示了如何为响应加时间戳,以此作为保证数据到达顺序的一种简单手段。
正如所看到的,DWR 提供了许多东西 —— 它允许迅速而简单地创建到服务器端域对象的 Ajax 接口,而不需要编写任何
servlet 代码、对象序列化代码或客户端 XMLHttpRequest
代码。使用 DWR 部署到 Web 应用程序极为简单,而且 DWR
的安全性特性可以与 J2EE 基于角色的验证系统集成。但是 DWR 并不是对于任何一种应用程序架构都适合,所以在设计域
对象的 API 时需要做些考虑。
如果想学习用 DWR 进行 Ajax 的利弊的更多内容,最好的方式就是下载并开始实践。DWR 有许多我没有介绍的特性,
文章源代码 是把 DWR 投入使用的一个良好起点。请参阅 参考资料,学习关于 Ajax、DWR 和相关技术的更多内容。
这个系列中要指出的最重要的一点是:对于 Ajax 应用程序,没有包治百病的解决方案。Ajax 是一个快速发展的领域,
不断有新技术涌现。在这个系列的三篇文章中,我的重点在于带您开始在 Ajax 应用程序的 Web 层中利用 Java 技术
—— 不管是选择基于 XMLHttpRequest
的带有对象序列化框架的技术,还是选择 DWR 这样的更高级抽象。请在后
续几个月中留意面向 Java 开发人员介绍 Ajax 的文章。
发表评论
-
Ext中Proxy说明:HttpProxy/MemoryProxy/ScriptTagProxy
2008-01-17 14:16 5602Ext.data.DataProxy 数据代理类是一个纯虚类, ... -
AJAX基础教程
2006-12-26 18:27 1659AJAX基础教程 这篇文章将带您浏览整个AJAX的基本概 ... -
DWR让Ajax如此简单
2006-12-26 18:29 1312Ajax,或者说是异步JavaScript和XML,描述了一种 ... -
XLoadTree 基于AJAX + XML动态加载的JS树组件的文档翻译
2006-12-26 18:42 8909codeman1_2b-src.zipcodeman1_2b. ... -
面向Java开发人员的Ajax: 构建动态的Java应用程序
2007-01-06 14:04 1648在 Web 应用程序开发中,页面重载循环是最大的一个使用障碍, ... -
面向Java开发人员的Ajax:Ajax的Java对象序列化
2007-01-06 14:10 1772在 Ajax 应用程序中序列 ... -
看看如何在Struts应用中施展AJAX魔法
2007-01-06 23:29 1779AJAX是最近在web开发流程 ...
相关推荐
本主题主要关注Java开发人员如何利用Ajax,特别是通过Direct Web Remoting (DWR)框架来实现这一目标。 **Direct Web Remoting (DWR)** 是一个开放源码的Java库,它使得在浏览器和服务器之间进行双向通信变得更加...
面向Java开发人员的Ajax系列第三部分探讨了如何利用Direct Web Remoting (DWR)简化Ajax开发,特别是将JavaBean的方法暴露给JavaScript代码,自动化Ajax的复杂工作。DWR是一个开源项目,采用Apache许可协议,包括...
面向Java开发人员的Ajax技术,特别是与Jetty服务器和Direct Web Remoting (DWR)框架的结合,为创建高性能、可扩展的Comet应用程序提供了强大的工具。Comet是一种Web交互模式,它允许服务器向客户端推送数据,而不...
hex163下载频道:所有精品资料全部无分下载! 第 1 部分:Ajax 简介 ...第 14部分:面向 Java 开发人员的 Ajax 结合 Direct Web Remoting 使用 Ajax 第 15部分:面向 Java 开发人员的 Ajax: 探索 Google Web Toolkit
Direct Web Remoting (DWR) 是一个开源的Java库,它允许Web应用程序在客户端的JavaScript和服务器端的Java之间进行直接的、异步的通信,实现了Web应用中的Ajax功能。DWR通过自动化处理JavaScript和Java之间的类型...
DWR(Direct Web Remoting)是一个开源的类库,可以帮助开发人员开发包含AJAX技术的网站.它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样.
DWR(Direct Web Remoting)是一个web远程调用框架,利用这个框架可以让AJAX变得很简单,通过DWR可以在客户端通过JavaScript直接调用服务器的Java方法并返回值给JavaScript,整个过程就好像通过本地客户端调用一样,...
DWR-Direct Web Remoting 自己收集整理的DWR学习资料,包括了: 1.开发所需的dwr.jar; 2.DWR和Ajax技术的ppt文件; 3.DWR中文文档; 4.网上的一些文章; 5.收集的一些简单实例
DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用行在WEB服务器上的JAVA函数,就像它就在浏览器...
**DWR(Direct Web Remoting)**是一种基于Java的Ajax框架,主要用于在Web浏览器和服务器之间进行异步通信。DWR允许开发者使用JavaScript直接调用服务器端的Java方法,极大地简化了Web应用的开发,提高了用户体验,...
java工具类,DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA方法,就...
DWR(Direct Web Remoting)是一个开源的类库,可以帮助开发人员开发包含AJAX技术的网站.它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样.
在这个项目中,我们将聚焦于如何利用Direct Web Remoting (DWR) 框架来实现Ajax的自动补全功能。 DWR是一种轻量级的Java库,它允许JavaScript和Java之间进行安全的、动态的远程方法调用(RMI)。DWR简化了Ajax应用的...
第 14部分:面向 Java 开发人员的 Ajax 结合 Direct Web Remoting 使用 Ajax 154 1.1 DWR 是什么? 155 1.2 关于示例 155 1.3 实现目录 156 1.4 测试部署 157 1.5 调用远程对象 158 1.6 实现购物车 160 1.7 ...
### DWR (Direct Web Remoting) 介绍与应用 #### 一、概述 DWR(Direct Web Remoting)是一个开放源代码的项目,遵循Apache许可协议。它为开发者提供了一个强大的工具集,使得通过JavaScript调用Java方法变得简单...
DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站.它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器...
- 推荐一些用于简化Ajax与Java开发的库和框架,如Spring MVC、DWR(Direct Web Remoting)等。 10. **最佳实践** - 提供一些在实际开发中提升效率和代码质量的建议,如代码模块化、响应式设计等。 通过本文的...
### SD大会精品讲座:运用AJAX开发Web-2.0应用 #### 一、引言 随着互联网技术的快速发展,Web 2.0已经成为网络应用的重要趋势之一。它强调用户参与、互动以及个性化服务,而AJAX(异步JavaScript与XML)作为实现...