`

webqq更新——采用反向AJAX实现在线人员上下线模拟

阅读更多
原文:http://www.abigdreamer.com/mywork/webqq-update-online-reverse-ajax-implementation-off-the-assembly-line-simulation.html
本blog已转移到造梦师http://www.abigdreamer.com,欢迎大家常去我的blog看看!

说明:本次更新只是模拟了一下人员的上下线,并没有采用真是的数据(我一台电脑开那么多浏览器测试的话有点受不了,谁叫电脑烂呢,呵呵) 。另外需要注意的就是,需要用这个新的dwr.jar覆盖掉原来的那个dwr.jar,要不会出问题的!

有朋友问我怎样用反向AJAX来实现在线人员列表的更新,提到DWR允许javascript访问服务器端的Java方法,这使得AJAX使用起来会比较容易,而在DWR2.0里面添加了一个非常强大的功能——反向AJAX,也就是说,服务器端的Java方法可以取得浏览器端的Web上下文,并可以调用javascript的方法,将服务器端的数据异步地传输给浏览器。本文将通过一个demo展示这种特性。这个demo实现了类似股票交易系统中实时更新数据的功能,事实上是通过发布-订阅模式去实现的。也就是说,客户端订阅一个主题,服务器端通过一个线程向订阅这个主题的浏览器定时、异步地发送数据,从而实现了这种实时更新的功能。
    我们知道,客户端浏览器可以随时连接到web服务器,并向服务器请求资源,而服务器却没有这种能力,它不能主动地于客户端浏览器建立连接,并主动地将数据发送给浏览器。DWR支持3种从服务器端发送数据给客户端的方式:
1、轮询。客户端在每个时间周期内向服务器发送请求,看看服务器端有没有数据更新,如果有,就向服务器请求数据。
2、Comet:基于HTTP长连接的服务器推动方式。客户端向服务器发送请求后,服务器将数据通过response发送给客户端,但并不会将此response关闭,而是一直通过response将最新的数据发送给客户端浏览器,直到客户端浏览器关闭。
3、PiggyBack(回传)。服务器端将最新的数据排成队列,然后等待客户端下一次请求,接收到请求后就将等待更新的数据发给客户端。
这3种方式各有优劣,而DWR可以同时支持轮询和Comet。
首先,我们要让DWR程序支持反向AJAX。只需要在web.xml中添加如下配置:
<servlet>
        <servlet-name>dwr-invoker</servlet-name>
        <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>activeReverseAjaxEnabled</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>initApplicationScopeCreatorsAtStartup</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>maxWaitAfterWrite</param-name>
            <param-value>100</param-value>
        </init-param> 
        <load-on-startup>1</load-on-startup>
    </servlet>    
    <servlet-mapping>
        <servlet-name>dwr-invoker</servlet-name>
        <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

将初始化参数activeReverseAjaxEnabled设置为true表示启动反向AJAX。另外,添加这个功能的核心之处在于服务器端的发布者——Publisher.java,在这个类里面,首先通过org.directwebremoting.WebContext来获得访问这个应用的Web上下文:
WebContext webContext = WebContextFactory.get();
ServletContext servletContext = webContext.getServletContext();
serverContext = ServerContextFactory.get(servletContext);
webContext.getScriptSessionsByPage("");


这里主要通过WebContext类获得DWR应用的WEB上下文,用ServletContext获得DWRServlet的上下文,以及通过WEB上下文获取访问本应用的客户端浏览器的ScriptSession。通过ScriptSession,可以在服务器端向客户端浏览器发出执行js方法的指令,并把服务器端数据传送给js方法,具体的用法如下:

Collection sessions = serverContext
						.getScriptSessionsByPage("/webQQ/webQQ.jsp");
				ScriptProxy proxy = new ScriptProxy(sessions);

				WebQQUser user = users.getNextUserStatu();
				proxy.addFunctionCall("publishUserStatus", user);


这段代码首先通过getScriptSessionsByPage方法获得所有访问/webQQ/webQQ.jsp这个资源的客户端浏览器的ScriptSession,并为这些session建立代理(ScriptProxy),通过这个代理,让客户端执行publishUserStatus的js方法。其中addFunctionCall就是向客户端发送执行js方法的服务器端方法,第一个参数是js方法的签名,后面的都是js方法的参数。user是要发布的即时数据。user这个对象是随机生成的(见org.darkness.test.webqq. WebQQUsers类),Publish.java这个类启动了一个线程(worker),这个线程不断地生成user的数据,并发布给客户端。
以下是html页面的核心部分的代码:

var listeners = [];

function subscribeUserStatus(callBackHandler){
	listeners.push(callBackHandler);
}

function publishUserStatus(user){
	for(var i=0;i<listeners.length;i++){
		listeners[i].fun.call(listeners[i].scope,user);
	}
}

subscribeUserStatus({
	fun:function(user){
		try{
			var rootChildNodes = Ext.getCmp('im-tree').root.childNodes;
			for(var i=0;i<rootChildNodes.length;i++){
				var childNodes = rootChildNodes[i].childNodes;
				for(var j=0;j<childNodes.length;j++){
					if(childNodes[j].id == user.account){
						if(user.isShowOnline == 0){
							childNodes[j].getUI().getIconEl().src = 'images/user_delete.gif';
							
							var tempChild = childNodes[j];
							// appendChild就会将其放置到最尾端,不需要再remove了
							//rootChildNodes[i].removeChild(tempChild);
							rootChildNodes[i].appendChild(tempChild);
						}else{
							childNodes[j].getUI().getIconEl().src = 'images/user.gif';
							
							// 将刚上线的人员移动到最顶端
							var firstChild = rootChildNodes[i].firstChild;
							var tempChild = childNodes[j];
							rootChildNodes[i].insertBefore(tempChild, firstChild);
						}
						
						// 本来想用TreeNode自带的排序方法的,可试过了,总是没反应
						//rootChildNodes[i].sort(function(nodeA, nodeB){
						//	return nodeA.getUI().getIconEl().src > nodeB.getUI().getIconEl().src;
						//}, rootChildNodes[i]);
						return;
					}
				}
			}
			
		}catch(e){
		}
	},
	scope:this
});
dwr.engine.setActiveReverseAjax(true);

这一块代码主要是将改变在线或下线的用户的图标。
subscribeUserStatus方法订阅在线人员列表的数据(这些数据由服务器端的Java方法进行发布)。其中通过一个匿名回调函数,将取得改变的数据在页面显示出来(即人员的上、下线)。该回调方法非常简单,只是将TreeNode组件中的图标改变了一下,实现了实时提醒用户上下线的功能。
另外,服务器端还有一个监听器PublisherServletContextListener,这是为了在适当的时候关闭发布者的线程。这个监听器要结合其他两个DWR的监听器使用,只需在web.xml里面声明就行了:
<listener>
     <listener-class>org.directwebremoting.servlet.EfficientShutdownServletContextAttributeListener</listener-class>
</listener>
<listener>
        <listener-class>org.directwebremoting.servlet.EfficientShutdownServletContextListener</listener-class>
    </listener>
    <listener>
        <listener-class> org.darkness.webqq.web.servlet.PublisherServletContextListener</listener-class>
    </listener>

最后,看一下dwr的映射关系dwr.xml:
<dwr>
  <allow>
    
    <create creator="new" javascript="Publisher" scope="application">
      <param name="class" value="org.darkness.webqq.web.servlet.Publisher"/>
    </create>
    <convert converter="bean" match="org.darkness.webqq.model.WebQQUser"/>

    <!-- this is a bad idea for live, but can be useful in testing -->
    <convert converter="exception" match="java.lang.Exception"/>
    <convert converter="bean" match="java.lang.StackTraceElement"/>
  </allow>
</dwr>

注意<convert converter="bean" match="org.darkness.webqq.model.WebQQUser"/>这个配置,dwr允许将自定义的Java类型与js对象进行相互转换,但要声明转换器。
以下是程序运行的结果:

  • 大小: 25 KB
分享到:
评论
11 楼 suken2302401 2009-11-14  
最好的做法是监听scriptSession  这种做法对于访问量大的  服务器扛不住的
10 楼 g3123298 2009-06-19  
哥们我有事找您 请教您一下!!
9 楼 g3123298 2009-06-09  
ext中2个js文件 一个放着treepanel了 另一个怎么调用它里面的treepanel?
8 楼 myclover 2009-06-03  
可以详细点说明一下反正ajax技术吗?
最好能够使用图解的方式给我们看看
这样看着好像还不是很明白,客户端和
服务器所传输的格式是怎么样的啊?
还是依赖HTTP协议进行传输的吗?
7 楼 depravedangel 2009-06-01  
g3123298 写道

depravedangel 写道
没有说随机的事件 g3123298 写道 depravedangel 写道 WebQQUser user = users.getNextUserStatu(); g3123298 写道 做了一对 但应该是一个在线显示另一个不在线显示 定时 开始全下线 然后循环在线&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp; 我是在WebQQUser user = users.getNextUserStatu();这个方法里面采用了一个线程来随机产生一个人员的上下线状态,所以不一定是 “然后循环在线”,可能一个人刚上线了,接着又下线了,这个是随机的,你可以将这个方法内部换成你在线人员列表里面的真实数据。 我可能不太理解您随机出现的意思, 但我想要的需求是在mysql数据库读在线的人数 然后前台有人下线触角一个事件然后对方变成灰色,没有说随机的事件 打扰您了 我是采取随机策略来模拟人员的上下线来进行测试的,你在正式的项目中之需要将随机生成的人员列表改成你真正的在线人员列表就可以了 请述我打扰您了,我很菜 变成真正的在线人员 直接在数据库多填些数据 做模拟人员我不太懂 望您做事坐到低送佛送到西,您这样给我让我做我消化不了 谢谢

我是在内存中模拟的人员上下线,并没有在数据库填数据
WebQQUser user = users.getNextUserStatu();一次也只模拟了一个人的在线状态,你可以将这块代码换成你内存中的在线人员列表。
既然都是在内存中的,不存在切换的问题,你自己想想。
6 楼 g3123298 2009-06-01  
depravedangel 写道

没有说随机的事件
g3123298 写道
depravedangel 写道 WebQQUser user = users.getNextUserStatu(); g3123298 写道 做了一对 但应该是一个在线显示另一个不在线显示 定时 开始全下线 然后循环在线&amp;amp;amp;nbsp;&amp;amp;amp;nbsp;&amp;amp;amp;nbsp; 我是在WebQQUser user = users.getNextUserStatu();这个方法里面采用了一个线程来随机产生一个人员的上下线状态,所以不一定是 “然后循环在线”,可能一个人刚上线了,接着又下线了,这个是随机的,你可以将这个方法内部换成你在线人员列表里面的真实数据。 我可能不太理解您随机出现的意思, 但我想要的需求是在mysql数据库读在线的人数 然后前台有人下线触角一个事件然后对方变成灰色,没有说随机的事件 打扰您了 我是采取随机策略来模拟人员的上下线来进行测试的,你在正式的项目中之需要将随机生成的人员列表改成你真正的在线人员列表就可以了

请述我打扰您了,我很菜
变成真正的在线人员 直接在数据库多填些数据 做模拟人员我不太懂
望您做事坐到低送佛送到西,您这样给我让我做我消化不了 谢谢
5 楼 g3123298 2009-06-01  
还有2个小点
第一个点就是发送的那个键盘事件Enter的

第二个点就是带有特殊符号的发送不到对方比方 ' i'm from Beijing 进不到数据库
4 楼 depravedangel 2009-05-31  
没有说随机的事件
g3123298 写道

depravedangel 写道
WebQQUser user = users.getNextUserStatu(); g3123298 写道 做了一对 但应该是一个在线显示另一个不在线显示 定时 开始全下线 然后循环在线&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; 我是在WebQQUser user = users.getNextUserStatu();这个方法里面采用了一个线程来随机产生一个人员的上下线状态,所以不一定是 “然后循环在线”,可能一个人刚上线了,接着又下线了,这个是随机的,你可以将这个方法内部换成你在线人员列表里面的真实数据。 我可能不太理解您随机出现的意思, 但我想要的需求是在mysql数据库读在线的人数 然后前台有人下线触角一个事件然后对方变成灰色,没有说随机的事件 打扰您了

我是采取随机策略来模拟人员的上下线来进行测试的,你在正式的项目中之需要将随机生成的人员列表改成你真正的在线人员列表就可以了
3 楼 g3123298 2009-05-31  
depravedangel 写道

WebQQUser user = users.getNextUserStatu();
g3123298 写道
做了一对 但应该是一个在线显示另一个不在线显示 定时 开始全下线 然后循环在线&amp;nbsp;&amp;nbsp;&amp;nbsp; 我是在WebQQUser user = users.getNextUserStatu();这个方法里面采用了一个线程来随机产生一个人员的上下线状态,所以不一定是 “然后循环在线”,可能一个人刚上线了,接着又下线了,这个是随机的,你可以将这个方法内部换成你在线人员列表里面的真实数据。

我可能不太理解您随机出现的意思,
但我想要的需求是在mysql数据库读在线的人数 然后前台有人下线触角一个事件然后对方变成灰色,没有说随机的事件 打扰您了
2 楼 depravedangel 2009-05-27  
WebQQUser user = users.getNextUserStatu();
g3123298 写道

做了一对 但应该是一个在线显示另一个不在线显示 定时 开始全下线 然后循环在线&nbsp;&nbsp;&nbsp;

我是在WebQQUser user = users.getNextUserStatu();这个方法里面采用了一个线程来随机产生一个人员的上下线状态,所以不一定是 “然后循环在线”,可能一个人刚上线了,接着又下线了,这个是随机的,你可以将这个方法内部换成你在线人员列表里面的真实数据。
1 楼 g3123298 2009-05-26  
做了一对 但应该是一个在线显示另一个不在线显示
定时 开始全下线 然后循环在线   

相关推荐

    WebQQ协议登录加密算法——VC6实现源码

    WebQQ协议登录加密算法——VC6实现源码

    ajax+servlet+jsp实现webqq

    【标题】:“Ajax + Servlet + JSP 实现WebQQ” 【描述】:此项目是基于Ajax、Servlet和JSP技术实现的一个网页版QQ应用。它旨在提供与原版QQ相似的功能,让用户能够在网页上进行即时通讯,无需安装任何客户端软件。...

    ajax + xml 实现的webQQ

    总结来说,Ajax + XML 实现的WebQQ结合了异步通信和结构化数据交换的优势,为用户提供了一种无需下载安装、即开即用的在线聊天体验。这种技术不仅适用于即时通讯应用,还广泛应用于各种需要实时交互和数据更新的Web...

    WebQQ AJAX实现

    WebQQ AJAX实现是一种基于网页的即时通讯技术,它利用了Asynchronous JavaScript and XML(AJAX)的核心特性,使得用户在不刷新整个页面的情况下能够实时发送和接收消息,从而提供了类似于桌面应用的用户体验。AJAX...

    仿webQQ源码 .net ajax XML jQ

    【标题】"仿webQQ源码 .net ajax XML jQ" 涉及的主要知识点包括:WebQQ的实现原理、.NET框架的应用、Ajax技术、XML数据处理以及jQuery库的使用。下面将对这些关键点进行详细介绍。 1. **WebQQ实现原理**:WebQQ是一...

    AJAX实现网页即时聊天(PHP版WEBQQ)

    本项目名为"AJAX实现网页即时聊天(PHP版WEBQQ)",是一款基于AJAX技术构建的在线即时通讯应用,适用于PHP环境。它为用户提供了无需刷新页面即可进行实时聊天的功能,类似于腾讯的WEBQQ服务。该程序特别适合PHP爱好...

    WebQQ效果实现例子

    WebQQ是一种基于网页技术实现的在线聊天应用,它允许用户在浏览器中体验类似于桌面QQ的交互功能。这个“WebQQ效果实现例子”很显然是一个示例项目,旨在展示如何在Web环境中模拟桌面QQ的酷炫效果,如桌面拖拽、桌面...

    (仿webQQ)ajax网页聊天工具 .net版

    这个工具利用了AJAX(Asynchronous JavaScript and XML)技术来实现页面的异步更新,提供类似于即时通讯软件的用户体验,无需刷新整个页面即可实时获取和发送信息。 【描述】中提到“基于.net的仿webQQ网页聊天技术...

    ajax webqq

    【Ajax WebQQ:技术解析与实现】 Ajax(Asynchronous JavaScript and XML)是一种在无需刷新整个网页的情况下,能够更新部分网页的技术。它通过在后台与服务器进行少量数据交换,使网页实现异步更新,大大提升了...

    Web QQ(ajax 实现的一个QQ程序)

    Web QQ是腾讯公司推出的一款基于Ajax技术实现的网页版即时通讯工具,它允许用户在无需安装客户端软件的情况下,...Ajax技术的运用,使得Web应用在不刷新页面的情况下也能实现动态更新,大大提升了用户的在线沟通体验。

    WebQQ在线客服系统 1.0

    基于PHP+MYSQL开发,采用最新ajax技术,使用WebQQ在线客服系统,网站在线客服可以即时知道网站上有访客进入,了解该访客来自哪个区域,来源搜索引擎,或直接输入网址,是否曾经来过,访问了哪些页面,当前访问的页面...

    Comet, 下一代反向AJAX(即服务器推送技术- Server-side push)

    您可能已经听说过 Comet,因为它最近受到了一定的关注。Comet 有时也称反向 Ajax ...目前一些主流网站都有类似的原理,例如:webQQ、开心网、白社会等等,它们中消息动态都是采用类似的技术,也许具体实现方式不一样;

    WebQQ_Demo WebQQ_Demo

    WebQQ_Demo是一个基于Web技术实现的QQ在线聊天示例应用。这个项目展示了如何利用Web技术来模拟原生QQ客户端的功能,让用户可以在浏览器上进行即时通讯。WebQQ_Demo的出现,是互联网技术和社交应用结合的一个典范,它...

    ext 实现的webQQ 源码、应用、含数据库

    3. **Ajax通信**:EXT提供了异步通信的接口,WebQQ通过Ajax技术与服务器进行通信,实现实时的消息收发。 4. **布局管理**:EXT的布局管理器可以帮助组织和调整组件的大小和位置,适应不同屏幕尺寸和分辨率。 5. **...

    webqq ajax js

    【标题】"WebQQ AJAX JS" 是一种基于Web的即时通讯技术,利用AJAX(Asynchronous JavaScript and XML)和JavaScript实现QQ的在线聊天功能。它允许用户在网页上实现与QQ客户端类似的沟通体验,无需安装额外软件,只需...

    韩顺平ajax webqq离线聊天程序

    "webqq"则表明该程序模拟了QQ的在线聊天体验,但通过Web界面实现,用户可以在浏览器中进行聊天,无需安装额外的客户端软件。"离线聊天"暗示了程序可能包含离线消息存储和发送的功能,使得用户在网络不稳定或者离线时...

    JSP+Mysql 实现简易的 WebQQ

    【JSP+MySQL实现简易WebQQ】是一种基于Java服务器页面(JSP)技术和MySQL数据库构建的在线聊天系统,它允许用户通过网页进行即时通讯。在这个项目中,我们将深入探讨涉及的技术、步骤以及关键知识点。 首先,JSP是...

    本源码已经实现webQQ的大部分功能

    熬了几个通宵终于做好了,里面实现的webQQ的大部分功能,而且全开源,适用中高级.net开发人员研究,主要是对 XML 的操作和ajax,还用了少量的JQ可以自由增加组,加好友等 数据库在DB_asp.netfaq.cn文件夹中(sql2000)...

    WEBqq在线文件

    【标题】"WEBqq在线文件"揭示了我们讨论的主题与QQ的网络版本——WebQQ紧密相关。WebQQ是腾讯公司推出的一种基于网页的即时通讯服务,让用户无需下载客户端即可通过浏览器进行聊天、发送文件等操作。它实现了互联网...

    webqq 界面实现代码 html 直接运行 和现有版本完全一致

    AJAX用于在不刷新整个页面的情况下,向服务器发送异步请求并获取数据,比如在WebQQ中实时获取好友的在线状态、新消息等。 5. **WebSocket**:WebSocket协议提供了一种在客户端和服务器之间建立长连接的方式,使得...

Global site tag (gtag.js) - Google Analytics