- 浏览: 408676 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (268)
- java (22)
- Acegi (8)
- Ajax (17)
- Annotation (3)
- Ant (3)
- JBOSS (6)
- Xdoclet (1)
- CSS (20)
- Data Warehouse (11)
- DB2 (3)
- DOM (1)
- dos (2)
- JMF (1)
- JMS (5)
- J2EE (17)
- Hibernate (7)
- struts (10)
- CORBA (1)
- 职业 (2)
- JSF (1)
- JSTL (8)
- 其它 (1)
- Log4j (7)
- svg (7)
- quartz (3)
- web2.0 (2)
- velocity (2)
- apache commons (1)
- js (9)
- html (4)
- sql (3)
- linux (4)
- dwr (14)
- spring (5)
- GWT (7)
- portlet (4)
- 软件工程 (10)
- actionscript (1)
- 测试 (1)
- tomcat (3)
- flash (0)
- 线程 (1)
- mysql (6)
- flex (1)
- oracle (7)
- crystalreport (4)
- itext (4)
- memcache (2)
- linux 监控 (2)
- mongodb (1)
- Kafka (5)
- 网络 (2)
- 分布式计算 (2)
最新评论
-
chenyongxin:
mark
JBoss 4.0.2集群基本知识及配置方法指南 -
softor:
我找到了,下载吧:http://ishare.iask.sin ...
jad是最简单的class反编译为java文件的小工具 (转载) -
softor:
求下载
dodo@lovehang.com
jad是最简单的class反编译为java文件的小工具 (转载) -
juedui0769:
不错!
请问: 如何在 将 log4j.appender ...
Tomcat 日志 配置 (转载) -
spp_1987:
// 建立一个上传文件的输出流
...
Struts上传多个及N个文件的例子
许多开发人员都期待着利用 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 和 Ajax 开发。如果愿意学习关于这些主题的更多内容,请参阅下面的 参考资料 小节。可以从 下载 小节下载示例应用程序的完整代码,包括 DWR。
构建示例的 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 开发具有内置的支持,但是其他开发环境也可以。按以下步骤开始:
创建一个新的 JSR-168 portlet 项目。给项目起名为 InterPortletMessaging,但是现在还不创建任何 portlet。
下载 dwr.jar(版本 1.1;请参阅 参考资料 中的链接)。把 dwr.jar 添加到项目的 /WebContent//WEB-INF/lib 目录。
打开 web.xml 并添加清单 1 中的代码。这会把 DWR servlet 添加到应用程序。这个 servlet 被用在后台处理请求并把响应发送回浏览器。
清单 1. DWR servlet
<servlet> <servlet-name>dwr-invoker</servlet-name> <display-name>DWR Servlet</display-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param></servlet><servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern></servlet-mapping>
用清单 2 中的代码在 WEB-INF 目录创建一个名为 dwr.xml 的文件。这个文件是 DWR 的配置文件,它告诉容器哪些类在 JavaScript 中是可用的。DWR 读取这个 XML 文件并动态地生成把 Java 类表示成 JavaScript 类的 JavaScript 代码。这样您就可以在浏览器中提供由这些 Java 类提供的功能。目前还没有真正创建在清单 2 中引用的 Java 类,但是我们先来看一下。
清单 2. dwr.xml
<!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="MessagingBean"> <param name="class" value="msg.MessagingBean"/> </create> </allow></dwr>
现在可以在 portlet 中使用 DWR 了。但是在创建示例 portlet 之前,需要创建一个消息 bean 和一个伪装数据库 bean(充当示例应用程序的后端)。
创建 MockupDB 和 MessagingBean
清单 3 所示的 MockupDB 是个单体类,模拟客户订单的数据库。所有订单都硬编码在这个类中。真实应用程序可能使用关系数据库系统,但这个示例对我们的目的来说足够了。
清单 3. MockupDB
package db;import java.util.Hashtable;import java.util.Map;public class MockupDB { private static MockupDB instance=new MockupDB(); private String[] orders=new String[4]; private Map orderDetails=new Hashtable(); private Map customerDetails=new Hashtable(); private MockupDB() { String ordStart="ORD"; orders[0]=ordStart+"000408015"; orders[1]=ordStart+"001600023"; orders[2]=ordStart+"000042000"; orders[3]=ordStart+"011235813"; orderDetails.put(orders[0],"1. WebSphere Everyplace Connection Manager<br/>"+ "2. WebSphere Portal"); orderDetails.put(orders[1],"1. DB2 Universal Database<br/>2. DB2 Everyplace"); orderDetails.put(orders[2],"1. Tivoli Access Manager for e-business <br/>2."+ "Tivoli Directory Integrator"); orderDetails.put(orders[3],"1. IBM System z9<br/>2. IBM System p5 550 Express"); customerDetails.put(orders[0],"<b>Systems and Technology Group</b><br/>"+ "Some Road<br/>Finland"); customerDetails.put(orders[1],"<b>Global Financing</b><br/>Another Street"+ "<br/>Finland"); customerDetails.put(orders[2],"<b>Software</b><br/>Yet Another Road"+ "<br/>Finland"); customerDetails.put(orders[3],"<b>Global Services</b><br/>Still Another "+ "Street<br/>Finland"); } public static MockupDB getInstance() { return instance; } public String[] getOrders() { return orders; } public String getOrderDetails(String orderNro) { return (String)orderDetails.get(orderNro); } public String getCustomerDetails(String orderNro) { return (String)customerDetails.get(orderNro); }}
清单 4 所示的 MessagingBean 是个简单的 POJO,有两个方法,都接受订单号,但是分别返回订单细节和客户细节。MessagingBean 从 MockupDB 得到细节。
清单 4. MessagingBean
package msg;import javax.servlet.http.HttpSession;import db.MockupDB;public class MessagingBean { public MessagingBean() { } public String getOrderDetails(String orderNumber,HttpSession httpSession) { String orderDetails=MockupDB.getInstance().getOrderDetails(orderNumber) httpSession.setAttribute("orderDetailsOrderNumber",orderNumber); httpSession.setAttribute("orderDetails",orderDetails); return orderDetails; } public String getCustomerDetails(String orderNumber,HttpSession httpSession) { String customerDetails=MockupDB.getInstance().getCustomerDetails(orderNumber); httpSession.setAttribute("customerDetailsOrderNumber",orderNumber); httpSession.setAttribute("customerDetails",customerDetails); return customerDetails; }}
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" import="java.util.*,javax.portlet.*,interportletmessagingusingajax.*" %><%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><SCRIPT type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath() + "/dwr/interface/MessagingBean.js") %>'> </SCRIPT><SCRIPT type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath() + "/dwr/engine.js") %>'> </SCRIPT><SCRIPT type="text/javascript">function <portlet:namespace />sendOrderNr(orderNr){document.getElementById("orderDetailsOrderNumber").innerHTML=orderNr;document.getElementById("customerDetailsOrderNumber").innerHTML=orderNr;MessagingBean.getOrderDetails(orderNr,<portlet:namespace />showOrderDetails);MessagingBean.getCustomerDetails(orderNr,<portlet:namespace />showCustomerDetails);return false;}function <portlet:namespace />showOrderDetails(orderDetails){document.getElementById("orderDetails").innerHTML=orderDetails;return false;}function <portlet:namespace />showCustomerDetails(customerDetails){document.getElementById("customerDetails").innerHTML=customerDetails;return false;}</SCRIPT>
创建 portlet
现在有了后端和代理函数,可以开发 portlet 本身了。所有三个 portlet 都使用相同的代码基;惟一的区别是每个 portlet 使用的 JSP 的名称。
使用清单 6 中的代码创建一个新 portlet,并给它起名为 Orders:
清单 6. Orders.java
package interportletmessagingusingajax;import java.io.*;import javax.portlet.*;public class Orders extends GenericPortlet { // JSP folder name public static final String JSP_FOLDER = "/interportletmessagingusingajax/jsp/"; // JSP file name to be rendered on the view mode public static final String VIEW_JSP = "OrdersView"; public void init(PortletConfig config) throws PortletException{ super.init(config); } public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { // Set the MIME type for the render response response.setContentType(request.getResponseContentType()); // Invoke the JSP to render PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher( getJspFilePath(request, VIEW_JSP)); rd.include(request,response); //this is workaround for portletsession sharing between //servlets and portlets //see http://weblogs.java.net/blog/wholder/archive/2005/02/session_session.html //and http://mail-archives.apache.org/mod_mbox/portals-pluto-dev/200502.mbox/%3Ca //2519328f3ba1d1eddfc33c924b6805d@umich.edu%3E // PortletRequestDispatcher rd2 = getPortletContext().getRequestDispatcher("/dwr/"); rd2.include(request, response); } private static String getJspFilePath(RenderRequest request, String jspFile) { String markup = request.getProperty("wps.markup"); if( markup == null ) markup = getMarkup(request.getResponseContentType()); return JSP_FOLDER+markup+"/"+jspFile+"."+getJspExtension(markup); } private static String getMarkup(String contentType) { if( "text/vnd.wap.wml".equals(contentType) ) return "wml"; return "html"; } private static String getJspExtension(String markupName) { return "jsp"; }}
创建并打开 OrdersView.jsp(在 interportletmessagingusingajax/jsp/html 目录),并把清单 7 中的代码添加到它:
清单 7. OrdersView.jsp
<%@ page contentType="text/html" import="java.util.*,javax.portlet.*,interportletmessagingusingajax.*" %><%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><jsp:include page="javascriptFunctions.jsp" /><DIV style="margin: 6px"><H4 style="margin-bottom: 3px">Orders</H4><table cellspacing="0" cellpadding="5" border="1"><% db.MockupDB database= db.MockupDB.getInstance();String[] orders=database.getOrders();for(int i=0;i<orders.length;i++){%><tr><td><%="000000000"+String.valueOf(i+1) %></td><td><a href="" onclick="return <portlet:namespace />sendOrderNr('<%= orders[i]%>');"><%=orders[i]%></a></td></tr><%} %></table></DIV>
第二个 portlet 是 OrderDetailsPortlet.java。对这个 portlet 使用 清单 6 中的代码,并把 VIEW_JSP 变量的值改成 OrdersDetailsPortletView.jsp。这个 JSP 的代码如清单 8 所示:
清单 8. OrdersDetailsPortletView.jsp
<%@ page contentType="text/html" import="java.util.*,javax.portlet.*,interportletmessagingusingajax.*" %><%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><DIV style="margin: 6px"><H4 style="margin-bottom: 3px">Order details</H4><table cellspacing="0" cellpadding="5" border="1"><tr><th>Order number</th><th>Order details</th></tr><tr><%String orderDetailsOrderNumber=(String)renderRequest.getPortletSession().getAttribute( "orderDetailsOrderNumber",PortletSession.APPLICATION_SCOPE);String orderDetails=(String)renderRequest.getPortletSession().getAttribute( "orderDetails",PortletSession.APPLICATION_SCOPE);if(orderDetailsOrderNumber==null){orderDetailsOrderNumber="";}if(orderDetails==null){orderDetails="";}%><td><div id="orderDetailsOrderNumber"><%=orderDetailsOrderNumber%></div></td><td><div id="orderDetails"><%=orderDetails%></div></td></tr></table></DIV>
第三个 portlet 是 CustomerDetailsPortlet.java。对这个 portlet 使用 清单 6 中的代码,并把 VIEW_JSP 变量的值改成 CustomerDetailsPortletView.jsp。这个 JSP 的代码如清单 9 所示:
清单 9. CustomerDetailsPortletView.jsp
<%@ page contentType="text/html" import="java.util.*,javax.portlet.*,interportletmessagingusingajax.*" %><%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><%%><DIV style="margin: 6px"><H4 style="margin-bottom: 3px">Customer details</H4><table cellspacing="0" cellpadding="5" border="1"><tr><th>Order number</th><th>Customer details</th></tr><tr><%String customerDetailsOrderNumber= (String)renderRequest.getPortletSession().getAttribute( "customerDetailsOrderNumber",PortletSession.APPLICATION_SCOPE);String customerDetails=(String)renderRequest.getPortletSession().getAttribute( "customerDetails", PortletSession.APPLICATION_SCOPE);if(customerDetailsOrderNumber==null){customerDetailsOrderNumber="";}if(customerDetails==null){customerDetails="";}%><td><div id="customerDetailsOrderNumber"><%=customerDetailsOrderNumber%></div></td><td><div id="customerDetails"><%=customerDetails%></div></td></tr></table></DIV>
示例应用程序现在准备好了。下一步是把 portlet 打包成 WAR 文件并在 Apache Jetspeed 门户中测试它。
回页首
测试示例应用程序
在这一节,将看到示例应用程序的作用。首先,创建 portlet WAR 并把它安装到 Jetspeed 门户。然后,把三个 portlet 添加到门户,看它们是如何工作的。将把它们全都构建到一个页面,但如果需要也可以把它们放到多个页面;幕后的机制仍然起作用。
把 portlet 应用程序安装到 Jetspeed
把 portlet WAR 文件安装到 Jetspeed 的方法是把 WAR 文件拷贝到 <Jetspeed install dir>/webapps/jetspeed/WEB-INF/deploy 目录。然后 Jetspeed 会自动安装 portlet,portlet 即可使用了。
使用以下步骤把新页面添加到 Jetspeed 门户:
进入 Jetspeed 门户,并作为管理员登录。
点击右下角的 Edit 图标,并添加名为 Inter-Portlet Messaging 的新页面,如图 2 所示:
图 2. 添加新页面
选择 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 开发的具体细节,从而简化了工作。
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 和 Ajax 开发。如果愿意学习关于这些主题的更多内容,请参阅下面的 参考资料 小节。可以从 下载 小节下载示例应用程序的完整代码,包括 DWR。
构建示例的 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 开发具有内置的支持,但是其他开发环境也可以。按以下步骤开始:
创建一个新的 JSR-168 portlet 项目。给项目起名为 InterPortletMessaging,但是现在还不创建任何 portlet。
下载 dwr.jar(版本 1.1;请参阅 参考资料 中的链接)。把 dwr.jar 添加到项目的 /WebContent//WEB-INF/lib 目录。
打开 web.xml 并添加清单 1 中的代码。这会把 DWR servlet 添加到应用程序。这个 servlet 被用在后台处理请求并把响应发送回浏览器。
清单 1. DWR servlet
<servlet> <servlet-name>dwr-invoker</servlet-name> <display-name>DWR Servlet</display-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param></servlet><servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern></servlet-mapping>
用清单 2 中的代码在 WEB-INF 目录创建一个名为 dwr.xml 的文件。这个文件是 DWR 的配置文件,它告诉容器哪些类在 JavaScript 中是可用的。DWR 读取这个 XML 文件并动态地生成把 Java 类表示成 JavaScript 类的 JavaScript 代码。这样您就可以在浏览器中提供由这些 Java 类提供的功能。目前还没有真正创建在清单 2 中引用的 Java 类,但是我们先来看一下。
清单 2. dwr.xml
<!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="MessagingBean"> <param name="class" value="msg.MessagingBean"/> </create> </allow></dwr>
现在可以在 portlet 中使用 DWR 了。但是在创建示例 portlet 之前,需要创建一个消息 bean 和一个伪装数据库 bean(充当示例应用程序的后端)。
创建 MockupDB 和 MessagingBean
清单 3 所示的 MockupDB 是个单体类,模拟客户订单的数据库。所有订单都硬编码在这个类中。真实应用程序可能使用关系数据库系统,但这个示例对我们的目的来说足够了。
清单 3. MockupDB
package db;import java.util.Hashtable;import java.util.Map;public class MockupDB { private static MockupDB instance=new MockupDB(); private String[] orders=new String[4]; private Map orderDetails=new Hashtable(); private Map customerDetails=new Hashtable(); private MockupDB() { String ordStart="ORD"; orders[0]=ordStart+"000408015"; orders[1]=ordStart+"001600023"; orders[2]=ordStart+"000042000"; orders[3]=ordStart+"011235813"; orderDetails.put(orders[0],"1. WebSphere Everyplace Connection Manager<br/>"+ "2. WebSphere Portal"); orderDetails.put(orders[1],"1. DB2 Universal Database<br/>2. DB2 Everyplace"); orderDetails.put(orders[2],"1. Tivoli Access Manager for e-business <br/>2."+ "Tivoli Directory Integrator"); orderDetails.put(orders[3],"1. IBM System z9<br/>2. IBM System p5 550 Express"); customerDetails.put(orders[0],"<b>Systems and Technology Group</b><br/>"+ "Some Road<br/>Finland"); customerDetails.put(orders[1],"<b>Global Financing</b><br/>Another Street"+ "<br/>Finland"); customerDetails.put(orders[2],"<b>Software</b><br/>Yet Another Road"+ "<br/>Finland"); customerDetails.put(orders[3],"<b>Global Services</b><br/>Still Another "+ "Street<br/>Finland"); } public static MockupDB getInstance() { return instance; } public String[] getOrders() { return orders; } public String getOrderDetails(String orderNro) { return (String)orderDetails.get(orderNro); } public String getCustomerDetails(String orderNro) { return (String)customerDetails.get(orderNro); }}
清单 4 所示的 MessagingBean 是个简单的 POJO,有两个方法,都接受订单号,但是分别返回订单细节和客户细节。MessagingBean 从 MockupDB 得到细节。
清单 4. MessagingBean
package msg;import javax.servlet.http.HttpSession;import db.MockupDB;public class MessagingBean { public MessagingBean() { } public String getOrderDetails(String orderNumber,HttpSession httpSession) { String orderDetails=MockupDB.getInstance().getOrderDetails(orderNumber) httpSession.setAttribute("orderDetailsOrderNumber",orderNumber); httpSession.setAttribute("orderDetails",orderDetails); return orderDetails; } public String getCustomerDetails(String orderNumber,HttpSession httpSession) { String customerDetails=MockupDB.getInstance().getCustomerDetails(orderNumber); httpSession.setAttribute("customerDetailsOrderNumber",orderNumber); httpSession.setAttribute("customerDetails",customerDetails); return customerDetails; }}
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" import="java.util.*,javax.portlet.*,interportletmessagingusingajax.*" %><%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><SCRIPT type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath() + "/dwr/interface/MessagingBean.js") %>'> </SCRIPT><SCRIPT type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath() + "/dwr/engine.js") %>'> </SCRIPT><SCRIPT type="text/javascript">function <portlet:namespace />sendOrderNr(orderNr){document.getElementById("orderDetailsOrderNumber").innerHTML=orderNr;document.getElementById("customerDetailsOrderNumber").innerHTML=orderNr;MessagingBean.getOrderDetails(orderNr,<portlet:namespace />showOrderDetails);MessagingBean.getCustomerDetails(orderNr,<portlet:namespace />showCustomerDetails);return false;}function <portlet:namespace />showOrderDetails(orderDetails){document.getElementById("orderDetails").innerHTML=orderDetails;return false;}function <portlet:namespace />showCustomerDetails(customerDetails){document.getElementById("customerDetails").innerHTML=customerDetails;return false;}</SCRIPT>
创建 portlet
现在有了后端和代理函数,可以开发 portlet 本身了。所有三个 portlet 都使用相同的代码基;惟一的区别是每个 portlet 使用的 JSP 的名称。
使用清单 6 中的代码创建一个新 portlet,并给它起名为 Orders:
清单 6. Orders.java
package interportletmessagingusingajax;import java.io.*;import javax.portlet.*;public class Orders extends GenericPortlet { // JSP folder name public static final String JSP_FOLDER = "/interportletmessagingusingajax/jsp/"; // JSP file name to be rendered on the view mode public static final String VIEW_JSP = "OrdersView"; public void init(PortletConfig config) throws PortletException{ super.init(config); } public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { // Set the MIME type for the render response response.setContentType(request.getResponseContentType()); // Invoke the JSP to render PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher( getJspFilePath(request, VIEW_JSP)); rd.include(request,response); //this is workaround for portletsession sharing between //servlets and portlets //see http://weblogs.java.net/blog/wholder/archive/2005/02/session_session.html //and http://mail-archives.apache.org/mod_mbox/portals-pluto-dev/200502.mbox/%3Ca //2519328f3ba1d1eddfc33c924b6805d@umich.edu%3E // PortletRequestDispatcher rd2 = getPortletContext().getRequestDispatcher("/dwr/"); rd2.include(request, response); } private static String getJspFilePath(RenderRequest request, String jspFile) { String markup = request.getProperty("wps.markup"); if( markup == null ) markup = getMarkup(request.getResponseContentType()); return JSP_FOLDER+markup+"/"+jspFile+"."+getJspExtension(markup); } private static String getMarkup(String contentType) { if( "text/vnd.wap.wml".equals(contentType) ) return "wml"; return "html"; } private static String getJspExtension(String markupName) { return "jsp"; }}
创建并打开 OrdersView.jsp(在 interportletmessagingusingajax/jsp/html 目录),并把清单 7 中的代码添加到它:
清单 7. OrdersView.jsp
<%@ page contentType="text/html" import="java.util.*,javax.portlet.*,interportletmessagingusingajax.*" %><%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><jsp:include page="javascriptFunctions.jsp" /><DIV style="margin: 6px"><H4 style="margin-bottom: 3px">Orders</H4><table cellspacing="0" cellpadding="5" border="1"><% db.MockupDB database= db.MockupDB.getInstance();String[] orders=database.getOrders();for(int i=0;i<orders.length;i++){%><tr><td><%="000000000"+String.valueOf(i+1) %></td><td><a href="" onclick="return <portlet:namespace />sendOrderNr('<%= orders[i]%>');"><%=orders[i]%></a></td></tr><%} %></table></DIV>
第二个 portlet 是 OrderDetailsPortlet.java。对这个 portlet 使用 清单 6 中的代码,并把 VIEW_JSP 变量的值改成 OrdersDetailsPortletView.jsp。这个 JSP 的代码如清单 8 所示:
清单 8. OrdersDetailsPortletView.jsp
<%@ page contentType="text/html" import="java.util.*,javax.portlet.*,interportletmessagingusingajax.*" %><%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><DIV style="margin: 6px"><H4 style="margin-bottom: 3px">Order details</H4><table cellspacing="0" cellpadding="5" border="1"><tr><th>Order number</th><th>Order details</th></tr><tr><%String orderDetailsOrderNumber=(String)renderRequest.getPortletSession().getAttribute( "orderDetailsOrderNumber",PortletSession.APPLICATION_SCOPE);String orderDetails=(String)renderRequest.getPortletSession().getAttribute( "orderDetails",PortletSession.APPLICATION_SCOPE);if(orderDetailsOrderNumber==null){orderDetailsOrderNumber="";}if(orderDetails==null){orderDetails="";}%><td><div id="orderDetailsOrderNumber"><%=orderDetailsOrderNumber%></div></td><td><div id="orderDetails"><%=orderDetails%></div></td></tr></table></DIV>
第三个 portlet 是 CustomerDetailsPortlet.java。对这个 portlet 使用 清单 6 中的代码,并把 VIEW_JSP 变量的值改成 CustomerDetailsPortletView.jsp。这个 JSP 的代码如清单 9 所示:
清单 9. CustomerDetailsPortletView.jsp
<%@ page contentType="text/html" import="java.util.*,javax.portlet.*,interportletmessagingusingajax.*" %><%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><%%><DIV style="margin: 6px"><H4 style="margin-bottom: 3px">Customer details</H4><table cellspacing="0" cellpadding="5" border="1"><tr><th>Order number</th><th>Customer details</th></tr><tr><%String customerDetailsOrderNumber= (String)renderRequest.getPortletSession().getAttribute( "customerDetailsOrderNumber",PortletSession.APPLICATION_SCOPE);String customerDetails=(String)renderRequest.getPortletSession().getAttribute( "customerDetails", PortletSession.APPLICATION_SCOPE);if(customerDetailsOrderNumber==null){customerDetailsOrderNumber="";}if(customerDetails==null){customerDetails="";}%><td><div id="customerDetailsOrderNumber"><%=customerDetailsOrderNumber%></div></td><td><div id="customerDetails"><%=customerDetails%></div></td></tr></table></DIV>
示例应用程序现在准备好了。下一步是把 portlet 打包成 WAR 文件并在 Apache Jetspeed 门户中测试它。
回页首
测试示例应用程序
在这一节,将看到示例应用程序的作用。首先,创建 portlet WAR 并把它安装到 Jetspeed 门户。然后,把三个 portlet 添加到门户,看它们是如何工作的。将把它们全都构建到一个页面,但如果需要也可以把它们放到多个页面;幕后的机制仍然起作用。
把 portlet 应用程序安装到 Jetspeed
把 portlet WAR 文件安装到 Jetspeed 的方法是把 WAR 文件拷贝到 <Jetspeed install dir>/webapps/jetspeed/WEB-INF/deploy 目录。然后 Jetspeed 会自动安装 portlet,portlet 即可使用了。
使用以下步骤把新页面添加到 Jetspeed 门户:
进入 Jetspeed 门户,并作为管理员登录。
点击右下角的 Edit 图标,并添加名为 Inter-Portlet Messaging 的新页面,如图 2 所示:
图 2. 添加新页面
选择 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 开发的具体细节,从而简化了工作。
发表评论
-
dwr 常见方法
2008-01-16 17:38 1003$(); 功能:相当于document.getElement ... -
DWR中提供XML的传递方法
2008-01-16 17:28 850自己用dom4j,所以用dom4j做例子; java ser ... -
DWRUtils API 使用方法(转载)
2008-01-16 17:21 752$("precloneNode1suf") ... -
DWREngine API 使用方法 (转载)
2008-01-16 17:21 2475//简易函数; abc(handler){ } DWRE ... -
dwr简介 (转载)
2008-01-16 16:39 1260最近Ajax比较火,全世界 ... -
dwr学习1 (转载)
2008-01-16 16:35 888这段时间较闲,研究了一 ... -
DWR源码学习(一)(转载
2008-01-16 16:10 1413DWR一个外国人实现的很有前途的AJAX框架。 多余的话就不说 ... -
JAVA中DWR开发项目实战经验(转载)
2008-01-16 16:06 1017自己在公司网站开发总用DWR开发的一个简单聊天 本人也是在网站 ... -
关于DWR2.0的配置问题(转载)
2008-01-16 16:00 894自从换工作之后就没有研究过DWR了。下载了最新的DWR2.0M ... -
ajax之旅--dwr探密(转载)
2008-01-16 15:58 792ajax是Asynchronous JavaScript an ... -
DWR使用笔记(转载)
2008-01-16 15:56 685DWR是一个框架,简单的说就是能够在javascript直接调 ... -
把DWR的配置写到Spring的配置文件里(转载)
2008-01-16 15:54 1066要读懂我这篇文章估计需要一些前期知识: 你要知道Spring是 ... -
DWR的学习文档(Hello World,类型转换,Spring,Annotation) (转载)
2008-01-16 15:37 1076DWR是作为远程调用的ajax框架,将服务端的java类,方法 ...
相关推荐
**Ajax + DWR**结合使用时,DWR作为一个中间层,处理JavaScript和Java之间的通信。开发者可以定义Java类和方法,DWR会自动生成对应的JavaScript接口,使得在浏览器中可以直接调用这些服务端方法。这样,我们可以在不...
DWR(Direct Web Remoting)是一种Java库,它允许JavaScript和Java在浏览器与服务器之间进行双向通信,而Ajax(Asynchronous JavaScript and XML)则是一种通过JavaScript实现异步数据交换和页面更新的技术,无需...
DWR(Direct Web Remoting)是一种在Web应用程序中实现异步JavaScript和XML(Ajax)的方法,它简化了客户端和服务器之间的通信,使得动态更新网页变得更加简单。DWR允许JavaScript直接调用Java方法,就像它们在同一...
DWR(Direct Web Remoting)是一种Java库,它允许JavaScript在浏览器端与服务器端的Java对象进行交互,实现了Ajax(Asynchronous JavaScript and XML)技术的一种高效应用。在传统的Web应用中,用户发起请求,服务器...
DWR是一个开源Java库,它允许Web应用程序在浏览器和服务器之间进行双向通信,即AJAX(Asynchronous JavaScript and XML)的增强版。在传统的AJAX中,数据请求通常由客户端发起,而DWR Reverse Ajax则允许服务器主动...
DWR(Direct Web Remoting)是一种JavaScript库,它允许Web应用程序实现服务器端与客户端之间的实时、双向通信,无需使用复杂的Ajax技术。DWR使得开发者能够像调用本地JavaScript函数一样轻松地调用服务器上的Java...
总的来说,DWR通过反向AJAX技术简化了服务器和客户端之间的通信,使得开发实时更新的应用变得更加便捷。通过学习和理解DWR的工作原理以及如何在项目中应用,你可以创建出更加动态、响应式的Web应用程序。
DWR(Direct Web Remoting)是一种Java库,它允许Web应用程序实现实时的双向通信,即反向Ajax。反向Ajax是指服务器能够主动地向客户端浏览器推送数据,而不仅仅是响应客户端的请求。DWR提供了三种反向Ajax技术,分别...
在DWR中,AJAX的实现变得更加简单,因为DWR提供了一套完整的框架,使得开发者可以方便地在客户端和服务器之间传递数据。 **DWR验证**通常用于实现用户输入的实时检查,例如在用户输入时检查邮箱地址的有效性、...
DWR是实现AJAX的一种工具,简化了AJAX应用的开发,隐藏了底层的HTTP通信细节,让开发者可以专注于业务逻辑。 6. **DWR的优缺点** 优点:易于使用,减少HTTP请求,提升用户体验;支持多种浏览器;提供丰富的API和...
描述中提到,DWR是基于AJAX的框架,这意味着它利用AJAX的优势,如后台数据传输和局部页面更新,简化了开发者实现无刷新功能的难度。这种技术适用于构建动态的、交互性强的门户网站,对于追求高效、流畅用户体验的...
**DWR (Direct Web Remoting) 是一个开源的Java库,它允许JavaScript在客户端与服务器端之间进行直接的异步通信,从而实现AJAX(Asynchronous JavaScript and XML)应用程序的功能。DWR使得开发者无需手动编写复杂的...
**DWR(Direct Web Remoting)**是一种Java库,它允许在浏览器和服务器之间进行实时、双向通信,从而实现AJAX(Asynchronous JavaScript and XML)应用程序。DWR简化了JavaScript与Java后端交互的过程,无需手动编写...
Direct Web Remoting (DWR) 是一种简化Ajax应用开发的框架。它允许JavaScript代码直接调用服务器端的Java方法,并处理返回的结果。本文将详细介绍如何在Struts2项目中利用DWR实现Ajax异步提交信息的过程。 #### 二...
DWR (Direct Web Remoting) 是一种基于Ajax的Java框架,它简化了JavaScript与Java之间的通信过程,使得开发者能够更加高效地构建富客户端应用程序。 #### 二、DWR简介 DWR由Joe Walker创建,首次发布于2003年,是...
DWR (Direct Web Remoting) 是一个开源Java库,它允许Web应用程序在客户端JavaScript和服务器端Java之间进行异步通信,实现了类似Ajax的功能。在这个小实例中,我们将探讨如何使用DWR来实现实时的文件上传功能,这...
这是我用dwr做的一个例子,非常好懂,就是一个文本框,旁边一个按钮,连接了mysql数据库,在文本框里输入注册名,如果数据库里面已有,就会在旁边提示出来,用的是DWR技术,DER是ajax技术里的一个框架,简单易学,只要看了我这...
DWR的核心功能是通过JavaScript和Java之间的远程方法调用(Remote Method Invocation, RMI)来简化AJAX(Asynchronous JavaScript and XML)开发。在“dwr.rar_dwr_dwr ajax_dwr 实现 联动 标签”这个项目中,我们将...
1. **DWR与Ajax**:DWR是基于Ajax技术的框架,它允许JavaScript在浏览器端与服务器端的Java对象进行实时通信,而无需刷新整个页面。通过这种方式,DWR使得Web应用能够实现更加动态和响应式的用户界面,提高交互性。 ...