Posted on 2009-11-19 18:28
瘋狂 閱讀(4050)
評論(0) 編輯 收藏 所屬分類:
java 、
dwr
效果:服務器端發出消息,各個客戶端及時接受消息。
1,要使用dwr的ajaxReverse 技術首先要在web.xml里給dwr的servlet加上下列參數配置:
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
2,服務器端代碼:
public class MyReverse {
public void sendMes(String mes){
send("系統消息:"+mes);
}
public void send(final String output) {
String page = ServerContextFactory.get().getContextPath() + "/client.jsp";
Browser.withPage(page, new Runnable() {
public void run() {
Util.setValue("news", output); //news 客戶端jsp里面textarea的id
}
});
}
}
3.dwr配置:
<create javascript="myrevsrse" creator="new">
<param name="class" value="com.dwr.MyReverse"/>
</create>
3.服務端 (server.jsp用于發消息也就是管理員界面)
<html>
<script type="text/javascript" src="dwr/engine.js"></script>
<script type="text/javascript" src="dwr/util.js"></script>
<script type="text/javascript" src="dwr/interface/myrevsrse.js"></script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<script type="text/javascript">
function sendnews(){
var new_content = ${'newcontent'}.value;
myrevsrse.sendMes(new_content);
}
</script>
</head>
<body>
<input type="text" name="newcontent">
<input type = "button" value="發消息" onclick="sendnews()"/>
</body>
客戶端:
<html>
<script type="text/javascript" src="dwr/engine.js"></script>
<script type="text/javascript" src="dwr/util.js"></script>
<head>
<<script type="text/javascript">
</script>
</head>
<body onload="dwr.engine.setActiveReverseAjax(true);">
<textarea rows="20" cols="20" id="news"></textarea>
</body>
</html>
測試:
我們打開一個服務端,2和客戶端, 
服務端發出消息,點擊發消息后,個客戶端將同步顯示服務端發出的消息。

通過源代碼看看情況:(個人見解,希望大家指導和討論):
首先看看client端onload中執行的dwr方法:onload="dwr.engine.setActiveReverseAjax(true); 此方法鑒于源代碼:
org.directwebremoting.ui.dwr.Engine,方法內容:

/** *//**
* Does DWR poll the server for updates? (Default: false)
* @param activeReverseAjax True/False to turn RA on/off
* @see <a href="http://getahead.org/dwr/browser/engine/options">Options documentation</a>
*/
public static void setActiveReverseAjax(boolean activeReverseAjax)

{
ScriptBuffer script = new ScriptBuffer();
script.appendScript("dwr.engine.setActiveReverseAjax(")
.appendData(activeReverseAjax)
.appendScript(");");
ScriptSessions.addScript(script);
}
接著會調用:
Collection<ScriptSession> sessions = Browser.getTargetSessions();
for (ScriptSession scriptSession : sessions)

{
scriptSession.addScript(script);
}
其中Browser.getTargetSessions();是這樣說的:

/** *//**
* This method discovers the sessions that are currently being targeted
* by browser updates.
* <p>
* It will generally only be useful to authors of reverse ajax UI proxy
* APIs. Using it directly may cause scaling problems
* @return The list of current browser windows.
*/
public static Collection<ScriptSession> getTargetSessions()

{
TaskDispatcher taskDispatcher = TaskDispatcherFactory.get();
Collection<ScriptSession> sessions = taskDispatcher.getTargetSessions();
if (sessions != null)

{
return sessions;
}

WebContext webContext = WebContextFactory.get();
if (webContext != null)

{
sessions = new ArrayList<ScriptSession>();
sessions.add(webContext.getScriptSession());
return sessions;
}

throw new IllegalStateException("No current UI to manipulate. See org.directwebremoting.Browser to set one.");
}
這個方法只對reverse代理有用,直接使用它可能會有問題,
這里將看到WebContent 這個是關鍵:這里記錄了client端連接的信息,而最重要的當然是session和response,最終服務端信息是同過response的PrintWriter來輸出到客戶端,而實際上dwrServlet在處理requst的時候調用了這個類,調用內容看下代碼:
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException

{
try

{
webContextBuilder.engageThread(container, request, response);

UrlProcessor processor = container.getBean(UrlProcessor.class);
processor.handle(request, response);
}
finally

{
webContextBuilder.disengageThread();
}
}
其中的ebContextBuilder.engageThread(container, request, response);正式調用了這個類:
public void engageThread(Container container, HttpServletRequest request, HttpServletResponse response)

{
try

{
ServletConfig servletConfig = container.getBean(ServletConfig.class);
ServletContext servletContext = container.getBean(ServletContext.class);

WebContext ec = new DefaultWebContext(container, request, response, servletConfig, servletContext);
user.set(ec);
}
catch (Exception ex)

{
log.fatal("Failed to create an ExecutionContext", ex);
}
}
通過webcontext將我們的請求信息維持在服務端,
具體下面的過程的大意就是 通過過濾所有scriptsession 是否含有dwr.engine.setActiveReverseAjax(true); 信息 并通過response發出服務端信息。
時間關系歡迎大家繼續討論!