科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道结合Direct Web Remoting使用Ajax2

结合Direct Web Remoting使用Ajax2

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

虽然令人兴奋,但是把 Ajax 功能添加到应用程序可能意味着大量的艰苦工作。在本文中Philip McCarthy 介绍了如何使用Direct Web Remoting(DWR)直接把 JavaBean 的方法公开给 JavaScript 代码并自动进行 Ajax 的繁重工作。

作者:Philip McCarthy 来源:IT专家网 2008年6月1日

关键字: AJAX 使用 结合 java

  • 评论
  • 分享微博
  • 分享邮件
可以在可访问的方法旁边的文本框中输入参数值并点击 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()

/*
 * 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";
  }
}

  在上面的 searchFormSubmitHandler() 函数中,我们感兴趣的代码当然是 catalog.findItems(searchexp, displayItems);。这一行代码就是通过网络向 DWR servlet 发送 XMLHttpRequest 并用远程对象的响应调用 displayItems() 函数所需要的全部内容。

  displayItems() 回调本身是由一个 Item 数组表示调用的。这个数组传递给 DWRUtil.addRows() 便捷函数,同时还有要填充的表的 ID 和一个函数数组。表中每行有多少单元格,这个数组中就有多少个函数。按照顺序使用来自数组的 Item 逐个调用每个函数,并用返回的内容填充对应的单元格。

在这个示例中,我想让商品表中的每一行都显示商品的名称、说明和价格,并在最后一列显示商品的 Add to Cart 按钮。清单 4 显示了实现这一功能的单元格函数数组:

  清单 4. 填充商品表的单元格函数数组

/*
 * 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;
  }
];

  前三个函数只是返回 dwr.xml 中 Item 的 convertor 包含的字段内容。最后一个函数创建一个按钮,把 Item 的 ID 赋给它,并指定在点击按钮时应当调用名为 addToCartButtonHandler 的函数。这个函数是第二个用例的入口点:向购物车中添加 Item。

  实现购物车

  用户购物车的 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 表示。

      DWR 的安全性

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

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

  转换购物车

  为了不让客户代码对 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 的内容并接收购物车的新状态。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章