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的时候,加上下面的内容:
2 |
< servlet-name >dwr-invoker</ servlet-name >
|
3 |
< servlet-class >org.directwebremoting.servlet.DwrServlet</ servlet-class >
|
5 |
< param-name >activeReverseAjaxEnabled</ param-name >
|
6 |
< param-value >true</ param-value >
|
然后在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,需
要进行如下的配置:
2 |
< param-name >maxWaitAfterWrite</ param-name >
|
3 |
< param-value >-1</ param-value >
|
这里,设置maxWaitAfterWrite是-1,表示这个时间和Full Streaming Mode一样,设置关闭时间是60
秒.
Polling Mode
Polling Mode 是一种轮询方式,这可以避免长时间保持连接而产生的对服务器资源的占用.如果要是用
轮询方式,还需要做以下的配置:
2 |
< param-name >org.directwebremoting.extend.ServerLoadMonitor</ param-name >
|
3 |
< param-value >org.directwebremoting.impl.PollingServerLoadMonitor</ param-value >
|
2 |
< param-name >disconnectedTime</ param-name >
|
3 |
< param-value >60000</ param-value >
|
这是将轮询周期改为6000毫秒,也就是6秒
让Web具备了Push的方式,这对于很多应用是梦寐以求的,比如,如果有一个基于Web的网络聊天系统,
如果使用Push技术可以更加满足功能的需要,还有比如说一些需要server端根据数据条件主动向
browser端发送数据的应用需求,都非常需要这样的功能.
下面就举一个股票报盘的例子,能够让Server端通过主动的方式想Browser端发送股票信息.
先说一下所需jar包:dwr.jar commons-logging.jar
然后介绍如何配置:
1. 在web.xml中配置如下内容:
02 |
< servlet-name >dwr-invoker</ servlet-name >
|
03 |
< servlet-class >org.directwebremoting.servlet.DwrServlet</ servlet-class >
|
05 |
< param-name >activeReverseAjaxEnabled</ param-name >
|
06 |
< param-value >true</ param-value >
|
10 |
< servlet-name >dwr-invoker</ servlet-name >
|
11 |
< url-pattern >/dwr/*</ url-pattern >
|
2. 在dwr.xml中配置如下内容:
4 |
< create creator = "new" javascript = "StocksPusher" >
|
5 |
< param name = "class" value = "dwr.reverse.StocksPusher" />
|
3. 股票报盘的页面getStockInfo.html
01 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
02 |
"http://www.w3.org/TR/html4/loose.dtd"> |
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(); |
18 |
StocksPusher.closeShow(); |
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()" />
|
29 |
< table style = "width:500px" border = "0" cellpadding = "0" >
|
31 |
< td class = "headName" >< b >Stock Name</ b ></ td >
|
32 |
< td class = "headValue" >< b >Stock Value</ b ></ td >
|
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 >
|
4. 报盘的主程序StocksPusher.java ,关键部分在代码后面有中文注释
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;
|
14 |
public class StocksPusher {
|
15 |
private static boolean closeMarket = false ;
|
17 |
* Initialize the stocklist with values. |
19 |
public StocksPusher() {
|
22 |
* Send the Stock-Values to the file "getStockInfo.html" |
24 |
public void sendStocks() throws InterruptedException {
|
25 |
WebContext wctx = WebContextFactory.get();
|
26 |
String currentPage = wctx.getCurrentPage();
|
28 |
Collection sessions = wctx.getScriptSessionsByPage(currentPage);
|
30 |
Util utilAll = new Util(sessions);
|
34 |
if (closeMarket) break ;
|
35 |
StocksBean stock = StockPriceTracer.getNextStockInfo(); |
36 |
utilAll.setValue(stock.getStock(), stock.getValue());
|
37 |
dwr.util.js中的setValue()函数用法完全一样,第一个参数是页面Element的id ,第二个参数是对该id |
39 |
System.out.println( "Pushing stock: " + stock.getStock() + " = " +
|
43 |
public void beginShow(){
|
46 |
public void closeShow(){
|
5. 还有一个类是为了模拟实时获取股票信息的工具StockPriceTracer.java,也可能是访问数据库,
也可能来至卫星的大盘数据,等等,这个类是用随机的方法获得股票价格:
02 |
import java.util.ArrayList;
|
03 |
import java.util.List;
|
04 |
import java.util.Random;
|
05 |
import java.util.Stack;
|
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" ));
|
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())); |
41 |
private String getRandomPrice(String current){
|
42 |
float fcurrent = 0 .0F;
|
44 |
fcurrent = Float.parseFloat(current); |
45 |
} catch (NumberFormatException e){
|
48 |
Random rdm = new Random();
|
49 |
float tmp = fcurrent + rdm.nextFloat();
|
50 |
return String.valueOf(tmp);
|
6. 还有一个类是一个JavaBeanStockBean.java
02 |
public class StocksBean {
|
03 |
private String stock = "" ;
|
04 |
private String value = "" ;
|
05 |
public StocksBean(String stock, String value) {
|
09 |
public String getStock() {
|
12 |
public void setStock(String stock) {
|
15 |
public String getValue() {
|
18 |
public void setValue(String value) {
|
相关推荐
在"聊天DWR推送"实例中,我们可能会看到以下关键技术点: - **聊天室接口**:服务器端定义了一个或多个处理聊天消息的Java类,这些类提供了添加、获取和广播消息的方法。 - **JavaScript接口**:DWR自动生成了与...
在本项目"基于DWR框架的Web推送技术实现"中,我们将探讨如何利用DWR框架来构建一个实时的Web聊天程序。 首先,理解DWR框架的核心概念是至关重要的。DWR允许开发者在浏览器中直接调用服务器上的Java方法,就像它们是...
在`dwr.xml`中,你可以使用`<push>`标签来配置推送引擎,例如设置推送类型(如Ajax或者WebSocket)和超时时间。 接着,在服务器端编写Java类和方法,这些方法将用于生成和发送推送消息。你需要确保这些方法是DWR可...
### DWR 2.0 自动推送技术详细解析与实例 #### 一、背景与概述 随着互联网技术的发展,Web 应用越来越注重实时性与交互性,这推动了多种实时通信技术的发展。传统的Web应用架构是基于客户端(Browser)发起请求、...
3. **实时推送**:DWR的Push功能允许服务器主动将数据推送到客户端,而不是等待客户端发起请求。这通常通过建立持久连接(如HTTP长轮询或WebSocket)来实现。实例可能会包含创建推送通道、订阅事件和处理推送消息的...
DWR的推送功能基于`Push`接口,它可以监听服务器端的数据变化并实时推送到客户端。你可以创建一个`PushContext`,设置监听器,当服务器端的数据发生变化时,DWR会自动将更新推送给所有已连接的客户端。 **安全和...
3. **推送机制**:DWR提供了Push技术,可以实现在服务器端有新数据时立即推送到客户端,无需用户刷新页面。这通常涉及到`PushEngine`和`Channel`的概念。 4. **Session管理**:描述中提到"合理的使用sessionManage...
在这个"基于DWR消息推送技术"的实例中,你可能会看到如何配置DWR的`dwr.xml`文件以启用`Push`,如何在服务器端创建推送服务,以及如何在客户端编写JavaScript代码来接收和处理推送消息。通过实际运行这个实例,你...
DWR的`Push`功能使用长轮询(Long Polling)或HTML5的WebSocket等技术来实现实时推送。客户端页面则通过DWR JavaScript API接收这些推送的消息并更新用户界面。 2. `javascript-chat.html`:这个例子可能基于用户...
DWR的Push API允许服务器在数据变更时主动推送给客户端,提高了实时性。 3. **DWR配置**: 配置DWR涉及到创建`dwr.xml`配置文件,其中定义了允许的JavaScript调用、安全设置以及其他自定义选项。例如,你可以在...
DWR Push基于Comet技术,可以实现在服务器有新数据时主动推送给客户端。首先,你需要在服务器端创建一个Push服务,比如`NotificationPusher`类,里面有一个`broadcastMessage`方法用于广播消息。然后,在客户端,你...
总之,这个基于DWR的聊天系统实例展示了DWR在创建实时Web应用中的强大功能,包括反转Ajax、Push技术、数据流处理、加密和持久化等。通过学习这个项目,开发者可以进一步提升自己在构建高效、安全的Ajax应用方面的...
- **Push技术**:DWR3.0引入了Push技术,允许服务器主动向客户端推送数据,实现双向通信。 - **异步调用**:除了同步调用,DWR还支持异步调用,提高用户体验。 - **Batching**:将多个请求打包成一个批次发送,...
本篇将详细介绍如何利用Spring3和DWR3创建聊天功能,以及DWR的Server Push技术在其中的作用。 首先,Spring3是一个全面的Java企业级应用开发框架,提供了依赖注入、AOP(面向切面编程)、MVC(模型-视图-控制器)等...
7. **实战案例**:通过一个简单的服务器推送实例,如实时消息通知,来展示DWR的实际应用。 8. **错误处理与调试**:如何处理DWR调用中的错误,以及如何利用DWR的调试模式进行问题排查。 通过以上内容,你可以逐步...
6. **DWR的高级特性**:探索DWR的Batching和Polling功能,用于批量处理请求和实现定时轮询,以及如何利用DWR的Push技术实现实时推送。 7. **实例与实战**:通过实际的项目案例,学习如何将DWR应用到实际开发中,...
4. **Ajax Push**:DWR的双向通信特性,使得服务器可以主动推送更新到客户端,适用于实时性要求高的应用。 学习DWR时,你需要理解以下知识点: 1. **安装和配置**:如何在项目中引入DWR库,设置DWR的配置文件,以及...
- **Server Push**:让服务器主动向客户端推送数据。 - **Comet**:一种实现Server Push的技术,通过对HTTP连接的长期保持来实现服务器向客户端推送数据。 - **WebSocket**:提供了全双工的通信通道,可以实现...