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方法即可完成推送。
dwr推送技术深入研究的更多相关文章
- DWR推送技术
		“服务器推送技术”(ServerPushing)是最近Web技术中最热门的一个流行术语.它是继“Ajax”之后又一个倍受追捧的Web技术.“服务器推送技术”最近的流行跟“Ajax ”有着密切的关系. ... 
- Web端服务器推送技术原理分析及dwr框架简单的使用
		1 背景 “服务器推送技术”(ServerPushing)是最近Web技术中最热门的一个流行术语.它是继“Ajax”之后又一个倍受追捧的Web技术.“服务器推送技术”最近的流行跟“Ajax ”有着密切 ... 
- Web端server推送技术原理分析及dwr框架简单的使用
		1 背景 "server推送技术"(ServerPushing)是近期Web技术中最热门的一个流行术语.它是继"Ajax"之后又一个倍受追捧的Web技术.&qu ... 
- Android推送技术研究
		前言 最近研究Android推送的实现, 研究了两天一夜, 有了一点收获, 写下来既为了分享, 也为了吐槽. 需要说明的是有些东西偏底层硬件和通信行业, 我对这些一窍不通, 只能说说自己的理解. 为什 ... 
- 转:Android推送技术研究
		Android推送技术研究 字数5208 阅读4026 评论5 喜欢35 前言 最近研究Android推送的实现, 研究了两天一夜, 有了一点收获, 写下来既为了分享, 也为了吐槽. 需要说明的是有些 ... 
- PHP ServerPush (推送) 技术的探讨
		2016年11月29日17:51:03 转自:http://www.cnblogs.com/hnrainll/archive/2013/05/07/3064874.html 需求: 我想做个会员站内通 ... 
- PHP ServerPush (推送) 技术
		用来代替ajax的请求 转自:http://blog.163.com/bailin_li/blog/static/17449017920124811524364/ 需求: 我想做个会员站内通知的功能. ... 
- PHP ServerPush (推送) 技术的探讨[整理]
		需求: 我想做个会员站内通知的功能.不想用以前的ajax查询,听说有个推技术.以下文章介绍的不错,来自转载, ============================================= ... 
- PHP ServerPush (推送) 技术的探讨【转】
		随着人们对Web即时应用需求的不断上升,Server Push(推送)技术在聊天.消息提醒尤其是社交网络等方面开始兴起,成为实时应用的数据流核心.这篇日志试图探讨的便是各种适合于PHP的Push的实现 ... 
随机推荐
- 表达式树解析"框架"
			干货!表达式树解析"框架"(2) 为了过个好年,我还是赶快把这篇完成了吧 声明 本文内容需要有一定基础的开发人员才可轻松阅读,如果有难以理解的地方可以跟帖询问,但我也不一定能回 ... 
- Hadoop作业提交之TaskTracker获取Task
			[Hadoop代码笔记]Hadoop作业提交之TaskTracker获取Task 一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobC ... 
- Mac OS X安装之硬盘和光盘引导总结
			继上一篇虚拟机环境下的安装,这篇文档主要描述硬盘和光盘引导安装Mac OS X,并可实现多操作系统. 硬盘安装: 首先介绍下硬盘安装需要用到的软件. Java虚拟机.作为HFSExplorer的运行前 ... 
- Day1:T3 bfs T4 树形DP
			T3:BFS 回看了一下Day1的T3...感觉裸裸的BFS,自己当时居然没有看出来... 同时用上升和下降两种状态bfs即可 这一题还要注意一个细节的地方,就是题目要求的是求往返的最优解 k=min ... 
- mac 下安装oh my zsh
			1.直接从github上下载 git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh 2.拷贝到账户目录下 cp ~/. ... 
- Mysql--选择适合的引擎,提高操作速度
			在MySQL 5.1中,MySQL AB引入了新的插件式存储引擎体系结构,允许将存储引擎加载到正在运新的MySQL服务器中 一.数据引擎简介 在MySQL 5.1中,MySQL AB引入了新的插件 ... 
- 构建一个真实的应用电子商务SportsStore(十)
			构建一个真实的应用电子商务SportsStore(十) 我们现在还需要为管理员提供一个途径,使他能方便的管理网站的商品目录,这也是所有网站都需要的功能,常用到了几乎所有开发人员都要开发这种功能的地步, ... 
- Web API 的安全性
			Web API 的安全性 ASP.NET Web API 可非常方便地创建基于 HTTP 的 Services,这些服务可以非常方便地被几乎任何形式的平台和客户端(如浏览器.Windows客户端.An ... 
- js 调用父窗口的方法
			opener.show(); 父窗体需要顶一个show() 方法 父面页代码: <!DOCTYPE HTML PUBLIC "-//IETF//DTD LEVEL1//EN" ... 
- Html中DIV成为超级链接,解决在360浏览器+IE9显示小手图标的兼容性!
			Html中DIV成为超级链接,解决在360浏览器+IE9显示小手图标的兼容性! <div style="cursor:pointer;" onclick="sele ... 
