DWR的基本原理以及前后台互相调用并整合SPRING的简易DEMO

         工作也已经有几年了, 最近突然心血来潮, 想写点技术博客,记录在工作和学习中碰到的一些问题,一方面方便自己以后查看,一方面也可以帮助下碰到同类问题的朋友们。 好了,闲话少说,进入第一篇博客的正文。 
        最近工作中有一个需求,需要开发一个类似QQ的即时聊天系统,不过要基于BS架构,上网搜索了下,JAVA中的COMET技术可以成为实现该需求的良好途径。 
        comet 【计】:基于 HTTP 长连接的“服务器推”技术,是一种新的 Web 应用架构。基于这种架构开发的应用中,服务器端会主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求。Comet 架构非常适合事件驱动的 Web 应用,以及对交互性和实时性要求很强的应用,如股票交易行情分析、聊天室和 Web 版在线游戏等。(百度百科) 
        现在网上有不少开源的comet框架,比如pushlet,dwr等, 当然, 你也可以自用用jquery甚至纯JS来实现。 我这里选用了dwr,毕竟是比较成熟的框架了,用起来可能可以比较顺手些。 
        简单介绍下DWR,DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA函数,就像它就在浏览器里一样。(百度百科) 
        显然,楼主不方便把实际工作的代码放上来,这里就放一个简易的DEMO, DEMO实现了一些基本功能: 
        1. 前台调用后台的JAVA方法,并利用JAVA返回值执行回调函数。 
        2. 在后台中将数据发送至第二个页面,并调用该页面的JS方法。 
        3. 与SPRING的简单整合。 
        下面楼主把实现这个工程的步骤重复下。 
        第一步, 自然要先导入JAR包。 这个DEMO只需要DWR和SPRING2个JAR包,如需要可以在附件中下载(包含在DEMO的项目中)。 
        然后,配置WEB.xml文件,配置如下,功能基本已经写了注释,再补充一点,通过[项目地址]/dwr可以查看被dwr转化的类,可以点击进入测试页面,这样对于一些不知道怎么在实际页面中调用的初学者,可以查看源文件复制其代码。 在实际项目发布后将其设置为false,以避免用户进入此页面。 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   
  5.     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
  6.     <servlet>  
  7.         <!-- dwr配置 -->  
  8.         <servlet-name>dwr-invoker</servlet-name>  
  9.         <servlet-class>  
  10.             org.directwebremoting.servlet.DwrServlet  
  11.         </servlet-class>  
  12.         <init-param>  
  13.             <description>打开debug可以通过[项目地址]/dwr查看被加载的类</description>  
  14.             <param-name>debug</param-name>  
  15.             <param-value>true</param-value>  
  16.         </init-param>  
  17.         <init-param>  
  18.             <description>使用服务器推技术(反转AJAX)</description>  
  19.             <param-name>activeReverseAjaxEnabled</param-name>  
  20.             <param-value>true</param-value>  
  21.         </init-param>  
  22.         <init-param>  
  23.             <description>使用comet方式推送数据</description>  
  24.             <param-name>pollAndCometEnabled</param-name>  
  25.             <param-value>true</param-value>  
  26.         </init-param>  
  27.     </servlet>  
  28.     <servlet-mapping>  
  29.         <servlet-name>dwr-invoker</servlet-name>  
  30.         <url-pattern>/dwr/*</url-pattern>  
  31.     </servlet-mapping>  
  32.   
  33.   
  34.     <!-- Spring配置 -->  
  35.     <context-param>  
  36.         <param-name>contextConfigLocation</param-name>  
  37.         <param-value>/WEB-INF/classes/bean.xml</param-value>  
  38.     </context-param>  
  39.     <listener>  
  40.         <listener-class>  
  41.             org.springframework.web.context.ContextLoaderListener  
  42.         </listener-class>  
  43.     </listener>  
  44. </web-app>  

      接下去是dwr的配置文件dwr.xml,将它放在web.xml的同一级即可。 这里是最简单的和spring的整合配置,如需更加复杂的功能,请自行搜索。 
Xml代码   收藏代码
  1. <!DOCTYPE dwr PUBLIC  
  2.     "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"  
  3.     "http://www.getahead.ltd.uk/dwr/dwr10.dtd">  
  4. <dwr>  
  5.     <allow>  
  6.         <!-- 让dwr自动生成Controller.js文件 -->  
  7.         <create creator="spring" javascript="Controller">  
  8.             <param name="beanName" value="controller" />  
  9.         </create>  
  10.           
  11.         <!-- 转化器,DWR对于自定义的BEAN需要转换,可以用*表示所有 -->  
  12.         <convert match="songzl.message.User" converter="bean" />  
  13.       
  14.     </allow>  
  15. </dwr>  

下面spring的配置文件 bean.xml. 根据web.xml中的配置,将其放入src的根目录下。配置很简单,就是设置一个自动加载的bean的范围, 当然你也可以用<bean id="XXX" class="XXX"> 这样来加载。 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
  6.                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"  
  7.     default-lazy-init="true" default-autowire="byName">  
  8.   
  9.     <!-- 扫描songzl.message包下的类 并将其自动加载为spring的bean -->  
  10.     <context:component-scan base-package="songzl.message">  
  11.     </context:component-scan>  
  12. </beans>  

接下去2个JAVA类。 第一个user.java,一个放参数的javaben没什么可以多说 
Java代码   收藏代码
  1. package songzl.message;  
  2.   
  3. public class User {  
  4.     private String name;  
  5.     private String password;  
  6.     public String getName() {  
  7.         return name;  
  8.     }  
  9.     public void setName(String name) {  
  10.         this.name = name;  
  11.     }  
  12.     public String getPassword() {  
  13.         return password;  
  14.     }  
  15.     public void setPassword(String password) {  
  16.         this.password = password;  
  17.     }  
  18. }  

        第二个是控制类,Controller.java,也就是后台业务逻辑的主要实现类。 这里需要说下的是ScriptSession。ScriptSession是由DWR创建的,它用于保持长连接以管理页面。在JAVA中通过ServerContextFactory.get().getScriptSessionsByPage 来获取指定页面的ScriptSession以调用该页面的JS方法。关于ScriptSession后文还有一些补充。 
Java代码   收藏代码
  1. package songzl.message;  
  2.   
  3. import java.util.Collection;  
  4.   
  5. import org.directwebremoting.ScriptBuffer;  
  6. import org.directwebremoting.ScriptSession;  
  7. import org.directwebremoting.ServerContextFactory;  
  8. import org.springframework.stereotype.Component;  
  9.   
  10. @Component  
  11. public class Controller {  
  12.     public String getLoginUser(User user){  
  13.         final String result = "name: "+user.getName()+"----password:"+user.getPassword();  
  14.         System.out.println(result);  
  15.         String recivePage = "/DwrTest/message/reciver.jsp";    //接收方的页面 /项目名/页面  
  16.         Collection<ScriptSession> scss = ServerContextFactory.get().getScriptSessionsByPage(recivePage);//获取所有指定页面  
  17.         for(ScriptSession ss : scss){  
  18.             ss.addScript(new ScriptBuffer("reciverMes('"+result+"')"));   //调用页面的JS方法  
  19.         }  
  20.         return result;  
  21.     }  
  22. }  

接下去是发送页面,sender.jsp。 要注意不要忘记导入engine.js和Controller.js。 其中Controller.js是DWR根据你的配置文件自动帮你生成的。 
Java代码   收藏代码
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  7. <title>数据发送页面</title>  
  8. <script type='text/javascript' src='/DwrTest/dwr/engine.js'></script>  
  9. <script type="text/javascript" src="/DwrTest/dwr/interface/Controller.js"></script>    
  10. <script type="text/javascript">  
  11.     function submitLogin(){  
  12.          var name=document.getElementById("name").value;     
  13.          var password=document.getElementById("password").value;     
  14.          var obj={name:name,password:password};        //obj需要在dwr.xml中配置conventer,字段名需要和class中的一致  
  15.          //回调函数,返回JAVA方法中的返回值  
  16.          Controller.getLoginUser(obj,function(data){   
  17.                 alert("返回的值是"+data);  
  18.          })  
  19.     }  
  20. </script>    
  21. </head>  
  22. <body>  
  23.     账号 :<input type="text" id="name"/>  
  24.     密码 : <input type="text" id="password"/>  
  25.     <input type="submit" value="提交" οnclick="submitLogin()"/>  
  26. </body>  
  27. </html>  


最后是接收的页面。 reciver.jsp。 要注意的是一定不要忘记加上οnlοad="dwr.engine.setActiveReverseAjax(true)" 楼主一开始就是忘了这句。 结果怎么也调试不出来。 蛋疼呐    
Java代码   收藏代码
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  7. <title>数据接受页面</title>  
  8. <script type='text/javascript' src='/DwrTest/dwr/engine.js'></script>  
  9. <script type="text/javascript">  
  10.     function reciverMes(mes){  
  11.         alert(mes);  
  12.     }  
  13. </script>    
  14. </head>  
  15. <body οnlοad="dwr.engine.setActiveReverseAjax(true)">  
  16.     <font size='5'>当发送页面点击发送信息, 本地可以立即接受到发来的消息</font>  
  17. </body>  
  18. </html>  

         这样这个工程基本就定型了。 打开http://localhost:8080/DwrTest/message/sender.jsp和http://localhost:8080/DwrTest/message/reciver.jsp两个页面。 在第一个页面的输入框中随便填一点值,点击提交。 第一个页面会执行其回调函数。 第二个页面会执行controller中的方法。 (注意 为示区别 2个页面alert的值是不一样的) 
          最后,对ScriptSession作一点补充。"当我们访问一个页面的时候,如果是第一次访问,就会创建一个新的HttpSession,之后再访问的时候,就会保持当前的Session,即使是刷新,也能保持当前的HttpSession。 但是,ScriptSession不同,第一次访问,会创建一个ScriptSession,但是,如果你刷新,就会创建一个新的ScriptSession". 通过这段描述不难发现,如果用户多次刷新页面,将产生无数个无用的ScriptSession, 占了内存不说还会影响后来用户的链接。 
          怎么解决呢?DWR3 提供了ScriptSessionManager 这个接口来管理ScriptSession。 大家可以写一个类 复写DefaultScriptSessionManager这个方法,在其中捕获无用的scriptSession,并调用scriptSession.invalidate()将其无效化。 然后在WEB.XML的DWR的servlet配置中加入下面的代码: 
Xml代码   收藏代码
  1. <init-param>  
  2.             <param-name>  
  3.                 org.directwebremoting.extend.ScriptSessionManager  
  4.             </param-name>  
  5.             <param-value>  
  6.                        你的实现类(X.X.XXX)  
  7.             </param-value>  
  8.         </init-param>  

        具体实现代码就不贴了,可以通过搜索引擎搜索下。 并不是很复杂。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值