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的時候,加上下面的內容: javascript
<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>
<init-param> <param-name>maxWaitAfterWrite</param-name> <param-value>-1</param-value> </init-param>
<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端發送股票信息. css
先說一下所需jar包:dwr.jar commons-logging.jar
而後介紹如何配置:
1. 在web.xml中配置以下內容: html
<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>
<dwr> <allow> <!-- Reverse Ajax Stock push Demo Config --> <create creator="new" javascript="StocksPusher"> <param name="class" value="dwr.reverse.StocksPusher"/> </create> </allow> </dwr>
<!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>
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; } }
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); } }
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; } }