dwr推送技術深入研究


DWR 工作原理:

  是通過動態把 Java 類生成為 Javascript。它的代碼就像 Ajax 一樣,你感覺調用就像發生在瀏覽器端,但是實際上代碼調用發生在服務器端,DWR 負責數據的傳遞和轉換。這種從 Java 到JavaScript的遠程調用功能的方式使DWR用起來有種非常像RMI或者SOAP的常規RPC機制,而且DWR的優點在於不需要任何的網頁瀏覽器插件就能運行在網頁上。

  Java 從根本上講是同步機制,然而 AJAX 卻是異步的。所以你調用遠程方法時,當數據已經從網絡上返回的時候,你需要提供有反調 (callback) 功能的 DWR,即你的js代碼調用最后一個參數是一個回調函數,由回調函數處理數據返回后想做的操作。

Comet

Comet方式通俗的說就是一種長連接機制(long lived http)。同樣是由Browser端主動發起請求,但是Server端以一種似乎非常慢的響應方式給出回答。這樣在這個期間內,服務器端可以使用同一個connection把要更新的數據主動發送給Browser。因此請求可能等待較長的時間,期間沒有任何數據返回,但是一旦有了新的數據,它將立即被發送到客戶機。Comet又有很多種實現方式,但是總的來說對Server端的負載都會有增加.雖然對於單位操作來說,每次只需要建議一次connection,但是由於connection是保持較長時間的,對於 server端的資源的占用要有所增加。

優點: 實時性好(消息延時小);性能好(能支持大量用戶)

缺點: 長期占用連接,喪失了無狀態高並發的特點。

應用: 股票系統、實時通訊。


1.先配置web.xml

<!-- dwr start -->
<servlet>
<!-- dwr框架的核心控制器 -->
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<!-- 在服務器端啟用反向ajax -->
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>

<!-- 為了得到更詳細的調試信息 -->
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>

<init-param>
<param-name>crossDomainSessionSecurity</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>allowScriptTagRemoting</param-name>
<param-value>true</param-value>
</init-param>

<init-param>
<param-name>org.directwebremoting.extend.ScriptSessionManager </param-name>
<param-value>com.worklite.core.tools.dwr.DWRScriptSessionManager</param-value>
</init-param>
<!-- 在服務器啟動階段,該servlet實例被創建 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<!-- 發送如下的請求,都會交給dwr的核心控制器處理 -->
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<!-- dwr end -->

2.新建dwr.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd">

<dwr>

<allow>

<create creator="new" javascript="DwrPush">
<param name="class" value="com.worklite.core.tools.dwr.DwrPush"/>
</create>

<create creator="new" javascript="ClientInitUtil">
<param name="class" value="com.worklite.core.tools.dwr.ClientInitUtil"/>
</create>

<create creator="new" javascript="WebMultiplePushUtil">
<param name="class" value="com.worklite.core.tools.dwr.WebMultiplePushUtil"/>
</create>

<create creator="new" javascript="WebSinglePushUtil">
<param name="class" value="com.worklite.core.tools.dwr.WebSinglePushUtil"/>
</create>

<create creator="new" javascript="WebSingleGamePushUtil">
<param name="class" value="com.worklite.core.tools.dwr.WebSingleGamePushUtil"/>
</create>

</allow>

</dwr>

3.編寫后台需要的類。

(1)DWRScriptSessionListener

public class DWRScriptSessionListener implements ScriptSessionListener {

//維護一個Map key為session的Id, value為ScriptSession對象
public static final Map<String, ScriptSession> scriptSessionMap = new MirrorMap<String, ScriptSession>();

/**
* ScriptSession創建事件
*/
@Override
public void sessionCreated(ScriptSessionEvent event) {
WebContext webContext = WebContextFactory. get();
HttpSession session = webContext.getSession();
ScriptSession scriptSession = event.getSession();
scriptSessionMap.put(session.getId(), scriptSession); //添加scriptSession
}

/**
* ScriptSession銷毀事件
*/
@Override
public void sessionDestroyed(ScriptSessionEvent event) {
//WebContext webContext = WebContextFactory. get();
//HttpSession session = webContext.getSession();
//scriptSessionMap.remove(session.getId()); //移除scriptSession
}

/**
* 獲取所有ScriptSession
*/
public static Collection<ScriptSession> getScriptSessions(){
return scriptSessionMap.values();
}


public static ScriptSession getScriptSession(String str){
Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
//遍歷每一個ScriptSession
for (ScriptSession scriptSession : sessions){
String tag = (String)scriptSession.getAttribute(str);
if ( tag!=null&&str.equals(tag)) {
return scriptSession;
}

}
return null;

}

public static int Count(String wId){

Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
//遍歷每一個ScriptSession
int i=0;
for (ScriptSession scriptSession : sessions){
String tag = (String)scriptSession.getAttribute(wId);
if ( tag!=null&&wId.equals(tag)) {
i++;
}

}
return i;

}

public static boolean getCustomList(String wId,int customId){

Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
//遍歷每一個ScriptSession
for (ScriptSession scriptSession : sessions){
String tagId=customId+wId;
String tag = (String)scriptSession.getAttribute(tagId);

if(tag!=null&&tagId.equals(tag)){
return true;
}

}
return false;

}


public static List<String> getCustomList(String wId){
List<String> customList=new ArrayList<String>();
Collection<ScriptSession> sessions = DWRScriptSessionListener.getScriptSessions();
//遍歷每一個ScriptSession
for (ScriptSession scriptSession : sessions){
Iterator<String> iter = scriptSession.getAttributeNames();
while(iter.hasNext()){
String str=iter.next();
if(str!=null&&str.contains(String.valueOf(","+wId))){
String customId = str.split(",")[0];
if (!customList.contains(customId))
customList.add(customId);
}
}
}


return customList;

}

public void init() throws ServletException {

Container container = ServerContextFactory.get().getContainer();

ScriptSessionManager manager = container.getBean(ScriptSessionManager.class);

ScriptSessionListener listener = new ScriptSessionListener() {

public void sessionCreated(ScriptSessionEvent ev) {

WebContext webContext = WebContextFactory. get();
HttpSession session = webContext.getSession();
ScriptSession scriptSession = ev.getSession();
scriptSessionMap.put(session.getId(), scriptSession); //添加scriptSession
}

public void sessionDestroyed(ScriptSessionEvent ev) {

WebContext webContext = WebContextFactory. get();
HttpSession session = webContext.getSession();
ScriptSession scriptSession = scriptSessionMap.remove(session.getId()); //移除scriptSession
}

};

manager.addScriptSessionListener(listener);

}

}

(2)DWRScriptSessionManager

public class DWRScriptSessionManager extends DefaultScriptSessionManager {

public DWRScriptSessionManager(){
//綁定一個ScriptSession增加銷毀事件的監聽器
this.addScriptSessionListener( new DWRScriptSessionListener());
Log.debug( "bind DWRScriptSessionListener");
}
}

(3)DwrPush注冊scriptSession 

public class DwrPush {

public void onPageLoad(final String tag){
//獲取當前的ScriptSession
ScriptSession scriptSession = WebContextFactory.get().getScriptSession();
scriptSession.setAttribute( tag, tag);
}
}

(4)WebMultiplePushUtil 用於群發

public class WebMultiplePushUtil {

public void push(final String wId,final String content,final String command){

//過濾器
ScriptSessionFilter filter = new ScriptSessionFilter() {

public boolean match(ScriptSession scriptSession) {

String tag = (String)scriptSession.getAttribute(wId);
if ( tag== null) {
return false;
} else {
return wId.equals(tag);
}
}
};

Runnable run = new Runnable(){
private ScriptBuffer script = new ScriptBuffer();

public void run() {
//設置要調用的 js及參數
script.appendCall( "showMessage","{\"wId\":\""+wId+"\",\"content\":\""+content+"\",\"command\":\""+command+"\"}");
//得到所有ScriptSession
Collection<ScriptSession> sessions = Browser.getTargetSessions();
//遍歷每一個ScriptSession
for (ScriptSession scriptSession : sessions){
scriptSession.addScript( script);
}
}
};
//執行推送
Browser. withAllSessionsFiltered(filter, run); //注意這里調用了有filter功能的方法
}
}

(5)WebSingleGamePushUtil 用於單發游戲

public class WebSingleGamePushUtil {

public void push(final String customId,final String wId,final Webcast_game_push push){

Runnable run = new Runnable(){
private ScriptBuffer script = new ScriptBuffer();
public void run() {
//設置要調用的 js及參數
script.appendCall( "show",JSONObject.fromObject(push).toString());
ScriptSession scriptSession =DWRScriptSessionListener.getScriptSession(customId+","+wId);
if(null!=scriptSession){
scriptSession.addScript( script);
}

}
};

//執行推送
Browser.withAllSessions(run);
}
}

(6)WebSinglePushUtil 用於單發通知

public class WebSinglePushUtil {

public void push(final String customId,final String wId,final String content,final String command){
//過濾器
ScriptSessionFilter filter = new ScriptSessionFilter() {

public boolean match(ScriptSession scriptSession) {
String tagId=customId+","+wId;
String tag = (String)scriptSession.getAttribute(tagId);
if ( tag== null) {
return false;
} else {
return tagId.equals(tag);
}
}
};

Runnable run = new Runnable(){
private ScriptBuffer script = new ScriptBuffer();
public void run() {
//設置要調用的 js及參數
script.appendCall( "show","{\"customId\":\""+customId+"\",\"wId\":\""+wId+"\",\"content\":\""+content+"\",\"command\":\""+command+"\"}");
//得到所有ScriptSession
Collection<ScriptSession> sessions = Browser.getTargetSessions();
//遍歷每一個ScriptSession
for (ScriptSession scriptSession : sessions){
scriptSession.addScript( script);
}
}
};

//執行推送
Browser. withAllSessionsFiltered(filter, run); //注意這里調用了有filter功能的方法
}
}

 

4.在jsp頁面引入相應的js

<script type="text/javascript" src="/worklite/dwr/engine.js"></script>
<script type="text/javascript" src="/worklite/dwr/util.js"></script>
<script type="text/javascript" src="/worklite/dwr/interface/DwrPush.js"></script>

dwr.engine.setActiveReverseAjax(true);
dwr.engine.setAsync(true);

dwr.engine._errorHandler = function(message, ex) {dwr.engine._debug("Error: " + ex.name + ", " + ex.message, true);};

<body onload="dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);onPageLoad();">

在頁面上要先掉用下DwrPush.onPageLoad(),加入scriptSession

function onPageLoad(){
DwrPush.onPageLoad(wId);
DwrPush.onPageLoad(""+customId+","+wId);
}

然后在代碼中調用相應的push方法即可完成推送。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM