许多开发人员都期待着利用 ajax 技术来提高基于 web 的应用程序的用户体验,但是 ajax 编程可能是一项麻烦的任务。开放源码的 direct web remoting (dwr) 库通过自动把 java 类转换成 javascript 类,可以为 java™ 开发人员简化 ajax 开发。在这篇文章中,将学习如何用 dwr 和符合 jsr-168 规范的 portlet 迅速而容易地构建 ajax 应用程序。
许多开发人员都期待着利用 ajax 技术来提高基于 web 的应用程序的用户体验,但是 ajax 编程可能是一项麻烦的任务。开放源码的 direct web remoting (dwr) 库通过自动把 java 类转换成 javascript 类,可以为 java™ 开发人员简化 ajax 开发。在这篇文章中,将学习如何用 dwr 和符合 jsr-168 规范的 portlet 迅速而容易地构建 ajax 应用程序。
portlet 是基于 java 平台的 web 门户应用程序。jsr-168 是开发 portlet 应用程序的 java community process 标准,它描述了 portlet 生命周期管理、portlet 容器合约、打包、部署以及与门户有关的其他方面。
异步 javascript + xml(或者叫做 ajax)是一项用于开发丰富、交互的 web 应用程序的技术。ajax 组合了 xml、html、dhtml、javascript 和 dom。
portlet 和 ajax 看起来彼此之间是完美搭配,因为它们都侧重于用 web 浏览器作为向用户呈现用户界面的工具。把这两者与 java 技术组合在一起的简易方式就是使用 dwr 库。dwr 是 apache 许可下的开放源码 java 库,用于构建基于 ajax 的 web 应用程序。dwr 的基本目的是向开发人员隐藏 ajax 的细节。您在服务器端使用普通 java 对象(pojo),而 dwr 动态地生成 javascript 代理函数,所以使用 javascript 的客户端开发感觉起来就像直接调用 javabean。dwr 的主要组件是一个 java servlet,处理从浏览器到服务器的调用。
本文使用 dwr、基于三个 portlet 来构建一个示例 ajax 应用程序。我将介绍如何把 dwr 与 porlet 应用程序集成,但是我不想深入 dwr 的幕后工作细节;在这个项目的 web 站点和 developerworks 的页面上可以找到关于这个库的更多信息。要构建我描述的应用程序,需要 1.3 或以后版本的 java 平台和符合 jsr-168 规范的的门户环境。我用来开发和测试这个代码的环境包含 ibm rational application developer v6.0、apache jetspeed 2.0 portal 和 java 5.0。
构建示例的 portlet 间通信应用程序
我们的示例应用程序有三个 portlet:orders、order details 和 customer details;图 1 显示了示例应用程序:
图 1. 示例应用程序
orders portlet 有一个订单列表。当用户点击订单号时,该 portlet 把订单号发送给 order details 和 customer details portlet,这两者然后显示适当的订单和客户细节。
设置开发环境
在可以开发 portlet 之前,需要设置开发环境和 dwr。我使用 ibm rational application developer v6.0,它对 java portlet 开发具有内置的支持,但是其他开发环境也可以。按以下步骤开始:
- 1. 创建一个新的 jsr-168 portlet 项目。给项目起名为 interportletmessaging,但是现在还不创建任何 portlet。
- 2. 下载 dwr.jar。把 dwr.jar 添加到项目的 /webcontent//web-inf/lib 目录。
- 3. 打开 web.xml 并添加清单 1 中的代码。这会把 dwr servlet 添加到应用程序。这个 servlet 被用在后台处理请求并把响应发送回浏览器。
清单 1. dwr servlet
|
<servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-mapping> |
4. 用清单 2 中的代码在 web-inf 目录创建一个名为 dwr.xml 的文件。这个文件是 dwr 的配置文件,它告诉容器哪些类在 javascript 中是可用的。dwr 读取这个 xml 文件并动态地生成把 java 类表示成 javascript 类的 javascript 代码。这样您就可以在浏览器中提供由这些 java 类提供的功能。目前还没有真正创建在清单 2 中引用的 java 类,但是我们先来看一下。
清单 2. dwr.xml
|
<!doctype dwr public <dwr> |
现在可以在 portlet 中使用 dwr 了。但是在创建示例 portlet 之前,需要创建一个消息 bean 和一个伪装数据库 bean(充当示例应用程序的后端)。
创建 mockupdb 和 messagingbean
清单 3 所示的 mockupdb 是个单体类,模拟客户订单的数据库。所有订单都硬编码在这个类中。真实应用程序可能使用关系数据库系统,但这个示例对我们的目的来说足够了。
清单 3. mockupdb
|
private static mockupdb instance=new mockupdb(); private string[] orders=new string[4]; private mockupdb() orderdetails.put(orders[0],"1. websphere everyplace connection manager<br/>"+ customerdetails.put(orders[0],"<b>systems and technology group</b><br/>"+ public string getcustomerdetails(string ordernro) |
清单 4 所示的 messagingbean 是个简单的 pojo,有两个方法,都接受订单号,但是分别返回订单细节和客户细节。messagingbean 从 mockupdb 得到细节。
清单 4. messagingbean
|
package db; import java.util.hashtable; public class mockupdb { package msg; import javax.servlet.http.httpsession; import db.mockupdb; public class messagingbean { public messagingbean() public string getcustomerdetails(string ordernumber,httpsession httpsession) |
messagingbean 还把订单细节和客户细节添加到 httpsession。
javascriptfunctions.jsp
javascriptfunctions.jsp 导入了来自 dwr 的 javascript 库(engine.js)并动态地创建库 messagingbean.js。注意,messagingbean.js 使用的名称与 dwr.xml(清单 2)中的 javabean 的名称相同;实际上,dwr 生成 messagingbean.js。dwr 框架使用 engine.js 库;作为开发人员,通常不需要考虑直接使用它。
如清单 5 所示,sendordernr() 函数调用 清单 4 中定义的 messagingbean 函数。dwr 自动把 httpsession 添加到方法调用。javascript 函数中的最后一个参数是 callback 函数。在稍后创建的 portlet jsp 中,包含这个 jsp。
清单 5. javascriptfunctions.jsp
|
<%@ page contenttype="text/html" <script type="text/javascript" <script type="text/javascript" <script type="text/javascript"> function <portlet:namespace />sendordernr(ordernr) return false; function <portlet:namespace />showorderdetails(orderdetails) function <portlet:namespace />showcustomerdetails(customerdetails) |
创建 portlet
现在有了后端和代理函数,可以开发 portlet 本身了。所有三个 portlet 都使用相同的代码基;惟一的区别是每个 portlet 使用的 jsp 的名称。
1. 使用清单 6 中的代码创建一个新 portlet,并给它起名为 orders:
清单 6. orders.java
|
package interportletmessagingusingajax; import java.io.*; import javax.portlet.*; public class orders extends genericportlet { // jsp folder name // jsp file name to be rendered on the view mode
public void doview(renderrequest request, renderresponse response) // invoke the jsp to render //this is workaround for portletsession sharing between } private static string getjspfilepath(renderrequest request, string jspfile) { private static string getjspextension(string markupname) { |
2. 创建并打开 ordersview.jsp(在 interportletmessagingusingajax/jsp/html 目录),并把清单 7 中的代码添加到它:
清单 7. ordersview.jsp
|
<%@ page contenttype="text/html" <div style="margin: 6px"> <h4 style="margin-bottom: 3px">orders</h4> string[] orders=database.getorders(); <td><%="000000000"+string.valueof(i+1) %></td> </table> |
3. 第二个 portlet 是 orderdetailsportlet.java。对这个 portlet 使用 清单 6 中的代码,并把 view_jsp 变量的值改成 ordersdetailsportletview.jsp。这个 jsp 的代码如清单 8 所示:
清单 8. ordersdetailsportletview.jsp
|
<%@ page contenttype="text/html" <div style="margin: 6px"> <h4 style="margin-bottom: 3px">order details</h4> <table cellspacing="0" cellpadding="5" border="1"> <tr> if(orderdetailsordernumber==null) if(orderdetails==null)
|
4. 第三个 portlet 是 customerdetailsportlet.java。对这个 portlet 使用 清单 6 中的代码,并把 view_jsp 变量的值改成 customerdetailsportletview.jsp。这个 jsp 的代码如清单 9 所示:
清单 9. customerdetailsportletview.jsp
|
<%@ page contenttype="text/html" <% <div style="margin: 6px"> <h4 style="margin-bottom: 3px">customer details</h4> <tr> if(customerdetailsordernumber==null) if(customerdetails==null) </table> |
示例应用程序现在准备好了。下一步是把 portlet 打包成 war 文件并在 apache jetspeed 门户中测试它。
测试示例应用程序
在这一节,将看到示例应用程序的作用。首先,创建 portlet war 并把它安装到 jetspeed 门户。然后,把三个 portlet 添加到门户,看它们是如何工作的。将把它们全都构建到一个页面,但如果需要也可以把它们放到多个页面;幕后的机制仍然起作用。
把 portlet 应用程序安装到 jetspeed
把 portlet war 文件安装到 jetspeed 的方法是把 war 文件拷贝到
使用以下步骤把新页面添加到 jetspeed 门户:
1. 进入 jetspeed 门户,并作为管理员登录。
2. 点击右下角的 edit 图标,并添加名为 inter-portlet messaging 的新页面,如图 2 所示:
图 2. 添加新页面
3. 选择 inter-portlet messaging 页面并点击 edit 图标。然后点击 add a portlet 图标,在这个页面上添加 portlet。选择 orders、order details 和 customer details portlet,并点击 select portlets,把选中的 portlet 添加到门户页面。完成之后,页面看起来应当像图 3:
图 3. 页面上的 portlet
portlet
orders portlet 如图 4 所示,列出订单:
图 4. orders portlet
在点击订单号时,其他 portlet 显示这个订单的细节。customer details portlet 显示客户信息,如图 5 所示。信息检索自 mockupdb。
图 5. customer details portlet
order details portlet 也显示检索自 mockupdb 的信息,如图 6 所示:
图 6. order details portlet
如果喜欢,可以回过去,向不同的页面添加一个或多个 portlet。将会看到,portlet 不需要在单个页面上,因为 portlet 内容保存在用户会话中。
结束语
这篇文章介绍了用 ajax 实现 portlet 间通信的一种方式。ajax 是开发交互式 web 页面的一种非常强大的技术,而支持 ajax 的 portlet 通过消除门户中典型存在的请求-响应延迟,极大地改善了用户体验。
可以用本文中的代码作为开发您自己的应用程序的起点;文中的代码还显示了 dwr 如何把 java 编程模型扩展到 web 浏览器。使用 dwr,javabean 几乎就像是在浏览器中可用一样。dwr 几乎隐藏了 ajax 的全部细节,让您可以专注于手头的工作,而不必考虑 ajax 开发的具体细节,从而简化了工作。






闽公网安备 35060202000074号