<filter> <filter-name>Set Character Encoding</filter-name> <filter-class>filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>GBK</param-value> </init-param> <init-param> <!-- Ajax important , charset=utf-8 其他都为gbk --> <param-name>ignore</param-name> <param-value>false</param-value> </init-param> </filter> <listener> <listener-class>hyjc.listener.CustomSessionListener</listener-class> </listener>
还是利用了 poll 的 方案 ,定时 刷新信息, 下一步打算利用长连接 来试试
生成了一个 Ext.window 就是聊天窗口了
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/updateChat.jsp', singleExpand :true, selModel:new Ext.tree.MultiSelectionModel(), root: new Ext.tree.AsyncTreeNode({ text:'Online', children:[{ 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) { 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 query = location.search.substring(1);//获取查询串 var sessionId = SESSION;//Ext.urlDecode(query).sid; // 发送消息 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 (i = 0; i < receivers.length; ++i) { receivers_values.push(receivers[i].attributes.sessionId); } if (receivers_values.length == 0) { alert("您没有选择接收者!"); tree.focus(); return; } //alert(receivers_values.length); if (receivers_values.length > 1) { if (!confirm("您选择了多个接收者,是否继续?")) { return; } } var nickname_value = 'forget'; var pars = { "content":content_value, "receivers":"" + receivers_values, "sender":sessionId // "nickname":'forget' }; var conn = new Ext.data.Connection(); // 发送异步请求 conn.request({ // 请求地址 url: 'chat/sendmsg.jsp', method: 'post', params: pars, // 指定回调函数 callback: msgsent }); } function msgsent(options, success, response) { requestCount--; if (success) { try { var jsonObj = Ext.util.JSON.decode(response.responseText); } catch(e) { } if (jsonObj && jsonObj.success) { var cur = jsonObj.cur; var sessions = []; var c = node.childNodes; for (var i = 0; i < c.length; i++) { sessions[c[i].attributes.sessionId] = c[i].attributes; } if (cur) { var a = []; for (var j = 0; j < cur.receivers.length; j++) { a.push(sessions[cur.receivers[j]].loginName); } 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">'+cur.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); } draw_m(chat_record.dom.lastChild,'#FFB100'); var mc = String.format(msg, cur.time, sessions[cur.sender].loginName, a); Ext.getCmp("history_panel").body.insertHtml('beforeEnd', mc); Ext.getCmp("history_panel").body.scroll('b', 10000, { duration:0.1 }); } Ext.getCmp("htmleditor").reset(); } else if(response.result) alert(response.result); } else { if(response.responseText) alert(response.responseText); } } //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 } var tree = Ext.getCmp('im-tree'); var node = tree.getNodeById('SunriseIm'); var requestCount = 0; function reloadUser() { if (requestCount == 10) { alert('服务器连接失败'); window.location = 'login.jsp'; return; } requestCount++; var conn = new Ext.data.Connection(); // 发送异步请求 conn.request({ // 请求地址 url: 'chat/updateChat.jsp', method: 'post', // 指定回调函数 callback: callback }); //回调函数 function callback(options, success, response) { requestCount--; if (success) { try { var jsonObj = Ext.util.JSON.decode(response.responseText); } catch(e) { } if (jsonObj) { var jsonNodes = jsonObj.nodes; var msgs = jsonObj.msgs; var cs = node.childNodes ; var nodes = {}; var sessions = {}; for (var i = 0; i < cs.length; i++) { nodes[cs[i].id] = cs[i]; } var user; for (var i = 0; i < jsonNodes.length; i++) { user = jsonNodes[i]; // alert(user.sessionId); sessions[user.sessionId] = user; if (nodes[user.id]) { nodes[user.id] = null; continue; } node.appendChild(user); } for (var id in nodes) { if (nodes[id]) node.removeChild(nodes[id]); } 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>' ; if (msgs) { for (var i = 0; i < msgs.length; i++) { var a = []; for (var j = 0; j < msgs[i].receivers.length; j++) { a.push(sessions[msgs[i].receivers[j]].loginName); } var chat_record =new Ext.Element(document.createElement('div')); chat_record.addClass('chat_record'); chat_record.update('<span style="margin:0px 5px 0px 5px">'+msgs[i].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-10,size_chat.height); //canvas.setSize(size_chat.width-,40); chat_record.appendChild(canvas); if(window['G_vmlCanvasManager'] ) { G_vmlCanvasManager.initElement(canvas.dom); } draw_m(chat_record.dom.lastChild,'#FFB100'); var mc = String.format(msg, msgs[i].time, sessions[msgs[i].sender].loginName, a); Ext.getCmp("history_panel").body.insertHtml('beforeEnd', mc); Ext.getCmp("history_panel").body.scroll('b', 10000, { duration:0.1 }); } if(!chatWin.isVisible()){ self.focus(); Ext.example.msg('叮当', '您有新的短消息 <a href="javascript:window.startChatWin()">查看</a>'); } } } else if(response.responseText) alert(response.responseText); } else { if(response.responseText) alert(response.responseText); } } } //chatWin.show(); //chatWin.setSize(0,0); //chatWin.hide(); if(!Ext.isIE) { chatWin.collapse(); } var chatTask = { run:reloadUser, //scope:this, interval: 5000 //1 second }; time_pro = new Ext.util.TaskRunner(); time_pro.start(chatTask); //chatWin.hide(); window.startChatWin = function (){ chatWin.show(); chatWin.center(); //Ext.getCmp('htmleditor').focus(); }; function 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(); } });
后台 见附件 ,主要是还要设一下 sessionListener