DWR 后台推送(线程监听、多页面推送,附完整实例)

引自:http://caizhenyao.iteye.com/blog/1747218

DWR2.x的推技术也叫DWR Reverse Ajax(逆向Ajax)主要是在BS架构中,从服务器端向多个浏览器主动推数据的一种技术。 



在DWR所开的线程中使用Reverse Ajax时,通过WebContextFactory.get()获取WebContext对象,进而获取脚本Session。 


在DWR之外使用Reverse Ajax时,就要用到ServerContext,在Spring环境中要得到ServerContext,就需要用到Spring的ServletContextAware接口。 



一、Reverse Ajax的实现有3种方式: 

      DWR的逆向Ajax主要包括两种模式:主动模式和被动模式。其中主动模式包括polling和comet两种,被动模式只有piggyback这一种。 



     1、piggyback方式 

           这是默认的方式。 

           如果后台有什么内容需要推送到前台,是要等到那个页面进行下一次ajax请求的时候,将需要推送的内容附加在该次请求之后,传回到页面。 
           只有等到下次请求页面主动发起了,中间的变化内容才传递回页面。 



      2、comet方式 

           当服务端建立和浏览器的连接,将页面内容发送到浏览器之后,对应的连接并不关闭,只是暂时挂起。如果后面有什么新的内容需要推送到客户端的时候直接通过前面挂起的连接再次传送数据。 

           服务器所能提供的连接数目是一定的,在大量的挂起的连接没有关闭的情况下,可能造成新的连接请求不能接入,从而影响到服务质量。 



      3、polling方式 

           由浏览器定时向服务端发送ajax请求,询问后台是否有什么内容需要推送,有的话就会由服务端返回推送内容。这种方式和我们直接在页面通过定时器发送ajax请求,然后查询后台是否有变化内容的实现是类似的。只不过用了dwr之后这部分工作由框架帮我们完成了。 





二、使用DWR的推技术的步骤 

     1、在web.xml文件中增加以下配置信息 

Xml代码  
<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>  
       
    <!-- DWR默认采用piggyback方式 -->  
       
    <!-- 使用polling和comet的方式 -->  
    <init-param>  
        <param-name>pollAndCometEnabled</param-name>  
        <param-value>true</param-value>  
    </init-param>  
       
    <!-- comet方式 -->  
    <!--    
    <init-param>  
        <param-name>activeReverseAjaxEnabled</param-name>  
        <param-value>true</param-value>  
    </init-param>  
     -->  
        
    <!-- polling方式:在comet方式的基础之上,再配置以下参数 -->  
    <!--    
    <init-param>  
        <param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>  
        <param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value>  
    </init-param>  
     -->  
         
    <!-- 毫秒数。页面默认的请求间隔时间是5秒 -->  
    <!--    
    <init-param>  
        <param-name>disconnectedTime</param-name>  
        <param-value>60000</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>  

<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> 

<!-- DWR默认采用piggyback方式 --> 

<!-- 使用polling和comet的方式 --> 
<init-param> 
<param-name>pollAndCometEnabled</param-name> 
<param-value>true</param-value> 
</init-param> 

<!-- comet方式 --> 
<!-- 
<init-param> 
<param-name>activeReverseAjaxEnabled</param-name> 
<param-value>true</param-value> 
</init-param> 
--> 

<!-- polling方式:在comet方式的基础之上,再配置以下参数 --> 
<!-- 
<init-param> 
<param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name> 
<param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value> 
</init-param> 
--> 
  
<!-- 毫秒数。页面默认的请求间隔时间是5秒 --> 
<!-- 
<init-param> 
<param-name>disconnectedTime</param-name> 
<param-value>60000</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>Xml代码  
<listener>  
        <listener-class>org.directwebremoting.servlet.EfficientShutdownServletContextAttributeListener</listener-class>  
</listener>  

<listener> 
        <listener-class>org.directwebremoting.servlet.EfficientShutdownServletContextAttributeListener</listener-class> 
</listener>Xml代码  
<listener>  
        <listener-class>org.directwebremoting.servlet.EfficientShutdownServletContextListener</listener-class>  
</listener>  

<listener> 
        <listener-class>org.directwebremoting.servlet.EfficientShutdownServletContextListener</listener-class> 
</listener> 

    2、在dwr.xml中增加以下配置信息 

Xml代码  
<create creator="new" javascript="DWRHelper">  
    <param name="class" value="com.cjm.web.dwr.DWRHelper"/>  
    <include method="addMessage"/>  
    <include method="test"/>  
</create>  
  
<convert converter="bean" match="com.cjm.web.dwr.Message">  
    <param name="include" value="id,text"/>  
</convert>  

<create creator="new" javascript="DWRHelper"> 
<param name="class" value="com.cjm.web.dwr.DWRHelper"/> 
<include method="addMessage"/> 
<include method="test"/> 
</create> 

<convert converter="bean" match="com.cjm.web.dwr.Message"> 
<param name="include" value="id,text"/> 
</convert> 

    3、pojo类Message的源码 

Java代码  
public class Message {   
    private long id = System.currentTimeMillis();   
    private String text;   
       
    public Message(){   
           
    }   
       
    public Message(String newText){   
        text = newText;   
    }   
       
    public long getId() {   
        return id;   
    }   
    public void setId(long id) {   
        this.id = id;   
    }   
    public String getText() {   
        return text;   
    }   
    public void setText(String text) {   
        this.text = text;   
    }   
 

public class Message { 
private long id = System.currentTimeMillis(); 
private String text; 

public Message(){ 

} 

public Message(String newText){ 
text = newText; 
} 

public long getId() { 
return id; 
} 
public void setId(long id) { 
this.id = id; 
} 
public String getText() { 
return text; 
} 
public void setText(String text) { 
this.text = text; 
} 
} 

     4、DWRHelper类源码 

Java代码  
public class DWRHelper {   
    private static LinkedList<Message> messages = new LinkedList<Message>();   
    private static ReentrantLock lock = new ReentrantLock(); //JDK5锁   
       
    public void addMessage(String text){   
        try{   
            lock.lock();   
               
            if(text!=null && text.trim().length()>0){   
                messages.addFirst(new Message(text));   
                if(messages.size()>10){   
                    messages.removeLast();   
                }   
            }   
        }catch(Exception ex){   
            ex.printStackTrace();   
        }finally{   
            lock.unlock();   
        }   
           
        //获得DWR上下文   
        WebContext webContext = WebContextFactory.get();   
           
        //获取当前页面URL,比如/ext3/test_tag.jsp   
        String currentPage = webContext.getCurrentPage();   
           
        //当前脚本sessin   
        ScriptSession scriptSession = webContext.getScriptSession();   
           
        //设置页面控件的值   
        Util util = new Util(scriptSession);   
        util.setValue("text", ""); //这里是清空页面输入框的值   
           
        //设置脚本sessin的属性值   
        scriptSession.setAttribute("uid", "cjm");   
           
        //获取脚本session的属性值   
        for(Iterator it=scriptSession.getAttributeNames();it.hasNext();){   
            String attrName = (String)it.next();   
            System.out.println(attrName + "=" + scriptSession.getAttribute(attrName));   
        }   
           
        //获取所有浏览当前页面的脚本session   
        Collection<ScriptSession> sessions = webContext.getScriptSessionsByPage(currentPage);   
           
        Util utilAll = new Util(sessions);   
           
        //执行客户端脚本   
        ScriptBuffer script = new ScriptBuffer();   
        script.appendScript("clientFunction(")   
          .appendData(scriptSession.getAttribute("uid"))   
          .appendScript(");");   
           
        for(ScriptSession session: sessions){   
            session.addScript(script);   
        }   
           
        //更新这些脚本session的一些元素   
        utilAll.removeAllOptions("messages");   
        utilAll.addOptions("messages", messages, "id", "text");   
    }   
 

public class DWRHelper { 
private static LinkedList<Message> messages = new LinkedList<Message>(); 
private static ReentrantLock lock = new ReentrantLock(); //JDK5锁 

public void addMessage(String text){ 
try{ 
lock.lock(); 

if(text!=null && text.trim().length()>0){ 
messages.addFirst(new Message(text)); 
if(messages.size()>10){ 
messages.removeLast(); 
} 
} 
}catch(Exception ex){ 
ex.printStackTrace(); 
}finally{ 
lock.unlock(); 
} 

//获得DWR上下文 
WebContext webContext = WebContextFactory.get(); 

//获取当前页面URL,比如/ext3/test_tag.jsp 
String currentPage = webContext.getCurrentPage(); 

//当前脚本sessin 
ScriptSession scriptSession = webContext.getScriptSession(); 

//设置页面控件的值 
Util util = new Util(scriptSession); 
util.setValue("text", ""); //这里是清空页面输入框的值 

//设置脚本sessin的属性值 
scriptSession.setAttribute("uid", "cjm"); 

//获取脚本session的属性值 
for(Iterator it=scriptSession.getAttributeNames();it.hasNext();){ 
String attrName = (String)it.next(); 
System.out.println(attrName + "=" + scriptSession.getAttribute(attrName)); 
} 

//获取所有浏览当前页面的脚本session 
Collection<ScriptSession> sessions = webContext.getScriptSessionsByPage(currentPage); 

Util utilAll = new Util(sessions); 

//执行客户端脚本 
ScriptBuffer script = new ScriptBuffer(); 
script.appendScript("clientFunction(") 
  .appendData(scriptSession.getAttribute("uid")) 
  .appendScript(");"); 

for(ScriptSession session: sessions){ 
session.addScript(script); 
} 

//更新这些脚本session的一些元素 
utilAll.removeAllOptions("messages"); 
utilAll.addOptions("messages", messages, "id", "text"); 
} 
} 

    5、JSP页面源码 

Html代码  
<%@ page language="java" pageEncoding="UTF-8"%>  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
  <head>  
    <script type='text/javascript' src='/ext3/dwr/engine.js'></script>  
    <script type='text/javascript' src='/ext3/dwr/util.js'></script>  
    <script type='text/javascript' src='/ext3/dwr/interface/DWRHelper.js'></script>  
  </head>  
     
  <!-- 通过 dwr.engine.setActiveReverseAjax(true); 启动该页面的Reverse Ajax功能  -->  
  <body onload="dwr.engine.setActiveReverseAjax(true);sendMessage();">  
    <p>输入信息: <input id="text" onkeypress="dwr.util.onReturn(event, sendMessage)" />    
    <input type="button" value="Send" onclick="sendMessage()" /></p>  
  
    <script type="text/javascript">  
        function sendMessage() {   
            DWRHelper.addMessage(dwr.util.getValue("text"));   
        }   
    </script>  
       
    <hr/>  
    <select id="messages"></select>  
       
  </body>  
</html>  

 

 

以上文章从别的地方直接复制过来的,楼主懒得详细描述。。后面附实例下载地址,里面有详细的注释说明,主要实现DWR推送、线程监听、事件监听、主动推送。。写得不好,请见谅。。然后有个特别需要注意的,部署好项目以后,访问的方式是:http://localhost:9999/MonitorSystem/indexTo,特别注意indexTo,因为是Spring MVC转发请求。。测试的时候,打开两个页面,分别是生产数据页面还有查看数据页面,当点击生产数据页面后,查看数据页面就会收到从后台推送过来的数据。。http://yun.baidu.com/share/link?shareid=1734778619&uk=2031663908

posted @ 2014-03-05 12:00  叶汉城  阅读(2454)  评论(1编辑  收藏  举报