用户购物车的 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.xml 中,我添加了 Cart 的 creator 和 convertor。create 元素指定应当把addItemToCart() 和 getCart() 方法远程化,而且重要的是,生成的 Cart 实例应当放在用户的会话中。所以,购物车的内容在用户的请求之间会保留。
Cart 的 convert 元素是必需的,因为远程的 Cart 方法返回的是 Cart 本身。在这里我指定在 Cart 的序列化 JavaScript 形式中应当存在的成员是 simpleContents 这个图和 formattedTotalPrice 这个字符串。
如果对这觉得有点儿不明白,那么只要记住 create 元素指定的是 DWR 客户可以调用的 Cart 服务器端方法,而 convert 元素指定在 Cart 的 JavaScript 序列化形式中包含的成员。