基于dwr2.0的Push推送技术详细解析以及实例
来源:互联网 发布:fanuc 电池 数据全清 编辑:程序博客网 时间:2024/05/19 12:17
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的时候,加上下面的内容:
然后在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,需
要进行如下的配置:
这里,设置maxWaitAfterWrite是-1,表示这个时间和Full Streaming Mode一样,设置关闭时间是60
秒.
Polling Mode
Polling Mode 是一种轮询方式,这可以避免长时间保持连接而产生的对服务器资源的占用.如果要是用
轮询方式,还需要做以下的配置:
这是将轮询周期改为6000毫秒,也就是6秒
2. 在dwr.xml中配置如下内容:
3. 股票报盘的页面getStockInfo.html
4. 报盘的主程序StocksPusher.java ,关键部分在代码后面有中文注释
5. 还有一个类是为了模拟实时获取股票信息的工具StockPriceTracer.java,也可能是访问数据库,
也可能来至卫星的大盘数据,等等,这个类是用随机的方法获得股票价格:
6. 还有一个类是一个JavaBeanStockBean.java
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的时候,加上下面的内容:
1
<
servlet
>
2
<
servlet-name
>dwr-invoker</
servlet-name
>
3
<
servlet-class
>org.directwebremoting.servlet.DwrServlet</
servlet-class
>
4
<
init-param
>
5
<
param-name
>activeReverseAjaxEnabled</
param-name
>
6
<
param-value
>true</
param-value
>
7
</
init-param
>
8
</
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,需
要进行如下的配置:
1
<
init-param
>
2
<
param-name
>maxWaitAfterWrite</
param-name
>
3
<
param-value
>-1</
param-value
>
4
</
init-param
>
这里,设置maxWaitAfterWrite是-1,表示这个时间和Full Streaming Mode一样,设置关闭时间是60
秒.
Polling Mode
Polling Mode 是一种轮询方式,这可以避免长时间保持连接而产生的对服务器资源的占用.如果要是用
轮询方式,还需要做以下的配置:
1
<
init-param
>
2
<
param-name
>org.directwebremoting.extend.ServerLoadMonitor</
param-name
>
3
<
param-value
>org.directwebremoting.impl.PollingServerLoadMonitor</
param-value
>
4
</
init-param
>
1
<
init-param
>
2
<
param-name
>disconnectedTime</
param-name
>
3
<
param-value
>60000</
param-value
>
4
</
init-param
>
让Web具备了Push的方式,这对于很多应用是梦寐以求的,比如,如果有一个基于Web的网络聊天系统,
如果使用Push技术可以更加满足功能的需要,还有比如说一些需要server端根据数据条件主动向
browser端发送数据的应用需求,都非常需要这样的功能.
下面就举一个股票报盘的例子,能够让Server端通过主动的方式想Browser端发送股票信息.
先说一下所需jar包:dwr.jarcommons-logging.jar
然后介绍如何配置:
1. 在web.xml中配置如下内容:
01
<
servlet
>
02
<
servlet-name
>dwr-invoker</
servlet-name
>
03
<
servlet-class
>org.directwebremoting.servlet.DwrServlet</
servlet-class
>
04
<
init-param
>
05
<
param-name
>activeReverseAjaxEnabled</
param-name
>
06
<
param-value
>true</
param-value
>
07
</
init-param
>
08
</
servlet
>
09
<
servlet-mapping
>
10
<
servlet-name
>dwr-invoker</
servlet-name
>
11
<
url-pattern
>/dwr/*</
url-pattern
>
12
</
servlet-mapping
>
2. 在dwr.xml中配置如下内容:
1
<
dwr
>
2
<
allow
>
3
<!-- Reverse Ajax Stock push Demo Config -->
4
<
create
creator
=
"new"
javascript
=
"StocksPusher"
>
5
<
param
name
=
"class"
value
=
"dwr.reverse.StocksPusher"
/>
6
</
create
>
7
</
allow
>
8
</
dwr
>
3. 股票报盘的页面getStockInfo.html
01
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
02
"http://www.w3.org/TR/html4/loose.dtd">
03
<
html
>
04
<
head
>
05
<
meta
http-equiv
=
"Content-Type"
content
=
"text/html; charset=UTF-8"
/>
06
<
title
>DWR Reverse Ajax Demo : Show Stock info</
title
>
07
<
link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"generic.css"
/>
08
<
script
type
=
'text/javascript'
src
=
'/AjaxShow/dwr/engine.js'
></
script
>
09
<
script
type
=
'text/javascript'
src
=
'/AjaxShow/dwr/util.js'
></
script
>
10
<
script
type
=
'text/javascript'
src='/AjaxShow/dwr/interface/
11
StocksPusher.js'></
script
>
12
<
script
type
=
"text/javascript"
>
13
function beginShow() {
14
StocksPusher.beginShow();
15
StocksPusher.sendStocks();
16
}
17
function endShow(){
18
StocksPusher.closeShow();
19
}
20
</
script
>
21
</
head
>
22
<
body
onload
=
"dwr.engine.setActiveReverseAjax(true);"
>
23
<
h3
>使用DWR Reverse Ajax进行股票报盘</
h3
>
24
<
p
>下面显示的股票信息是可以动态变化的</
p
>
25
<
input
type
=
"button"
value
=
"开市..."
onclick
=
"beginShow()"
/>
26
=========================
27
<
input
type
=
"button"
value
=
"闭市..."
onclick
=
"endShow()"
/>
28
<
hr
>
29
<
table
style
=
"width:500px"
border
=
"0"
cellpadding
=
"0"
>
30
<
tr
>
31
<
td
class
=
"headName"
><
b
>Stock Name</
b
></
td
>
32
<
td
class
=
"headValue"
><
b
>Stock Value</
b
></
td
>
33
</
tr
>
34
<
tr
><
td
>中移动</
td
><
td
><
div
id
=
"zyd"
>wait...</
div
></
td
></
tr
>
35
<
tr
><
td
>中石化</
td
><
td
><
div
id
=
"zsh"
>wait...</
div
></
td
></
tr
>
36
<
tr
><
td
>中石油</
td
><
td
><
div
id
=
"zsy"
>wait...</
div
></
td
></
tr
>
37
<
tr
><
td
>海尔电器</
td
><
td
><
div
id
=
"hedq"
>wait...</
div
></
td
></
tr
>
38
<
tr
><
td
>冀东水泥</
td
><
td
><
div
id
=
"jdsn"
>wait...</
div
></
td
></
tr
>
39
<
tr
><
td
>用友软件</
td
><
td
><
div
id
=
"yyrj"
>wait...</
div
></
td
></
tr
>
40
<
tr
><
td
>柳钢股份</
td
><
td
><
div
id
=
"lggf"
>wait...</
div
></
td
></
tr
>
41
<
tr
><
td
>招商银行</
td
><
td
><
div
id
=
"zsyh"
>wait...</
div
></
td
></
tr
>
42
<
tr
><
td
>中国铁建</
td
><
td
><
div
id
=
"zgtj"
>wait...</
div
></
td
></
tr
>
43
<
tr
><
td
>深发展</
td
><
td
><
div
id
=
"sfz"
>wait...</
div
></
td
></
tr
>
44
<
tr
><
td
>金山软件</
td
><
td
><
div
id
=
"jsrj"
>wait...</
div
></
td
></
tr
>
45
<
tr
><
td
>大连实德</
td
><
td
><
div
id
=
"dlsd"
>wait...</
div
></
td
></
tr
>
46
<
tr
><
td
>九寨沟</
td
><
td
><
div
id
=
"jzg"
>wait...</
div
></
td
></
tr
>
47
<
tr
><
td
>中国平安</
td
><
td
><
div
id
=
"zgpa"
>wait...</
div
></
td
></
tr
>
48
<
tr
><
td
>工商银行</
td
><
td
><
div
id
=
"gsyh"
>wait...</
div
></
td
></
tr
>
49
<
tr
><
td
>鞍钢股份</
td
><
td
><
div
id
=
"aggf"
>wait...</
div
></
td
></
tr
>
50
<
tr
><
td
>中国航天</
td
><
td
><
div
id
=
"zght"
>wait...</
div
></
td
></
tr
>
51
</
table
>
52
<
br
>
53
</
body
>
54
</
html
>
4. 报盘的主程序StocksPusher.java ,关键部分在代码后面有中文注释
01
package
dwr.reverse;
02
import
java.util.ArrayList;
03
import
java.util.Collection;
04
import
java.util.List;
05
import
org.directwebremoting.WebContext;
06
import
org.directwebremoting.WebContextFactory;
07
import
org.directwebremoting.proxy.dwr.Util;
08
import
org.directwebremoting.util.Logger;
09
/**
10
* Reverse Ajax class.
11
*
12
* @author Henry Huang
13
*/
14
public
class
StocksPusher {
15
private
static
boolean
closeMarket =
false
;
16
/**
17
* Initialize the stocklist with values.
18
*/
19
public
StocksPusher() {
20
}
21
/**
22
* Send the Stock-Values to the file "getStockInfo.html"
23
*/
24
public
void
sendStocks()
throws
InterruptedException {
25
WebContext wctx = WebContextFactory.get();
//这里是获取WebContext上下文
26
String currentPage = wctx.getCurrentPage();
//从上下文中获取当前页面,这些是DWR
27
Reverse Ajax 要求的必须方式
28
Collection sessions = wctx.getScriptSessionsByPage(currentPage);
//再一个page中
29
可能存在多个ScriptSessions,
30
Util utilAll =
new
Util(sessions);
//Util 是DWR 在Server端模拟Brower端 dwr.util.js
31
的类, Engine也是
32
while
(
true
){
33
Thread.sleep(
500
);
34
if
(closeMarket)
break
;
35
StocksBean stock = StockPriceTracer.getNextStockInfo();
36
utilAll.setValue(stock.getStock(), stock.getValue());
//这里的setValue()用法和
37
dwr.util.js中的setValue()函数用法完全一样,第一个参数是页面Element的id ,第二个参数是对该id
38
赋的新值
39
System.out.println(
"Pushing stock: "
+ stock.getStock() +
" = "
+
40
stock.getValue());
41
}
42
}
43
public
void
beginShow(){
44
closeMarket =
false
;
45
}
46
public
void
closeShow(){
47
closeMarket =
true
;
48
}
49
}
5. 还有一个类是为了模拟实时获取股票信息的工具StockPriceTracer.java,也可能是访问数据库,
也可能来至卫星的大盘数据,等等,这个类是用随机的方法获得股票价格:
01
package
dwr.reverse;
02
import
java.util.ArrayList;
03
import
java.util.List;
04
import
java.util.Random;
05
import
java.util.Stack;
06
/**
07
* Reverse Ajax class.
08
*
09
* @author Henry Huang
10
*/
11
public
class
StockPriceTracer {
12
private
static
StockPriceTracer tracer =
null
;
13
private
List<StocksBean> stocks =
new
ArrayList<StocksBean>();
14
private
Stack<StocksBean> cycleStack =
new
Stack<StocksBean>();
15
private
StockPriceTracer(){
16
stocks.add(
new
StocksBean(
"zsy"
,
"36.55"
));
17
stocks.add(
new
StocksBean(
"dlsd"
,
"91.01"
));
18
stocks.add(
new
StocksBean(
"zsh"
,
"22.59"
));
19
stocks.add(
new
StocksBean(
"lggf"
,
"5.07"
));
20
stocks.add(
new
StocksBean(
"hedq"
,
"71.77"
));
21
stocks.add(
new
StocksBean(
"jdsn"
,
"31.61"
));
22
stocks.add(
new
StocksBean(
"yyrj"
,
"51.29"
));
23
stocks.add(
new
StocksBean(
"zsyh"
,
"52.70"
));
24
stocks.add(
new
StocksBean(
"zgtj"
,
"16.96"
));
25
stocks.add(
new
StocksBean(
"sfz"
,
"54.34"
));
26
stocks.add(
new
StocksBean(
"jsrj"
,
"178.48"
));
27
stocks.add(
new
StocksBean(
"zyd"
,
"134.48"
));
28
stocks.add(
new
StocksBean(
"jzg"
,
"76.32"
));
29
stocks.add(
new
StocksBean(
"zgpa"
,
"80.63"
));
30
stocks.add(
new
StocksBean(
"gsyh"
,
"18.79"
));
31
stocks.add(
new
StocksBean(
"aggf"
,
"20.19"
));
32
stocks.add(
new
StocksBean(
"zght"
,
"11.13"
));
33
}
34
public
static
StocksBean getNextStockInfo(){
35
if
(
null
== tracer) tracer =
new
StockPriceTracer();
36
if
(tracer.cycleStack.empty()) tracer.cycleStack.addAll(tracer.stocks);
37
StocksBean tmp = tracer.cycleStack.pop();
38
tmp.setValue(tracer.getRandomPrice(tmp.getValue()));
39
return
tmp;
40
}
41
private
String getRandomPrice(String current){
42
float
fcurrent =
0
.0F;
43
try
{
44
fcurrent = Float.parseFloat(current);
45
}
catch
(NumberFormatException e){
46
fcurrent =
0
.01F;
47
}
48
Random rdm =
new
Random();
49
float
tmp = fcurrent + rdm.nextFloat();
50
return
String.valueOf(tmp);
51
}
52
}
6. 还有一个类是一个JavaBeanStockBean.java
01
package
dwr.reverse;
02
public
class
StocksBean {
03
private
String stock =
""
;
04
private
String value =
""
;
05
public
StocksBean(String stock, String value) {
06
this
.setStock(stock);
07
this
.setValue(value);
08
}
09
public
String getStock() {
10
return
stock;
11
}
12
public
void
setStock(String stock) {
13
this
.stock = stock;
14
}
15
public
String getValue() {
16
return
value;
17
}
18
public
void
setValue(String value) {
19
this
.value = value;
20
}
21
}
- 基于dwr2.0的Push推送技术详细解析以及实例
- 基于dwr2.0的Push推送技术详细解析以及实例
- 基于dwr2.0的Push推送技术详细解析以及实例
- 基于dwr2.0的Push推送技术详细解析以及实例
- 基于dwr2.0的Push推送技术详解以及实例
- 【AJAX】AJAX技术详细解析以及实例
- 【AJAX】AJAX技术详细解析以及实例
- PHP中Push(推送)技术的探讨
- DWR2.x的推技术
- 推送技术server push
- 消息推送技术Push
- PUSH推送原理解析
- 基于PHP Socket配置以及实例的详细介绍
- Comet基于iframe的服务器推送(Server Push)例子
- 实现一个简单的服务端推送方案-实例篇Push
- 实现一个简单的服务端推送方案-实例篇Push
- ios消息推送全面解析和push证书的生成
- ios消息推送全面解析和push证书的生成
- php生成二维码的类及方法
- 面向对象 特点
- .Net网站资源全集合
- .net session、cookie、application 小结
- ubuntu 下搭建arm-linux-gcc 命令未找到问题
- 基于dwr2.0的Push推送技术详细解析以及实例
- android 转 比较好的widget讲解
- Objective-C 初窥之字典(Dic)
- c#冒泡排序
- core dump解析(4)
- 在MacOS和iOS上使用VPN的几个问题(MTU太大导致打不开网页)
- [转载]Java基础 之软引用、弱引用、虚引用 ·
- build open office
- 工厂模式