本文摘自: http://slei.net 在Liferay Portal中使用DWR Portal的概念风风火火地炒了好几年,确始终没有大红大紫。眼看着Ajax和Web 2.0朝自己杀来,靠Portal产品过日子的厂商们也终于按耐不住了。老牌开源Portal产品Liferay在其4.0版本中就加入了Ajax的东东,其Portlet的移动、添加和删除就是基于Ajax的。但是这远远是不够的,如果不能在产品级别更好的支持Portlet内部的Ajax,那么传统的Portal很可能会穷途末路,因为完全基于Ajax的PortalFramework已经出现了,如Light。 然而无论Ajax和Web 2.0发展成什么样,有一点它是无法取代Portal的,就是Web系统的组件化乃至服务化。Portal最有价值的地方也就是提出了把Web系统当作组件或服务来集成,这样,无论是遗留下来的Web系统,还是新开发的Web系统,都可以很简单地集成在一块儿,并且,把某个Web系统替换掉也是很简单的。也许不久的将来,Ajax和Web 2.0的阵营中也会出现把Web系统当作组件或服务的技术,但是这其实就是Portal的概念,换汤不换药。 前阵子有机会在Liferay Portal下开发一些Ajax的Portlet,其中用到了DWR,有些tricky的地方,写在这里方便各位,也方便自己。 在Portlet的jsp中引用DWR的js不能简单地直接使用相对路径,比如,如果DWR的js相对jsp放在/dwr目录中的话,如下的引用方式是不对的: <script type="text/javascript" src="/dwr/engine.js"></script> <script type="text/javascript" src="/dwr/util.js"></script> <script type="text/javascript" src="/dwr/interface/YourClass.js"></script> 因为当你把Portlet部署到Liferay的时候,这个相对路径的意义就变了。为了正确引用js,我们必须使用如下的声明方式: <script type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath() + "/dwr/engine.js") %>'> </script> <script type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath() + "/dwr/util.js") %>'> </script> <script type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath() + "/dwr/interface/RssReader.js") %>'> </script> <script type='text/javascript' src='/dwr/interface/SelectProductTypeSearch.js'></script> <script type='text/javascript' src='/dwr/interface/SelectSchoolBuildingSearch.js'></script> <script type='text/javascript' src='/dwr/engine.js'></script> <script type='text/javascript' src='/dwr/util.js'></script> 其中的renderRequest和renderResponse是Liferay Portal添加到jsp中的隐含变量,负责对Portlet进行渲染。renderRequest.getContextPath()就是当前jsp的路径,加上js相对于jsp的路径,最后要用renderResponse.encodeURL()方法解码一下才能得到正确的路径。 其他方面,DWR的使用方法就和在一般的jsp中的使用方法一样了。从这里也可以看出,不光是使用DWR,所有对js及其他资源的引用都要用这种方法。 如何实现DWR的多人同时开发 这几天研究了一下DWR,觉的有了这个东东后,Ajax就非常Easy了,可以说是不用学了,我用的是1.1.1的版本,2.0的版本目前还在开发,具体的网址是http://getahead.ltd.uk/dwr/documentation,里面说的很简单,对Web开发比较熟的化,一天就能全学会,不过要做好的话,还是需要在工作中遇到具体的问题再具体解决,再和Spring和Hibernate一结合的化,感觉能大大加快开发进度,现在主要说说如何配置多个dwr.xm,这样的化就可以多个人同时开发,互不影响,这对公司的版本控制还是比较有益处的. 主要是在web.xml中配置 <servlet> <servlet-name>dwr-user-invoker</servlet-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>config-user</param-name> <param-value>WEB-INF/dwr-user.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet> <servlet-name>dwr-admin-invoker</servlet-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>config-admin</param-name> <param-value>WEB-INF/dwr-admin.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr-admin-invoker</servlet-name> <url-pattern>/dwradmin/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>dwr-user-invoker</servlet-name> <url-pattern>/dwruser/*</url-pattern> </servlet-mapping> 这样的话在WEB-INF文件夹下就新增两个XML文件,分别为dwr-user.xml,dwr-admin.xml就行了,然后访问:http://localhost:8080/your app/dwruser就能看到它的测试页面了,把它的javascript文件的存放位置拷下来,放到你的JSP或html文件中,就OK了,我觉的这个测试页主要也就是做这个的,它的一些测试方法,我觉的不是很好用.这样就可以同时有多个XML的配置文件,大家同时开发不影响. 最后记住一点,为了搞明白这一点,花了我一下午和晚上的时间,就是在你的web app目录中,不要创建dwruser或dwradmin这样的目录,更不要把Jsp或html放进去,否则的话,不管用绝对还是相对路径都找不到.
<script type='text/javascript' src='/dwr/dwr/interface/JDate.js'></script> <script type='text/javascript' src='/dwr/dwr/engine.js'></script> <script type='text/javascript' src='/dwr/dwr/util.js'></script> dwr的页面必须放在根文件么?(20分) 所属论坛: Web 开发 Ajax 发表时间: 2006-8-12 11:07:19 配置如下: 1.xml文件 <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> </web-app> 2.dwr.xml <?xml version="1.0" encoding="UTF-8"?> <!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="FirstAjax"> <param name="script" value="com.ajax.start.FirstAjax" /> </create> <create creator="new" javascript="DwrTest"> <param name="class" value="com.ajax.start.DwrTest"/> <param name="script"> <![CDATA[ com.ajax.start.DwrTest; return DwrTest.getInstance(); ]]> </param> <include method="getMessage"/> </create> </allow> </dwr> 3.index.html <html> <head> <title> now start ajax </title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/> <script type="text/javascript" src="./dwr/interface/FirstAjax.js"></script> <script type="text/javascript" src="./dwr/engine.js"></script> <script type="text/javascript" src="./dwr/util.js" ></script> <script type="text/javascript" src="./dwr/interface/DwrTest.js" ></script> <script type="text/javascript"> function sendMessage(msg) { alert ("123"); var msgvalue = document.getElementById(msg).value; FirstAjax.getGreetings(loadMessage, msgvalue); } function loadMessage(data) { document.getElementById("message").innerHTML = data; } function getMessage(){ DwrTest.getMessage(load,1); } function load(data){ document.getElementById("message").innerHTML=data; var row = createElement("tr"); var nodetext=create } </script> </head> <body> <h2> ajax is coming....</h2> <table> <tr> <td>following...</td> </tr> <tr> <td> <input type="text" name="msg" size="30"> <input type="button" value="click me" name="tt" οnclick="sendMessage('msg')"> <input type="button" value="test1" name="tt" οnclick="getMessage()"> </td> </tr> <tr> <td> <div id="message"></div> </td> </tr> </table> </body> </html> 目录结构: webroot/WEB-INF/WEB.XML webroot/WEB-INF/DWR.XML webroot/admin/index.html dwr测试页测试DwrTest方法正常,但在index.html上却提示DwrTest未定义。把index.html放在webroot/目录下能正常显示。求解 第1楼 2006-8-12 11:15:00 返回顶部 ...... <script type="text/javascript" src="../dwr/interface/FirstAjax.js"></script> <script type="text/javascript" src="../dwr/engine.js"></script> <script type="text/javascript" src="../dwr/util.js" ></script> <script type="text/javascript" src="../dwr/interface/DwrTest.js" ></script> 原来是这样,结帖 ———————————————————————— AJAX,可不是荷兰阿贾克斯足球队,是一种利用XMLHTTP请求的技术,本文介绍DWR实现AJAX的框架。 1, 获取dwr.jar http://www.getahead.ltd.uk/dwr/download.html 获得的dwr.jar放到WEB-INF/lib目录下 2, 配置web工程的web.xml文件 <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> 3, 创建一个dwr.xml文件,放在WEB-INF目录下和web.xml做伴 <dwr> <allow> <create creator="new" javascript="JDate"> <param name="class" value="java.util.Date"/> </create> <create creator="new" javascript="Demo"> <param name="class" value="your.java.Bean"/> </create> </allow> </dwr> 4, 按照指示,此时运行http://localhost:8080/YOUR_APP/dwr 应该出现一个页面,但是我运行的时候出错了,原因是dwr.xml文件缺点东西。 改为: <?xml version="1.0" encoding="UTF-8"?> <!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="JDate"> <param name="class" value="java.util.Date"/> </create> <create creator="new" javascript="JString"> <param name="class" value="java.lang.String"/> </create> </allow> </dwr> 看到这个界面,我忽然有一个伟大的想法了!如果把jdk常用的类配置到这里,那么我们就可以很very方便的查看jdk API 各个方法的运行结果了哈。 关于dwr.dtd的说明,请参考 http://www.getahead.ltd.uk/dwr/server/dwrxml.html 【注意】 如果你使用的是dwr 0.8.x版本,这样写可能不对。我现在用的是0.9.2b版本。 5,点击页面列出的Jdate,可以查看java.util.Date()各个方法的输出,这是怎么实现的呢?查看一下源码,有几个很重要的地方。 <SCRIPT src="/ept/dwr/interface/JDate.js" type=text/javascript></SCRIPT> <SCRIPT src="/ept/dwr/engine.js" type=text/javascript></SCRIPT> <SCRIPT src="/ept/dwr/util.js" type=text/javascript></SCRIPT> 6,自己完整编写一个例子: 引用地址: http://yhe.dl.cn/html/trackback.do?log_id=178&type=1 (复制地址) 技术文摘 | 评论(7) | 阅读(1797) | Trackback(0) | ≡≡≡ 网友评论 ≡≡≡ 小红帽 网友说: 2005/12/29 16:14 建议看看这个http://www.amowa.net/buffalo_bak 198181 网友说: 2005/12/29 16:12 老实说,ajax还没有一个大众都可以去接受的“标准”框架。 这个框架也不太好用。 happy 网友说: 2005/11/25 16:43 为什么我在自己机器上装了可以用,装到另外一台机器就抱 dwrutil 未定义的错误啊 happy 网友说: 2005/11/25 16:35 sdf 阿獠二 网友说: 2005/07/18 11:38 lodestar51 网友说: 2005/07/13 21:17 前几天下载.看了一下DEMO,不太明白.以后向你学习.. 小红帽 网友说: 2005/07/07 10:18 其他资源: AJAX made simple with DWR http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-dwr_p.html http://www.getahead.ltd.uk/dwr/ Ajax 的一些资源汇总 http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=11362&threadID=23813&messageID=140065 ———————————————————————————————————————————— DWR(Direct Web Remoting)是一个WEB远程调用框架.利用这个框架可以让AJAX开发变得很简单.利用DWR可以在客户端利用JavaScript直接调用服务端的Java方法并返回值给JavaScript就好像直接本地客户端调用一样(DWR根据Java类来动态生成JavaScrip代码).它的最新版本DWR0.6添加许多特性如:支持Dom Trees的自动配置,支持Spring(JavaScript远程调用spring bean),更好浏览器支持,还支持一个可选的commons-logging日记操作. 以上摘自open-open,看了几天,确实是一个非常优秀的项目,它通过反射,将java翻译成javascript,然后利用回调机制,轻松实现了javascript调用Java代码。 其大概开发过程如下: 1.编写业务代码,该代码是和dwr无关的。 2.确认业务代码中哪些类、哪些方法是要由javascript直接访问的。 3.编写dwr组件,对步骤2的方法进行封装。 4.配置dwr组件到dwr.xml文件中,如果有必要,配置convert,进行java和javascript类型互转。 5.通过反射机制,dwr将步骤4的类转换成javascript代码,提供给前台页面调用。 5.编写网页,调用步骤5的javascript中的相关方法(间接调用服务器端的相关类的方法),执行业务逻辑,将执行结果利用回调函数返回。 6.在回调函数中,得到执行结果后,可以继续编写业务逻辑的相关javascript代码。 下面以用户注册的例子,来说明其使用。(注意,本次例子只是用于演示,说明DWR的使用,类设计并不是最优的)。 1.先介绍下相关的Java类 User: 用户类, public class User { //登陆ID,主键唯一 private String id; //姓名 private String name; //口令 private String password; //电子邮件 private String email; //以下包含getXXX和setXXX方法 ....... } UserDAO:实现User的数据库访问,这里作为一个演示,编写测试代码 public class UserDAO { //存放保存的数据 private static Map dataMap = new HashMap(); //持久用户 public boolean save(User user) { if (dataMap.containsKey(user.getId())) return false; System.out.println("下面开始保存用户"); System.out.println("id:"+user.getId()); System.out.println("password:"+user.getPassword()); System.out.println("name:"+user.getName()); System.out.println("email:"+user.getEmail()); dataMap.put(user.getId(), user); System.out.println("用户保存结束"); return true; } //查找用户 public User find(String id) { return (User)dataMap.get(id); } } DWRUserAccess:DWR组件,提供给javascript访问的。 public class DWRUserAccess { UserDAO userDAO = new UserDAO(); public boolean save(User user) { return userDAO.save(user); } public User find(String id) { return userDAO.find(id); } } 下面说明下程序执行的流程 1.用户在页面上输入相关注册信息,id、name、password、email,点击“提交”按钮 2.javascript代码开始执行,根据用户填写相关信息,通过dwr提供的DWRUserAccess.js里save的方法,调用服务器端的DWRUserAccess类save方法,将注册信息保存。 3.通过DWRUserAccess.jsp里的find方法,调用服务器端DWRUserAccess类里的find方法,执行用户信息查找。 注意,在以上的执行过程中,DWRUserAccess是供DWR调用的,是DWR组件,因此需要将DWRUserAccess类配置到dwr中。 接下来讲解本次dwr测试环境的配置。 1.新建一个webapp,命名为testApp 2.将dwr.jar拷贝到testApp的WEB-INF的lib目录下 3.编译上面的User,UserDAO,DWRUserAccess类,放到classes目录下 4.在web.xml中配置servlet,适配路径到dwr目录下,如下所示 <servlet> <servlet-name>dwr-invoker</servlet-name> <display-name>DWR Servlet</display-name> <description>Direct Web Remoter Servlet</description> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>scriptCompressed</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> 以上的配置可以拦截testApp下所有指向dwr的请求,关于这个拦截器,我们会在后面介绍。 5.WEB-INF下新建一个dwr.xml文件,内容如下: <?xml version="1.0" encoding="UTF-8"?> <!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="DWRUserAccess"> <param name="class" value="test.DWRUserAccess"/> </create> <convert converter="bean" match="test.User"/> </allow> </dwr> 这里我们把DWRUserAccess配置到了dwr中,create元素中,creater="new"表示每调用一次DWRUserAccess时,需要new一个这样的类;javascript="DWRUserAccess",表示提供给前台页面调用的javascirpt文件是DWRUserAccess.js。 convert元素用于数据类型转换,即java类和javascript之间相互转换,因为和前台交换的是User对象,因此需要对此使用bean转换,我们将在后面介绍这个类。 4.编写测试的HTML页面 test.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE>DWR测试</TITLE> <meta http-equiv=Content-Type content="text/html; charset=gb2312"> <script src="/oblog312/dwr/engine.js"></script> <script src="/oblog312/dwr/util.js"></script> <script src="/oblog312/dwr/interface/DWRUserAccess.js"></script> </HEAD> <BODY> <B>用户注册</B><br> ------------------------------------------------ <Br> <form name="regForm"> 登陆ID:<input type="text" name="id"><br> 口 令:<input type="password" name="password"><br> 姓 名:<input type="text" name="name"><br> 电子邮件:<input type="text" name="email"><br> <input type="button" name="submitBtn" value="提交" οnclick="OnSave()"><br> </form> <br> <br><B>用户查询</B><br> ------------------------------------------------ <Br> <form name="queryForm"> 登陆ID:<input type="text" name="id"><br> <input type="button" name="submitBtn" value="提交" οnclick="OnFind()"><br> </form> <br> </BODY> </HTML> <SCRIPT LANGUAGE="JavaScript"> <!-- function saveFun(data) { if (data) { alert("注册成功!"); } else { alert("登陆ID已经存在!"); } } function OnSave() { var userMap = {}; userMap.id = regForm.id.value; userMap.password = regForm.password.value; userMap.name = regForm.name.value; userMap.email = regForm.email.value; DWRUserAccess.save(userMap, saveFun); } function findFun(data) { if (data == null) { alert("无法找到用户:"+queryForm.id.value); return; } alert("找到用户,\nid:"+data.id+",\npassword:"+data.password+",\nname:"+data.name+",\nemail:"+data.email); } function OnFind() { DWRUserAccess.find(queryForm.id.value, findFun); } //--> </SCRIPT>
|