注册 | 登录 | 设为首页 | 加入收藏
您当前的位置:飞翔学院-IT中国 → 编程开发AJAX → 文章内容

结合Direct Web Remoting使用AJAX

作者:佚名 来源:不详 发布时间:2007-12-10 21:57:06
实现购物车
结合Direct Web Remoting使用AJAX(图三)
DWR 的安全性

DWR 设计时就考虑了安全性。使用 dwr.xml 明确地列出那些想做远程处理的类和方法,可以避免意外地把那些可能被恶意利用的功能公开出去。除此之外,使用调试测试模式,可以容易地审计所有公开到 Web 上的类和方法。

DWR 也支持基于角色的安全性。通过 bean 的 creator 配置,可以指定用户访问特定 bean 所必须属于的 J2EE 角色。通过部署多个 URL 受保护的 DWRServlet 实例,每个实例都有自己的 dwr.xml 配置文件,也可以提供拥有不同远程功能的用户集。

  用户购物车的 Java 表示基于 Map。当 Item 添加到购物车中时,Item 本身作为键被插入 Map。 Map 中对应的值是一个 Integer,代表购物车中指定 Item 的数量。所以 Cart.java 有一个字段 contents,声明为 Map<Item,Integer>。

  使用复杂类型作为哈希键给 DWR 带来一个问题 —— 在 JavaScript 中,数组的键必须是标量的。所以,DWR 无法转换 contents Map。但是,对于购物车用户界面来说,用户需要查看的只是每个商品的名称和数量。所以我向 Cart 添加了一个名为 getSimpleContents() 的方法,它接受 contents Map 并根据它构建一个简化的 Map<String,Integer>,只代表每个 Item 的名称和数量。这个用字符串作为键的 map 表示可以由 DWR 的转换器转换成 JavaScript。

  客户对 Cart 感兴趣的其他字段是 totalPrice,它代表购物车中所有商品的金额汇总。使用 Item,我还提供了一个合成的成员叫作 formattedTotalPrice,它是金额汇总的格式化好的 String 表示。

  转换购物车

  为了不让客户代码对 Cart 做两个调用(一个获得内容,一个获得总价),我想把这些数据一次全都发给客户。为了做到这一点,我添加了一个看起来有点儿怪的方法,如清单 5 所示:

   清单 5. Cart.getCart() 方法
 /**  * Returns the cart itself - for DWR  * @return the cart  */  public Cart getCart() {   return this; } 

  虽然这个方法在普通的 Java 代码中可能完全是多余的(因为在调用这个方法时,已经有对 Cart 的引用),但它允许 DWR 客户让 Cart 把自己序列化成 JavaScript。

  除了getCart(),需要远程化的另一个方法是 addItemToCart()。这个方法接受目录 Item 的 ID 的 String 表示,把这个商品添加到 Cart 中并更新总价。方法还返回 Cart,这样客户代码在一个操作中就能更新 Cart 的内容并接收购物车的新状态。

  清单 6 是扩展的 dwr.xml 配置文件,包含 Cart 类进行远程所需要的额外配置:

   清单 6. 修改过的 dwr.xml 包含了 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>     </convert converter="bean"        match="developerworks.ajax.store.Cart">       </param name="include"          value="simpleContents,formattedTotalPrice"/>     <//convert>   <//allow> </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 的远程方法的客户端代码了。

  调用远程的 Cart 方法

  首先,当商店的 Web 页首次装入时,我想检查保存在会话中的 Cart 的状态,看是否已经有一个购物车了。这是必需的,因为用户可能已经向 Cart 中添加了商品,然后刷新了页面或者导航到其他地方之后又返回来。在这些情况下,重新载入的页面需要用会话中的 Cart 数据对自己进行同步。我可以在页面的 onload 函数中用一个调用做到这一点,就像这样:Cart.getCart(displayCart)。请注意 displayCart() 是一个回调函数,由服务器返回的 Cart 响应数据调用。

  如果 Cart 已经在会话中,那么creator 会检索它并调用它的 getCart() 方法。如果会话中没有 Cart,那么 creator 会实例化一个新的,把它放在会话中,并调用 getCart() 方法。

  清单 7 显示了 addToCartButtonHandler() 函数的实现,当点击商品的 Add to Cart 按钮时会调用这个函数:

   清单 7. 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); } 

  由 DWR 负责所有通信,所以客户上的添加到购物车行为就是一个函数。清单 8 显示了这个示例的最后一部分 —— displayCart() 回调的实现,它用 Cart 的状态更新用户界面:

   清单 8. 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; } 

  在这里重要的是要记住,simpleContents 是一个把 String 映射到数字的 JavaScript 数组。每个字符串都是一个商品的名称,关联数组中的对应数字就是购物车中该商品的数量。所以表达式 cart.simpleContents[item] + " x " + item 可能就会计算出 “2 x Oolong 128MB CF Card” 这样的结果。
更多内容请看PCdog.com--Ajax技术专题
上一页  [1] [2] [3] [4]  下一页


  • 打印文档
  • 推荐好友
  • 返回顶部
  • 增大字体
  • 减少字体
关于本站 | 工作机会 | 合作网站 | 广告服务 | 市场合作| 联系我们 | 抽奖活动
版权所有: 武汉威俊科技有限公司 Copyright 2005-2007 www.ITCNW.COM All rights reserved