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方法即可完成推送。

dwr推送技术深入研究的更多相关文章

  1. DWR推送技术

    “服务器推送技术”(ServerPushing)是最近Web技术中最热门的一个流行术语.它是继“Ajax”之后又一个倍受追捧的Web技术.“服务器推送技术”最近的流行跟“Ajax ”有着密切的关系. ...

  2. Web端服务器推送技术原理分析及dwr框架简单的使用

    1 背景 “服务器推送技术”(ServerPushing)是最近Web技术中最热门的一个流行术语.它是继“Ajax”之后又一个倍受追捧的Web技术.“服务器推送技术”最近的流行跟“Ajax ”有着密切 ...

  3. Web端server推送技术原理分析及dwr框架简单的使用

    1 背景 "server推送技术"(ServerPushing)是近期Web技术中最热门的一个流行术语.它是继"Ajax"之后又一个倍受追捧的Web技术.&qu ...

  4. Android推送技术研究

    前言 最近研究Android推送的实现, 研究了两天一夜, 有了一点收获, 写下来既为了分享, 也为了吐槽. 需要说明的是有些东西偏底层硬件和通信行业, 我对这些一窍不通, 只能说说自己的理解. 为什 ...

  5. 转:Android推送技术研究

    Android推送技术研究 字数5208 阅读4026 评论5 喜欢35 前言 最近研究Android推送的实现, 研究了两天一夜, 有了一点收获, 写下来既为了分享, 也为了吐槽. 需要说明的是有些 ...

  6. PHP ServerPush (推送) 技术的探讨

    2016年11月29日17:51:03 转自:http://www.cnblogs.com/hnrainll/archive/2013/05/07/3064874.html 需求: 我想做个会员站内通 ...

  7. PHP ServerPush (推送) 技术

    用来代替ajax的请求 转自:http://blog.163.com/bailin_li/blog/static/17449017920124811524364/ 需求: 我想做个会员站内通知的功能. ...

  8. PHP ServerPush (推送) 技术的探讨[整理]

    需求: 我想做个会员站内通知的功能.不想用以前的ajax查询,听说有个推技术.以下文章介绍的不错,来自转载, ============================================= ...

  9. PHP ServerPush (推送) 技术的探讨【转】

    随着人们对Web即时应用需求的不断上升,Server Push(推送)技术在聊天.消息提醒尤其是社交网络等方面开始兴起,成为实时应用的数据流核心.这篇日志试图探讨的便是各种适合于PHP的Push的实现 ...

随机推荐

  1. SQLSERVER 总结1

    数据:描述事物的符号记录 数据库:按照数据结构来组织和存储管理的数据仓库 数据库管理系统:位于用户与操作系统之间的一层数据管理软件 数据库系统:在计算机系统中引入数据库后的系统构成.由数据库,数据库管 ...

  2. Winform 程序嵌入WPF程序 并发送消息

    废话不多说,先看解决方案目录 WindowsFormsDemo是主程序,WpfApp是嵌入的WPF程序,先看WPF程序,程序默认启动的页面是MainWindow.xaml,这里注释掉App.xaml里 ...

  3. 用Python复习离散数学(二)

    这次复习的是计数问题,立刻走起吧! 1.乘法原理 如果一项工作需要t步完成的,第一步有n1种不同的选择,第二步有n2种不同的选择,……,第t步有nt中不同的选择,那么完成这项工作所有可能的选择种数为: ...

  4. Xcode开发和调试总结

    Xcode是iOS开发主要的工具.IDE.关于Xcode的细枝末节,可以参考苹果的官方文档或者众多的说明.此文档主要涉及常用开发和调试注意事项,参考版本为Xcode 5.1.1. 目标设置: 在此,我 ...

  5. [Usaco2008 Mar]Cow Travelling游荡的奶牛[简单DP]

    Description 奶牛们在被划分成N行M列(2 <= N <= 100; 2 <= M <= 100)的草地上游走,试图找到整块草地中最美味的牧草.Farmer John ...

  6. windows下Jdk和Tomcat的安装配置

    Jdk全称Java development Kit,Jdk是sun公司提供的免费开源的java语言开发工具包,现在最新版本是8.0,说道jdk的版本,有些人可能会有疑惑,怎么有说jdk1.6,jdk1 ...

  7. [转]iOS Tutorial – Dumping the Application Heap from Memory

     Source:https://blog.netspi.com/ios-tutorial-dumping-the-application-heap-from-memory/ An essential ...

  8. 企业架构研究总结(35)——TOGAF架构内容框架之构建块(Building Blocks)

    之前忙于搬家移居,无暇顾及博客,今天终于得闲继续我的“政治课”了,希望之后至少能够补完TOGAF方面的内容.从前面文章可以看出,笔者并无太多能力和机会对TOGAF进行理论和实际的联系,仅可对标准的文本 ...

  9. 记一次bug查找经历

    系统采用cell插件显示汇总数据,然后发现个公司数据显示不出来,接到这个任务开始查找bug. 通过需求了解并不知道其他公司什么情况,因为就这个公司有了反馈: 本来以为很容易找到点的,毕竟数据显示不出来 ...

  10. ajaxFileUpload+struts2实现多文件上传(动态添加文件上传框)

    上篇文章http://blog.csdn.net/itmyhome1990/article/details/36396291介绍了ajaxfileupload实现多文件上传, 但只是固定的文件个数,如 ...