基于dwr2.0的Push推送技术详细解析以及实例

标签: dwr2 push 推送技术 | 发表时间:2013-04-23 10:55 | 作者:luqin1988
出处:http://blog.csdn.net

DWR从2.0开始增加了push功能,也就是在异步传输的情况下可以从Web-Server端发送数据到
Browser.
我们知道,Web的访问机制天生是设计用来pull数据的,也就是只允许Browser端主动发起请求,server
是被动的响应.不允许Server向Browser发出一个connection请求,也就是说没有为server向Browser
push数据提供设计实现.
虽然没有直接的实现方法,却可以使用一些变通的方式完成类似的功能:
1. Polling
Polling其实就是轮询,是通过Browser在一个相对短的间隔时间内,反复向Server发出请求,然
后更新页面,这种方式没有什么新鲜的,只是需要浏览器端做一些工作就可以,哪怕没有太多服务器端的配
置也没问题.轮询的方式对于服务器来说会依据不同的访问间隔而产生不同程度的额外负载,因为每次访
问都有重新建立连接的过程.
2. Comet
Comet方式通俗的说就是一种长连接机制(long lived http).同样是由Browser端主动发起请
求,但是Server端以一种似乎非常慢的响应方式给出回答,这样在这个期间内,服务器端可以使用同一个
connection把要更新的数据主动发送给Browser.Comet又有很多中实现方式,但是总的来说对Server
端的负载都会有增加.虽然对于单位操作来说,每次只需要建议一次connection,但是由于connection是
保持较长时间的,对于server端的资源的占用要有所增加.
3. Piggyback
Piggyback方式是一种半主动的方式,也就是说还是由Browser主动发出请求,但是每次请求的
响应中除了当次的响应之外,还会把上次请求以来已经发生的变化同时发给Browser.也就是说,当次请
求的更新会搭载到下一次请求的响应中一并发回.这样,在Browser的感觉就好象上一次请求又有了更
新.但是这种感觉取决于Browser向Server发出请求的频度.如果,第二次请求迟迟没有发出,那么上一次
的更新就不会取到.
在DWR2.0中可以使用Active(主动) 和 Passive(被动)两种工作模式,在这里我们主要讨论
Active(主动)模式.Active(主动)模式又分为以下3种:
• Full Streaming Mode
• Early Closing Mode
• Polling Mode
Full Streaming Mode
这是Active模式下的一种默认配置,具有很快的响应速度,而且建立好的链接只有每60秒检查一次浏
览器是否是活跃的.这种工作模式的配置非常简单,在Web.xml中配置DWR的时候,加上下面的内容:

<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>
</servlet>

然后在Browser页面端加上下面一句就可以了:
dwr.engine.setActiveReverseAjax(true);
需要说明的是,长链接会增加Server的资源占用,有些Server比如Jetty允许在客户端关闭线程
(connection),在新版本中会把这种能力延伸到GlassFish 和Tomcat.总之,DWR的主导思想是尽
量保护Server,减小负载.
Early Closing Mode
在Browser和Server之间有Proxy或者mod_jk的情况下,需要能够良好的工作,需要这种模式:这种
模式和Full Streaming Mode相似,以Full模式开启connection,但是,如果没有输出的情况下,
它会在一个配置好的时间内关闭Connection,通常这个时间是60秒.
从2.04版开始,DWR默认使用Early Closing Mode,如果要要想使用Full Streaming Mode,需
要进行如下的配置:
<init-param>
<param-name>maxWaitAfterWrite</param-name>
<param-value>-1</param-value>
</init-param>

这里,设置maxWaitAfterWrite是-1,表示这个时间和Full Streaming Mode一样,设置关闭时间是60
秒.
Polling Mode
Polling Mode 是一种轮询方式,这可以避免长时间保持连接而产生的对服务器资源的占用.如果要是用
轮询方式,还需要做以下的配置:
<init-param>
<param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>
<param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value>
</init-param>
<init-param>
<param-name>disconnectedTime</param-name>
<param-value>60000</param-value>
</init-param>
这是将轮询周期改为6000毫秒,也就是6秒

让Web具备了Push的方式,这对于很多应用是梦寐以求的,比如,如果有一个基于Web的网络聊天系统,
如果使用Push技术可以更加满足功能的需要,还有比如说一些需要server端根据数据条件主动向
browser端发送数据的应用需求,都非常需要这样的功能.
下面就举一个股票报盘的例子,能够让Server端通过主动的方式想Browser端发送股票信息.

先说一下所需jar包:dwr.jar commons-logging.jar
然后介绍如何配置:
1. 在web.xml中配置如下内容:

<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>activeReverseAjaxEnabled</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. 在dwr.xml中配置如下内容:
<dwr>
<allow>
<!-- Reverse Ajax Stock push Demo Config -->
<create creator="new" javascript="StocksPusher">
<param name="class" value="dwr.reverse.StocksPusher"/>
</create>
</allow>
</dwr>

3. 股票报盘的页面getStockInfo.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>DWR Reverse Ajax Demo : Show Stock info</title>
<link rel="stylesheet" type="text/css" href="generic.css" />
<script type='text/javascript' src='/AjaxShow/dwr/engine.js'></script>
<script type='text/javascript' src='/AjaxShow/dwr/util.js'></script>
<script type='text/javascript' src='/AjaxShow/dwr/interface/
StocksPusher.js'></script>
<script type="text/javascript">
function beginShow() {
StocksPusher.beginShow();
StocksPusher.sendStocks();
}
function endShow(){
StocksPusher.closeShow();
}
</script>
</head>
<body onload="dwr.engine.setActiveReverseAjax(true);">
<h3>使用DWR Reverse Ajax进行股票报盘</h3>
<p>下面显示的股票信息是可以动态变化的</p>
<input type="button" value="开市..." onclick="beginShow()"/>
=========================
<input type="button" value="闭市..." onclick="endShow()"/>
<hr>
<table style="width:500px" border="0" cellpadding="0">
<tr>
<td class="headName" ><b>Stock Name</b></td>
<td class="headValue" ><b>Stock Value</b></td>
</tr>
<tr><td>中移动</td><td><div id="zyd">wait...</div></td></tr>
<tr><td>中石化</td><td><div id="zsh">wait...</div></td></tr>
<tr><td>中石油</td><td><div id="zsy">wait...</div></td></tr>
<tr><td>海尔电器</td><td><div id="hedq">wait...</div></td></tr>
<tr><td>冀东水泥</td><td><div id="jdsn">wait...</div></td></tr>
<tr><td>用友软件</td><td><div id="yyrj">wait...</div></td></tr>
<tr><td>柳钢股份</td><td><div id="lggf">wait...</div></td></tr>
<tr><td>招商银行</td><td><div id="zsyh">wait...</div></td></tr>
<tr><td>中国铁建</td><td><div id="zgtj">wait...</div></td></tr>
<tr><td>深发展</td><td><div id="sfz">wait...</div></td></tr>
<tr><td>金山软件</td><td><div id="jsrj">wait...</div></td></tr>
<tr><td>大连实德</td><td><div id="dlsd">wait...</div></td></tr>
<tr><td>九寨沟</td><td><div id="jzg">wait...</div></td></tr>
<tr><td>中国平安</td><td><div id="zgpa">wait...</div></td></tr>
<tr><td>工商银行</td><td><div id="gsyh">wait...</div></td></tr>
<tr><td>鞍钢股份</td><td><div id="aggf">wait...</div></td></tr>
<tr><td>中国航天</td><td><div id="zght">wait...</div></td></tr>
</table>
<br>
</body>
</html>

4. 报盘的主程序StocksPusher.java ,关键部分在代码后面有中文注释
package dwr.reverse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.proxy.dwr.Util;
import org.directwebremoting.util.Logger;
/**
* Reverse Ajax class.
*
* @author Henry Huang
*/
public class StocksPusher {
private static boolean closeMarket = false;
/**
* Initialize the stocklist with values.
*/
public StocksPusher() {
}
/**
* Send the Stock-Values to the file "getStockInfo.html"
*/
public void sendStocks() throws InterruptedException {
WebContext wctx = WebContextFactory.get(); //这里是获取WebContext上下文
String currentPage = wctx.getCurrentPage(); //从上下文中获取当前页面,这些是DWR
Reverse Ajax 要求的必须方式
Collection sessions = wctx.getScriptSessionsByPage(currentPage); //再一个page中
可能存在多个ScriptSessions,
Util utilAll = new Util(sessions); //Util 是DWR 在Server端模拟Brower端 dwr.util.js
的类, Engine也是
while(true){
Thread.sleep(500);
if(closeMarket) break;
StocksBean stock = StockPriceTracer.getNextStockInfo();
utilAll.setValue(stock.getStock(), stock.getValue()); //这里的setValue()用法和
dwr.util.js中的setValue()函数用法完全一样,第一个参数是页面Element的id ,第二个参数是对该id
赋的新值
System.out.println("Pushing stock: " + stock.getStock() + " = " +
stock.getValue());
}
}
public void beginShow(){
closeMarket = false;
}
public void closeShow(){
closeMarket = true;
}
}

5. 还有一个类是为了模拟实时获取股票信息的工具StockPriceTracer.java,也可能是访问数据库,
也可能来至卫星的大盘数据,等等,这个类是用随机的方法获得股票价格:
package dwr.reverse;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Stack;
/**
* Reverse Ajax class.
*
* @author Henry Huang
*/
public class StockPriceTracer {
private static StockPriceTracer tracer = null;
private List<StocksBean> stocks = new ArrayList<StocksBean>();
private Stack<StocksBean> cycleStack = new Stack<StocksBean>();
private StockPriceTracer(){
stocks.add(new StocksBean("zsy", "36.55"));
stocks.add(new StocksBean("dlsd", "91.01"));
stocks.add(new StocksBean("zsh", "22.59"));
stocks.add(new StocksBean("lggf", "5.07"));
stocks.add(new StocksBean("hedq", "71.77"));
stocks.add(new StocksBean("jdsn", "31.61"));
stocks.add(new StocksBean("yyrj", "51.29"));
stocks.add(new StocksBean("zsyh", "52.70"));
stocks.add(new StocksBean("zgtj", "16.96"));
stocks.add(new StocksBean("sfz", "54.34"));
stocks.add(new StocksBean("jsrj", "178.48"));
stocks.add(new StocksBean("zyd", "134.48"));
stocks.add(new StocksBean("jzg", "76.32"));
stocks.add(new StocksBean("zgpa", "80.63"));
stocks.add(new StocksBean("gsyh", "18.79"));
stocks.add(new StocksBean("aggf", "20.19"));
stocks.add(new StocksBean("zght", "11.13"));
}
public static StocksBean getNextStockInfo(){
if(null == tracer) tracer = new StockPriceTracer();
if(tracer.cycleStack.empty()) tracer.cycleStack.addAll(tracer.stocks);
StocksBean tmp = tracer.cycleStack.pop();
tmp.setValue(tracer.getRandomPrice(tmp.getValue()));
return tmp;
}
private String getRandomPrice(String current){
float fcurrent = 0.0F;
try{
fcurrent = Float.parseFloat(current);
}catch(NumberFormatException e){
fcurrent = 0.01F;
}
Random rdm = new Random();
float tmp = fcurrent + rdm.nextFloat();
return String.valueOf(tmp);
}
}

6. 还有一个类是一个JavaBeanStockBean.java
package dwr.reverse;
public class StocksBean {
private String stock = "";
private String value = "";
public StocksBean(String stock, String value) {
this.setStock(stock);
this.setValue(value);
}
public String getStock() {
return stock;
}
public void setStock(String stock) {
this.stock = stock;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
作者:luqin1988 发表于2013-4-23 10:55:31 原文链接
阅读:105 评论:0 查看评论

相关 [dwr2 push 推送技术] 推荐:

基于dwr2.0的Push推送技术详细解析以及实例

- - CSDN博客Web前端推荐文章
DWR从2.0开始增加了push功能,也就是在异步传输的情况下可以从Web-Server端发送数据到. 我们知道,Web的访问机制天生是设计用来pull数据的,也就是只允许Browser端主动发起请求,server. 是被动的响应.不允许Server向Browser发出一个connection请求,也就是说没有为server向Browser.

Facebook 美学转变:从收购Push Pop Press开始

- Brant - 爱范儿 · Beats of Bits
一直以来,Facebook 都遵循着实用美学至上的设计原则,讲究在最简洁的设计中纳入所有必需的功能. 而之所以拥有如此的设计文化,和 Facebook 在初期以 CEO Mark Zuckerberg 为技术主导的团队不无关系. 简洁的蓝白配色在出现伊始的确让人眼前一亮,清新的学院风加上冷酷的极客气息让 Facebook 在短时间内聚拢了极高的人气.

移动环境下push 技术开发__初级篇

- - ITeye博客
其实说白了就是研究androidpn这个开源项目,只因我的本科毕业设计的题目就是“移动环境下push技术开发”,所以起这个作为本篇博文的题目. 既然是初级篇,那当然后面还有进阶篇以及高级篇了,后面等我有时间再写吧. 其实我本来是想等我的毕业设计答辩结束后,再总结,再分享的,可是最近群里很多人整个环境都不会配,所以我就先来个初级篇吧.

微信公众平台:移动推送(Push)平台

- - 天涯海阁|Web2.0Share
之前曾经写过一个文章《 移动互联网的未来:基于情境/兴趣的推送》,至今我也觉得这个在未来会是有着巨大想想空间的移动生活方式. 之前其实也有不少初创企业在Push这个领域努力,不过效果却都不好,所以其实本质而言,要构建Push这样的平台,需要吸引大量的内容、媒体、品牌来提供Push内容,而对于内容、媒体、品牌而言,最在意的是这个平台有没有用户,而微信可能已经到了可以去构建这样一个信息推送平台的阶段.

苹果信息推送服务(Apple Push Notification Service)使用总结

- - IT技术博客大学习
标签:   Push   信息推送. 苹果信息推送服务(Apple Push Notification Service),是由苹果官方提供的消息推送服务. 推送形式包括顶部消息条、声音以及badge number()有了APNS,应用程序可在任意状态接收到与程序有关的消息(包括运行状态not running,foreground以及background),由于在大多数情况下,iOS中最多只有一个应用能处于active状态,所以,APNS为应用的交互提供了极大的便利.

为什么iComet比nginx-push-stream-module更好?

- - idea's blog
有些项目需要使用”Web服务器推(comet)技术时, 便因为 Web Server 用的是 Nginx 便选择了 nginx-push-stream-module, 但是根据我们的使用经验, nginx-push-stream-module 非常坑, 只适合同时在线几千人的小网站使用. 下面对比 iComet 服务器和 nginx-push-stream-module:.

物联网核心协议,消息推送技术演进

- - 博客 - 伯乐在线
消息触达能力是物联网(internet ofthings, IOT)的重要支撑,而物联网很多技术都源于移动互联网. 本文阐述移动互联网消息推送技术在物联网中的应用和演进. 从开发的角度,无线接入是物联网设备端的核心技术,身份设备管理和消息推送技术是物联网云端的核心技术. 而从场景体验的角度,除了前者,还要包括手机的前端开发技术.

微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨

- 荷泽 - 博客园-草屋主人的blog
微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨.      [文章作者:孙立 链接:http://www.cnblogs.com/sunli/ 更新时间:2010-08-24].      sns系统,微博系统都应用到了feed(每条微博或者sns里的新鲜事等我们称作feed)系统,不管是twitter.com或者国内的新浪微博,人人网等,在各种技术社区,技术大会上都在分享自己的feed架构,也就是推拉模式(timyang上次也分享了新浪微薄的模式).

AWS延伸到移动开发环节,Amazon推出移动设备消息推送服务(Amazon SNS Mobile Push)

- - 36氪
Amazon今天 宣布推出移动设备消息推送服务 Amazon SNS Mobile Push. Amazon Simple Notification Service(SNS)是2010年 推出的消息发送服务,之前开发者"可用 SNS 通过 SMS 文本消息或电子邮件来通知收件人",现在这项服务开始支持iOS,Android和Kindle Fire等移动设备的消息推送了.