`
yiminghe
  • 浏览: 1433707 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Extjs 聊天窗口 -续3 用pushlet来实现

阅读更多

       前一篇 自己实现了http长连接 , 很繁琐,后来看到pushlet 好评如潮 ,就用pushlet 重写了一遍,由于  pushlet ajax api 以及 servlet 使用 get 方法来实现 ,并且对于中文有的问题 ,故 将其改为 post 方式,并对于中文两次编码

 

 

 

修改了 ajax api , ajax-pushlet-client.js ,改为 post 方式提交数据 ,并 在网络处状况时 通知 回调函数

 

修改 pushlet servlet , (nl\justobjects\pushlet\servlet\Pushlet.java) 使其支持 post 方式,原来只是支持post xml



首先 ext chat window 的建立: 用了 pushlet 代码就简洁多了 ,我基本上是把pushlet当作一个数据库使用的

 

使用代码 : (代码简要分析见后)

 

/*
 利用pushlet 实现了 用户登录及时通知,退出及时通知,发送消息及时通知,用户单点登陆功能


 */
Ext.onReady(function () {
    var chatWin = new Ext.Window({
        width: 800,
        height: 500,
        title: 'Ext聊天窗口测试版',
        renderTo: document.body,
        border: false,
        hidden: true,
        layout: 'border',
        closeAction: 'hide',
        collapsible: true,
        constrain: true,
        iconCls: 'my-userCommentIcon',
        maximizable: true,
        items: [{
            region: 'west',
            id: 'chat-west-panel',
            title: '用户面板',
            split: true,
            width: 170,
            minSize: 100,
            maxSize: 200,
            collapsible: true,
            constrain: true,
            //margins:'0 0 0 5',
            layout: 'accordion',
            layoutConfig: {
                animate: true
            },
            items: [{
                items: new Ext.tree.TreePanel({
                    id: 'im-tree',
                    //rootVisible: false,
                    lines: false,
                    border: false,
                    dataUrl: 'chat/getUserFirst.jsp',
                    singleExpand: true,
                    selModel: new Ext.tree.MultiSelectionModel(),
                    root: new Ext.tree.AsyncTreeNode({
                        text: 'Sunrise',
                        id: 'SunriseIm',
                        //nodeType: 'async',
                        singleClickExpand: true,
                        expandable: true,
                        expanded: true
                    })
                }),
                title: '在线人员',
                //layout:'form',
                border: false,
                autoScroll: true,
                iconCls: 'im_list',
                tools: [{
                    id: 'refresh',
                    qtip: '刷新在线信息',
                    // hidden:true,
                    handler: function (event, toolEl, panel) {
                        imRootNode.reload();
                        //reloadUser();
                    }
                },
                {
                    id: 'close',
                    qtip: '清除选定',
                    // hidden:true,
                    handler: function (event, toolEl, panel) {
                        Ext.getCmp('im-tree').getSelectionModel().clearSelections();
                    }
                }]
            },
            {
                title: 'Settings',
                html: '<p>Some settings in here.</p>',
                border: false,
                iconCls: 'settings'
            }]
        },
        {
            region: 'center',
            layout: 'border',
            items: [{
                region: 'center',
                title: '历史记录  ',
                id: 'history_panel',
                autoScroll: true,
                iconCls: 'my-userCommentIcon',
                tools: [{
                    id: 'refresh',
                    qtip: '注意:如果长时间没有收到对方回应,试一下',
                    // hidden:true,
                    handler: function (event, toolEl, panel) {
                        // refresh logic
                    }
                }]
            },
            {
                region: 'south',
                title: '聊天啦',
                layout: 'fit',
                iconCls: 'user_edit',
                autoScroll: true,
                height: 200,
                collapsible: true,
                //margins:'0 0 0 0',
                items: {
                    xtype: 'form',
                    baseCls: 'x-plain',
                    autoHeight: true,
                    autoWidth: true,
                    bodyStyle: 'padding:10 10px 0;',
                    defaults: {
                        anchor: '95%'
                    },
                    items: [{
                        xtype: 'htmleditor',
                        height: 130,
                        id: 'htmleditor',
                        hideLabel: true
                    }]
                },
                bbar: [{
                    text: '发送请输入Ctrl-Enter',
                    handler: function () {
                        sendmsg();
                    },
                    iconCls: 'my-sendingIcon'
                },
                '-', {
                    text: '清除',
                    handler: function () {
                        Ext.getCmp("htmleditor").reset();
                    }
                }]
            }]
        }]
    });
    var tree = Ext.getCmp('im-tree');
    var imRootNode = tree.getNodeById('SunriseIm');
    tree.getLoader().on("loadexception", function (this1, node, response) {
        window.net_status = '_0';
        if (!Ext.Msg.isVisible()) Ext.Msg.wait('网络出问题了,正在重新连接中....');;
        setTimeout(function () {
            imRootNode.reload();
        },
        5000);
    });
    tree.getLoader().on("load", function (this1, node, response) {
        Ext.Msg.hide();
        if (window.net_status) {
            if (window.net_status == '_0') {
                window.net_status = '_1';
                PL.state = 2;
                init_my_chat();
            }
        }
    });
    var query = location.search.substring(1); //获取查询串
    var sessionId = SESSION; //Ext.urlDecode(query).sid;
    // 发送消息
    function onMsg(content, sender, receivers) {
        var msg = '<div style="margin:20px 5px 10px 5px">   <img src="js/ext/user_comment.png"/> {0} <b>{1}</b> 对 <b>{2}</b> 说:<br></div>';
        var chat_record = new Ext.Element(document.createElement('div'));
        chat_record.addClass('chat_record');
        chat_record.update('<span style="margin:0px 5px 0px 5px">' + decodeURIComponent(content) + '</span>');
        Ext.getCmp("history_panel").body.appendChild(chat_record);
        var canvas = new Ext.Element(document.createElement('canvas'));
        var size_chat = chat_record.getSize();
        if (!Ext.isIE && size_chat.height < 100) {
            chat_record.setHeight(100);
            size_chat.height = 100;
        }
        canvas.setSize(size_chat.width - 30, size_chat.height);
        //canvas.setSize(size_chat.width-,40);
        chat_record.appendChild(canvas);
        if (window['G_vmlCanvasManager']) {
            G_vmlCanvasManager.initElement(canvas.dom);
        }
        google_dialog_draw_m(chat_record.dom.lastChild, '#FFB100');
        var mc = String.format(((msg)), new Date().toLocaleString(), sender, receivers);
        Ext.getCmp("history_panel").body.insertHtml('beforeEnd', mc);
        Ext.getCmp("history_panel").body.scroll('b', 10000, {
            duration: 0.1
        });
    }

    function sendmsg() {
        Ext.getCmp("htmleditor").syncValue();
        var content_value = Ext.getCmp("htmleditor").getValue();
        if (content_value.trim() == '') {
            alert("您没有输入消息文本内容!");
            Ext.getCmp("htmleditor").focus(true);
            return;
        }
        var receivers_values = [];
        var tree = Ext.getCmp('im-tree');
        var receivers = tree.getSelectionModel().getSelectedNodes();
        for (var i = 0; i < receivers.length; ++i) {
            receivers_values.push(receivers[i].attributes.loginId);
        }
        if (receivers_values.length == 0) {
            alert("您没有选择接收者!");
            tree.focus();
            return;
        }
        if (receivers_values.length > 1) {
            if (!confirm("您选择了多个接收者,是否继续?")) {
                return;
            }
        }
        for (var i = 0; i < receivers_values.length; i++) {
            p_publish('/CHAT/' + receivers_values[i], 'action', 'CHAT', 'msg', encodeURIComponent(encodeURIComponent(content_value)), 'sender', encodeURIComponent(CURRENTUSERID), 'receivers', encodeURIComponent(receivers_values.join(',')));
        }
        onMsg(encodeURIComponent(content_value), CURRENTUSERID, receivers_values);
        Ext.getCmp("htmleditor").reset();
    }
    //event for source editing mode
    new Ext.KeyMap(Ext.getCmp("htmleditor").getEl(), [{
        key: 13,
        ctrl: true,
        stopEvent: true,
        fn: sendmsg
    }]);
    //event for normal mode
    Ext.getCmp("htmleditor").onEditorEvent = function (e) {
        this.updateToolbar();
        var keyCode = (document.layers) ? keyStroke.which : e.keyCode;
        if (keyCode == 13 && e.ctrlKey) sendmsg();
        //it'a my handler
    }
    /*
     对pushlet各种事件的处理
     */
    window.onError = function (event) {
        imRootNode.reload();
        //PL.state = 2;
        //setTimeout(init_my_chat , 1000);
        /*
		 	var p_errortype = event.get('p_errortype');
		 	//alert(p_errortype);
		 	if(p_errortype) {
		 		if(p_errortype == 'network') {
		 			PL.state = 2;
		 			setTimeout(p_join , 1000);
		 			//p_join();
		 			//alert(PL.state);
		 			
		 		}
		 	}
			//	alert(event.get('p_event') +'   -  error');
			*/
    }
    window.onData = function (event) {
        var action = event.get('action');
        //alert(action);
        if (action == 'CHAT') {
            var msg = event.get('msg');
            var sender = event.get('sender');
            var receivers = event.get('receivers').split(',');
            //if(sender == CURRENTUSERID) return;
            onMsg(msg, sender, receivers);
            if (!chatWin.isVisible()) {
                self.focus();
                Ext.example.msg('叮当', '您有新的短消息     <a href="javascript:window.startChatWin()">查看</a>');
            }
        } else if (action == 'USER') {
            var loginId = event.get('loginId');
            var loginName = decodeURIComponent(event.get('loginName'));
            var c = imRootNode.childNodes;
            var i = 0;
            for (i = 0; i < c.length; i++) {
                if (c[i].attributes.loginId == loginId) break;
            }
            if (i == c.length) {
                imRootNode.appendChild({
                    loginId: loginId,
                    leaf: true,
                    iconCls: 'user',
                    loginName: loginName,
                    text: loginId + "(" + loginName + ")"
                });
            }
        } else if (action == 'EXPIRE') {
            // Stop pushlet session
            p_leave();
            // Give some time to send the leave request to server
            setTimeout(function () {
                alert('有人从其它地方登陆了,你被退出!');
                window.location = 'index.jsp';
            },
            1000);
        } else if (action == 'USERDEL') {
            var loginId = event.get('loginId');
            var c = imRootNode.findChild('loginId', loginId);
            imRootNode.removeChild(c);
        }
    };
    if (!Ext.isIE) {
        chatWin.collapse();
    }
    function init_my_chat() {
        /*
		     监控各种事件源
		     */
        p_join();
        //监控发给自己的消息
        p_listen('/CHAT/' + encodeURIComponent(CURRENTUSERID));
        //监控自己是否在其他地方的登陆
        p_listen('/EXPIREDSESSIONID/' + encodeURIComponent(SESSION));
        //监控系统总的人数
        p_listen('/USER');
        //通知我来了
        p_publish('/USER', 'action', 'USER', 'loginId', encodeURIComponent(CURRENTUSERID), 'loginName', encodeURIComponent((encodeURIComponent(CURRENTUSERNAME))));
    }
    init_my_chat();
    //失效的session id
    var expiredSessionIdStr = Ext.urlDecode(window.location.search.substring(1));
    setTimeout(function () {
        //通知失效的sessionid窗口
        if (expiredSessionIdStr.expiredSessionId) {
            p_publish('/EXPIREDSESSIONID/' + encodeURIComponent(expiredSessionIdStr.expiredSessionId), 'action', 'EXPIRE', 'expiredSessionId', encodeURIComponent(expiredSessionIdStr.expiredSessionId));
        }
    },
    1000);
    window.startChatWin = function () {
        chatWin.show();
        chatWin.center();
        //Ext.getCmp('htmleditor').focus();
    };
    //心跳函数 五分钟更新一次,整体user数据,防止不按退出关闭浏览器
    var chatTask = {
        run: function () {
            imRootNode.reload();
        },
        //scope:this,
        interval: 10 * 60 * 1000 //1 second
    };
    time_pro = new Ext.util.TaskRunner();
    time_pro.start(chatTask);
    function google_dialog_draw_m(canvas, color) {
        var context = canvas.getContext("2d");
        var width = canvas.width;
        var height2 = canvas.height - 4.5;
        var height = canvas.height;
        context.beginPath();
        context.strokeStyle = color;
        context.moveTo(0.5, 0.5 + 5);
        context.arc(5.5, 5.5, 5, -Math.PI, -Math.PI / 2, false);
        context.lineTo(width - 0.5 - 5, 0.5);
        context.arc(width - 0.5 - 5, 5.5, 5, -Math.PI / 2, 0, false);
        context.lineTo(width - 0.5, height2 - 5);
        context.arc(width - 0.5 - 5, height2 - 5, 5, 0, Math.PI / 2, false);
        context.lineTo(width / 2 + 3, height2);
        context.lineTo(width / 2, height);
        context.lineTo(width / 2 - 3, height2);
        context.lineTo(0.5 + 5, height2);
        context.arc(0.5 + 5, height2 - 5, 5, Math.PI / 2, Math.PI, false);
        context.lineTo(0.5, 0.5 + 5);
        context.stroke();
    }
});
 


简单上述代码分析

 

还是很多人问我问题,我就简单解释一下上面代码,本来没打算做教程,只是自己记录一下的呀


报什么错啊,java那个替换好原来的java文件,在pushlet根目录要重新ant编译成一个jar,放在lib下面

ajax.js 放在头部

Ext.onReady 后进行其他处理

首先指明自己要监听的队列

init_my_chat 这个函数


发送消息就是往一个队列发送一个信号:

例如
p_publish('/CHAT/' + receivers_values[i], 'action', 'CHAT', 'msg', encodeURIComponent(encodeURIComponent(content_value)), 
               'sender', encodeURIComponent(CURRENTUSERID), 'receivers', encodeURIComponent(receivers_values.join(','))); 

接收消息就是
对各种信号处理

window.onData = function(event)




代码不难的,要细致一点,出错也要告诉我具体的信息才行,用firebug 调试,java 要配置 log4j

 

 

分享到:
评论
31 楼 windy0605 2013-09-22  
lz 这个能发图片或文件么?
30 楼 冻未条 2013-04-04  
楼主,求教,我用了pushlet,客户端有时能接收到,有时不能接收到。不能接收到时,有时服务端会报
00:55:39,019  WARN pushlet:93 - S-0:0:0:0:0:0:0:1[1]: [Subscriber] not alive for at least: 45000ms, leaving...
00:55:39,020  INFO pushlet:79 - SessionManager: Thu Apr 04 00:55:39 CST 2013 1 at 0:0:0:0:0:0:0:1 removed

00:59:10,636  INFO pushlet:79 - SessionManager: Thu Apr 04 00:59:10 CST 2013 AgingTimerTask: Session expired: 0:0:0:0:0:0:0:1[5]
00:59:10,636  INFO pushlet:79 - SessionManager: Thu Apr 04 00:59:10 CST 2013 5 at 0:0:0:0:0:0:0:1 removed

29 楼 cuisuqiang 2012-10-08  
cuisuqiang 写道
yiminghe 写道
646158013 写道
楼主你好。有一个问题。pushlet.srv 找不到是什么情况造成的。还有就是我的字符编码都同意的换成了 utf-8 为什么还有 中文乱码。新手问题还望解答。谢谢、


好像没用的,一定要自己客户端encodeURIComponent进行编码

pushlet传递中文有问题,页面什么都不显示!我的解决方法是后台编码,前台解码!详细见我博客!

http://cuisuqiang.iteye.com/多指教
28 楼 cuisuqiang 2012-10-08  
yiminghe 写道
646158013 写道
楼主你好。有一个问题。pushlet.srv 找不到是什么情况造成的。还有就是我的字符编码都同意的换成了 utf-8 为什么还有 中文乱码。新手问题还望解答。谢谢、


好像没用的,一定要自己客户端encodeURIComponent进行编码

pushlet传递中文有问题,页面什么都不显示!我的解决方法是后台编码,前台解码!详细见我博客!
27 楼 yiminghe 2011-04-11  
646158013 写道
楼主你好。有一个问题。pushlet.srv 找不到是什么情况造成的。还有就是我的字符编码都同意的换成了 utf-8 为什么还有 中文乱码。新手问题还望解答。谢谢、


好像没用的,一定要自己客户端encodeURIComponent进行编码
26 楼 646158013 2011-04-10  
楼主你好。有一个问题。pushlet.srv 找不到是什么情况造成的。还有就是我的字符编码都同意的换成了 utf-8 为什么还有 中文乱码。新手问题还望解答。谢谢、
25 楼 johnson_liu 2011-01-10  
刚学习pushlet这个东西,对于中文问题很是头疼,我对URl进行了俩次转码也改用了POST方式但是就是会出现一用中文session会被removed的~
24 楼 yiminghe 2010-10-29  
McQsad 写道
可以把你的qq告诉我吗, 我在chat的例子中有一些问题,我希望可以和你进一步交流  谢谢


一般不上qq,可以直接站内信
23 楼 McQsad 2010-10-29  
可以把你的qq告诉我吗, 我在chat的例子中有一些问题,我希望可以和你进一步交流  谢谢
22 楼 McQsad 2010-10-28  
yiminghe 写道
McQsad 写道
yiminghe 写道
McQsad 写道
我刚开始学习pushlet    正在看pushlet的源码   在pushlet中publish()这个函数在ajax的那个js文件中 是两个参数,为什么在页面调用它是传入的参数很多,可以给解答吗?


我都忘了,你再仔细看下,似乎代码直接用arguments引用其他参数的吧,不需要形参



恩  是arguments引用其他参数。我现在看了好多帖子,但是好像也不知道怎么去写一个pushlet的例子,我下载了源码  在其中仔细看chat的那个示例,里面有一个ajax的js文件,还有一个js-pushlet-client的js文件,为什么会有两个。就是觉得东看看,西看看,就迷糊了,想问问你当时是如何看的,如何着手写第一个pushlet的示例,我现在不知道模仿哪个,麻烦了


给你两个链接仔细看下吧:

https://www.ibm.com/developerworks/cn/web/wa-lo-comet/
http://www.javaworld.com/jw-03-2000/jw-03-pushlet.html



谢谢。。。 再有不懂得再来请教
21 楼 yiminghe 2010-10-27  
McQsad 写道
yiminghe 写道
McQsad 写道
我刚开始学习pushlet    正在看pushlet的源码   在pushlet中publish()这个函数在ajax的那个js文件中 是两个参数,为什么在页面调用它是传入的参数很多,可以给解答吗?


我都忘了,你再仔细看下,似乎代码直接用arguments引用其他参数的吧,不需要形参



恩  是arguments引用其他参数。我现在看了好多帖子,但是好像也不知道怎么去写一个pushlet的例子,我下载了源码  在其中仔细看chat的那个示例,里面有一个ajax的js文件,还有一个js-pushlet-client的js文件,为什么会有两个。就是觉得东看看,西看看,就迷糊了,想问问你当时是如何看的,如何着手写第一个pushlet的示例,我现在不知道模仿哪个,麻烦了


给你两个链接仔细看下吧:

https://www.ibm.com/developerworks/cn/web/wa-lo-comet/
http://www.javaworld.com/jw-03-2000/jw-03-pushlet.html
20 楼 McQsad 2010-10-27  
yiminghe 写道
McQsad 写道
我刚开始学习pushlet    正在看pushlet的源码   在pushlet中publish()这个函数在ajax的那个js文件中 是两个参数,为什么在页面调用它是传入的参数很多,可以给解答吗?


我都忘了,你再仔细看下,似乎代码直接用arguments引用其他参数的吧,不需要形参



恩  是arguments引用其他参数。我现在看了好多帖子,但是好像也不知道怎么去写一个pushlet的例子,我下载了源码  在其中仔细看chat的那个示例,里面有一个ajax的js文件,还有一个js-pushlet-client的js文件,为什么会有两个。就是觉得东看看,西看看,就迷糊了,想问问你当时是如何看的,如何着手写第一个pushlet的示例,我现在不知道模仿哪个,麻烦了
19 楼 yiminghe 2010-10-27  
McQsad 写道
我刚开始学习pushlet    正在看pushlet的源码   在pushlet中publish()这个函数在ajax的那个js文件中 是两个参数,为什么在页面调用它是传入的参数很多,可以给解答吗?


我都忘了,你再仔细看下,似乎代码直接用arguments引用其他参数的吧,不需要形参
18 楼 McQsad 2010-10-27  
我刚开始学习pushlet    正在看pushlet的源码   在pushlet中publish()这个函数在ajax的那个js文件中 是两个参数,为什么在页面调用它是传入的参数很多,可以给解答吗?
17 楼 zhouzelian03 2010-08-22  
yiminghe 写道
zhouzelian03 写道
我发现pushlet2.0.4中的例子chat,用英文就可以聊天,但是用中文就不行了,请问要怎么解决?


当时看它的源码好像写死了(编)解码方式,不依赖与服务器配置的话就是用encodeURIComponent 编码发送消息
服务器端程序再解码

这只是权且之计,效率不是很好



问题解决了,谢谢...
16 楼 yiminghe 2010-08-22  
zhouzelian03 写道
我发现pushlet2.0.4中的例子chat,用英文就可以聊天,但是用中文就不行了,请问要怎么解决?


当时看它的源码好像写死了(编)解码方式,不依赖与服务器配置的话就是用encodeURIComponent 编码发送消息
服务器端程序再解码

这只是权且之计,效率不是很好
15 楼 zhouzelian03 2010-08-22  
我发现pushlet2.0.4中的例子chat,用英文就可以聊天,但是用中文就不行了,请问要怎么解决?
14 楼 xiaoyu966 2009-03-30  
楼主,可以发一下界面美化中用到的图片吗?实在找不到那些图片。我决定一步一步来,先看着你的代码把界面搭建起来,再慢慢查资料看懂你的代码
13 楼 xiaoyu966 2009-03-30  
yiminghe 写道

xiaoyu966 写道
楼主,我怎么弄不不能让他跑起来。。。主要刚学没多久,毕业设计就要做带数据库的即时聊天。难度太大了。可以给我一份完整的代码吗?我想参考一下,跪谢!!主要时间实在是不够了,我得新学struts2,spring,ibatis,还有ext。。还有comet。公司给定的题目。每天只有2小时可以学习。有种想跳楼的感觉了。。。项目的一部分,后台分解太麻烦,我的建议:关于pushlet你可以看看 http://www.matrix.org.cn/resource/article/2007-01-16/bcc2c490-a502-11db-8440-755941c7293d.html后台请努力先看看简单的jsp即可 ,ext 方面要多看自带的example

好的,谢谢你!
12 楼 yiminghe 2009-03-29  
xiaoyu966 写道

楼主,我怎么弄不不能让他跑起来。。。主要刚学没多久,毕业设计就要做带数据库的即时聊天。难度太大了。可以给我一份完整的代码吗?
我想参考一下,跪谢!!主要时间实在是不够了,我得新学struts2,spring,ibatis,还有ext。。还有comet。公司给定的题目。每天只有2小时可以学习。有种想跳楼的感觉了。。。


项目的一部分,后台分解太麻烦,我的建议:

关于pushlet你可以看看
http://www.matrix.org.cn/resource/article/2007-01-16/bcc2c490-a502-11db-8440-755941c7293d.html

后台请努力先看看简单的jsp即可 ,

ext 方面要多看自带的example

相关推荐

Global site tag (gtag.js) - Google Analytics