专业编程基础技术教程

网站首页 > 基础教程 正文

基于WebSocket的网页端即时通讯技术

ccvgpt 2024-07-24 11:16:46 基础教程 19 ℃

基于html5的Websocket网页即时通讯技术,前端开发采用ExtJS前端框架

JavaEE框架:Mybatis、SpringMVC

基于WebSocket的网页端即时通讯技术

先去官网下载ExtJS框架的资料文件:

https://www.sencha.com/products/extjs/evaluate/

可以参考中文翻译过来的官网查看API:

http://extjs-doc-cn.github.io/ext4api/

下载集成的jar:


websocket.css:

@CHARSET "UTF-8";
.l-im-message-warn {
 font-family: "微软雅黑";
 cursor: default;
 width: 100%;
 padding: 5px 0px 5px 25px;
 -webkit-user-select : none;
 background: url("../images/information.png") no-repeat 5;
}
.l-im-message {
 font-family: "微软雅黑";
 cursor: default;
 width: 100%;
}
.l-im-message-over {
 background-color: rgba(233, 233, 233, 0.5);
}
.l-im-message-selected {
 background-color: rgba(250, 218, 90, 0.5);
}
.l-im-message-header {
 font-size: 12px;
 padding: 5px 0px 5px 10px;
}
.l-im-message-header-self {
 color: green;
}
.l-im-message-header-remote {
 color: blue;
}
.l-im-message-body {
 font-size: 12px;
 padding: 2px 0px 2px 20px;
}
.user-win {
 background-image: url( ../images/user_win.png )
 !important;
}
.user-online {
 background-image: url( ../images/group.png )
 !important;
}
.user {
 background-image: url( ../images/user.gif )
 !important;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

websocket.js:

var websocket;
var isCreatw = false;
var title="";
var win;
var input;
var isQj = true;
var toUser="";
function toUserMsg(toU){
 if((!isQj && toUser == toU) || toU == user){
 win.setTitle(title + " (已连接) 【现在全局对话】");
 isQj = true;
 toUser = "";
 }else{
 win.setTitle(title + " (已连接) 【现在单独与"+toU+"对话】");
 isQj = false;
 toUser = toU;
 }
}
 function creatw() {
 if(isCreatw){
 alert("已经启动");
 return;
 }else{
 isCreatw = true;
 }
 //创建用户输入框
 input = Ext.create('Ext.form.field.HtmlEditor', {
 region : 'south',
 height : 120,
 enableFont : false,
 enableSourceEdit : false,
 enableAlignments : false,
 listeners : {
 initialize : function() {
 Ext.EventManager.on(me.input.getDoc(), {
 keyup : function(e) {
 if (e.ctrlKey === true
 && e.keyCode == 13) {
 e.preventDefault();
 e.stopPropagation();
 send();
 }
 }
 });
 }
 }
 });
 //创建消息展示容器
 var output = Ext.create('MessageContainer', {
 region : 'center'
 });
 var dialog = Ext.create('Ext.panel.Panel', {
 region : 'center',
 layout : 'border',
 items : [input, output],
 buttons : [{
 text : '发送',
 handler : send
 }]
 });
 //初始话WebSocket
 function initWebSocket() {
 if (window.WebSocket) {
 websocket = new WebSocket(encodeURI('ws://'+wimadress));
 websocket.onopen = function() {
 //连接成功
 win.setTitle(title + ' (已连接) 【现在全局对话】');
 websocket.send('admin'+user);
 }
 websocket.onerror = function() {
 //连接失败
 win.setTitle(title + ' (连接发生错误)');
 }
 websocket.onclose = function() {
 //连接断开
 win.setTitle(title + ' (已经断开连接)');
 }
 //消息接收
 websocket.onmessage = function(message) {
 var message = JSON.parse(message.data);
 //接收用户发送的消息
 if (message.type == 'message') {
 output.receive(message);
 } else if (message.type == 'get_online_user') {
 //获取在线用户列表
 var root = onlineUser.getRootNode();
 Ext.each(message.list,function(user){
 var node = root.createNode({
 id : user,
 text : user,
 iconCls : 'user',
 leaf : true
 });
 root.appendChild(node);
 });
 } else if (message.type == 'user_join') {
 //用户上线
 var root = onlineUser.getRootNode();
 var user = message.user;
 var node = root.createNode({
 id : user,
 text : user,
 iconCls : 'user',
 leaf : true
 });
 root.appendChild(node);
 } else if (message.type == 'user_leave') {
 //用户下线
 var root = onlineUser.getRootNode();
 var user = message.user;
 var node = root.findChild('id',user);
 root.removeChild(node);
 }
 }
 }
 };
 //在线用户树
 var onlineUser = Ext.create('Ext.tree.Panel', {
 title : '在线用户',
 rootVisible : false,
 region : 'east',
 width : 150,
 lines : false,
 useArrows : true,
 autoScroll : true,
 split : true,
 iconCls : 'user-online',
 store : Ext.create('Ext.data.TreeStore', {
 root : {
 text : '在线用户',
 expanded : true,
 children : []
 }
 })
 });
 title = '欢迎您:' + user;
 //展示窗口
 win = Ext.create('Ext.window.Window', {
 title : title + ' (未连接)',
 layout : 'border',
 iconCls : 'user-win',
 minWidth : 650,
 minHeight : 460,
 width : 650,
 animateTarget : 'websocket_button',
 height : 460,
 items : [dialog,onlineUser],
 border : false,
 listeners : {
 render : function() {
 initWebSocket();
 }
 }
 });
 win.show();
 win.on("close",function(){
 websocket.send('LeaveAdmin');
 isCreatw = false;
 });
 //发送消息
 function send() {
 var content = input.getValue();
 if(toUser != ""){content = "admin886"+toUser+"admin888" + content;}
 var message = {};
 if (websocket != null) {
 if (input.getValue()) {
 Ext.apply(message, {
 from : user,
 content : content,
 timestamp : new Date().getTime(),
 type : 'message'
 });
 websocket.send(JSON.stringify(message));
 //output.receive(message);
 input.setValue('');
 }
 } else {
 Ext.Msg.alert('提示', '您已经掉线,无法发送消息!');
 }
 }
};
//用于展示用户的聊天信息
Ext.define('MessageContainer', {
 extend : 'Ext.view.View',
 trackOver : true,
 multiSelect : false,
 itemCls : 'l-im-message',
 itemSelector : 'div.l-im-message',
 overItemCls : 'l-im-message-over',
 selectedItemCls : 'l-im-message-selected',
 style : {
 overflow : 'auto',
 backgroundColor : '#fff'
 },
 tpl : [
 '<div class="l-im-message-warn">?欢迎使用即时通讯系统。</div>',
 '<tpl for=".">',
 '<div class="l-im-message">',
 '<div class="l-im-message-header l-im-message-header-{source}">{from} {timestamp}</div>',
 '<div class="l-im-message-body">{content}</div>', '</div>',
 '</tpl>'],
 messages : [],
 initComponent : function() {
 var me = this;
 me.messageModel = Ext.define('Leetop.im.MessageModel', {
 extend : 'Ext.data.Model',
 fields : ['from', 'timestamp', 'content', 'source']
 });
 me.store = Ext.create('Ext.data.Store', {
 model : 'Leetop.im.MessageModel',
 data : me.messages
 });
 me.callParent();
 },
 //将服务器推送的信息展示到页面中
 receive : function(message) {
 var me = this;
 message['timestamp'] = Ext.Date.format(new Date(message['timestamp']),
 'H:i:s');
 if(message.from == user){
 message.source = 'self';
 }else{
 message.source = 'remote';
 }
 me.store.add(message);
 if (me.el.dom) {
 me.el.dom.scrollTop = me.el.dom.scrollHeight;
 }
 }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

业务代码编写:

ChatServer.java

package com.appms.websocket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Date;
import net.sf.json.JSONObject;
import org.java_websocket.WebSocket;
import org.java_websocket.WebSocketImpl;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
/**
 * 即时通讯
 */
public class ChatServer extends WebSocketServer{
 public ChatServer(int port) throws UnknownHostException {
 super(new InetSocketAddress(port));
 }
 public ChatServer(InetSocketAddress address) {
 super(address);
 }
 /**
 * 触发连接事件
 */
 @Override
 public void onOpen( WebSocket conn, ClientHandshake handshake ) {
 }
 /**
 * 触发关闭事件
 */
 @Override
 public void onClose( WebSocket conn, int code, String reason, boolean remote ) {
 userLeave(conn);
 }
 /**
 * 客户端发送消息到服务器时触发事件
 */
 @Override
 public void onMessage(WebSocket conn, String message){
 message = message.toString();
 if(null != message && message.startsWith("admin")){
 this.userjoin(message.replaceFirst("admin", ""),conn);
 }if(null != message && message.startsWith("LeaveAdmin")){
 this.userLeave(conn);
 }if(null != message && message.contains("admin886")){
 String toUser = message.substring(message.indexOf("admin886")+8, message.indexOf("admin888"));
 message = message.substring(0, message.indexOf("admin886")) +"[私信] "+ message.substring(message.indexOf("admin888")+8, message.length());
 ChatServerPool.sendMessageToUser(ChatServerPool.getWebSocketByUser(toUser),message);//向所某用户发送消息
 ChatServerPool.sendMessageToUser(conn, message);//同时向本人发送消息
 }else{
 ChatServerPool.sendMessage(message.toString());//向所有在线用户发送消息
 }
 }
 public void onFragment( WebSocket conn, Framedata fragment ) {
 }
 /**
 * 触发异常事件
 */
 @Override
 public void onError( WebSocket conn, Exception ex ) {
 ex.printStackTrace();
 if( conn != null ) {
 //some errors like port binding failed may not be assignable to a specific websocket
 }
 }
 /**
 * 用户加入处理
 * @param user
 */
 public void userjoin(String user, WebSocket conn){
 JSONObject result = new JSONObject();
 result.element("type", "user_join");
 result.element("user", "<a onclick=\"toUserMsg('"+user+"');\">"+user+"</a>");
 ChatServerPool.sendMessage(result.toString()); //把当前用户加入到所有在线用户列表中
 String joinMsg = "{\"from\":\"[系统]\",\"content\":\""+user+"上线了\",\"timestamp\":"+new Date().getTime()+",\"type\":\"message\"}";
 ChatServerPool.sendMessage(joinMsg); //向所有在线用户推送当前用户上线的消息
 result = new JSONObject();
 result.element("type", "get_online_user");
 ChatServerPool.addUser(user,conn); //向连接池添加当前的连接对象
 result.element("list", ChatServerPool.getOnlineUser());
 ChatServerPool.sendMessageToUser(conn, result.toString()); //向当前连接发送当前在线用户的列表
 }
 /**
 * 用户下线处理
 * @param user
 */
 public void userLeave(WebSocket conn){
 String user = ChatServerPool.getUserByKey(conn);
 boolean b = ChatServerPool.removeUser(conn); //在连接池中移除连接
 if(b){
 JSONObject result = new JSONObject();
 result.element("type", "user_leave");
 result.element("user", "<a onclick=\"toUserMsg('"+user+"');\">"+user+"</a>");
 ChatServerPool.sendMessage(result.toString()); //把当前用户从所有在线用户列表中删除
 String joinMsg = "{\"from\":\"[系统]\",\"content\":\""+user+"下线了\",\"timestamp\":"+new Date().getTime()+",\"type\":\"message\"}";
 ChatServerPool.sendMessage(joinMsg); //向在线用户发送当前用户退出的消息
 }
 }
 public static void main( String[] args ) throws InterruptedException , IOException {
 WebSocketImpl.DEBUG = false;
 int port = 8887; //端口
 ChatServer s = new ChatServer(port);
 s.start();
 System.out.println( "服务器的端口" + s.getPort() );
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

ChatServerPool.java:

package com.appms.websocket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.java_websocket.WebSocket;
/**
 * 即时通讯
 */
public class ChatServerPool {
 private static final Map<WebSocket,String> userconnections = new HashMap<WebSocket,String>();
 /**
 * 获取用户名
 * @param session
 */
 public static String getUserByKey(WebSocket conn){
 return userconnections.get(conn);
 }
 /**
 * 获取WebSocket
 * @param user
 */
 public static WebSocket getWebSocketByUser(String user){
 Set<WebSocket> keySet = userconnections.keySet();
 synchronized (keySet) {
 for (WebSocket conn : keySet) {
 String cuser = userconnections.get(conn);
 if(cuser.equals(user)){
 return conn;
 }
 }
 }
 return null;
 }
 /**
 * 向连接池中添加连接
 * @param inbound
 */
 public static void addUser(String user, WebSocket conn){
 userconnections.put(conn,user); //添加连接
 }
 /**
 * 获取所有的在线用户
 * @return
 */
 public static Collection<String> getOnlineUser(){
 List<String> setUsers = new ArrayList<String>();
 Collection<String> setUser = userconnections.values();
 for(String u:setUser){
 setUsers.add("<a onclick=\"toUserMsg('"+u+"');\">"+u+"</a>");
 }
 return setUsers;
 }
 /**
 * 移除连接池中的连接
 * @param inbound
 */
 public static boolean removeUser(WebSocket conn){
 if(userconnections.containsKey(conn)){
 userconnections.remove(conn); //移除连接
 return true;
 }else{
 return false;
 }
 }
 /**
 * 向特定的用户发送数据
 * @param user
 * @param message
 */
 public static void sendMessageToUser(WebSocket conn,String message){
 if(null != conn && null != userconnections.get(conn)){
 conn.send(message);
 }
 }
 /**
 * 向所有的用户发送消息
 * @param message
 */
 public static void sendMessage(String message){
 Set<WebSocket> keySet = userconnections.keySet();
 synchronized (keySet) {
 for (WebSocket conn : keySet) {
 String user = userconnections.get(conn);
 if(user != null){
 conn.send(message);
 }
 }
 }
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

写个过滤器,在项目执行时启动:

package com.appms.filter;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.java_websocket.WebSocketImpl;
import com.appms.base.BaseController;
import com.appms.base.Const;
import com.appms.utils.Tools;
import com.appms.websocket.ChatServer;
import com.appms.websocket.OnlineChatServer;
public class StartFilter extends BaseController implements Filter{
 /**
 * 初始化
 */
 public void init(FilterConfig fc) throws ServletException {
 this.startWebsocketInstantMsg();
 this.startWebsocketOnline();
 }
 /**
 * 启动即时聊天服务
 */
 public void startWebsocketInstantMsg(){
 WebSocketImpl.DEBUG = false;
 ChatServer s = null;
 try {
 String strWEBSOCKET = Tools.readTxtFile(Const.WEBSOCKET);//读取WEBSOCKET配置,获取端口配置
 if(null != strWEBSOCKET && !"".equals(strWEBSOCKET)){
 String strIW[] = strWEBSOCKET.split(",fh,");
 if(strIW.length == 4){
 s = new ChatServer(Integer.parseInt(strIW[1]));
 s.start();
 }
 }
 System.out.println( "websocket服务器启动,端口" + s.getPort() );
 } catch (UnknownHostException e) {
 e.printStackTrace();
 }
 }
 /**
 * 启动在线管理服务
 */
 public void startWebsocketOnline(){
 WebSocketImpl.DEBUG = false;
 OnlineChatServer s = null;
 try {
 String strWEBSOCKET = Tools.readTxtFile(Const.WEBSOCKET);//读取WEBSOCKET配置,获取端口配置
 if(null != strWEBSOCKET && !"".equals(strWEBSOCKET)){
 String strIW[] = strWEBSOCKET.split(",fh,");
 if(strIW.length == 4){
 s = new OnlineChatServer(Integer.parseInt(strIW[3]));
 s.start();
 }
 }
 System.out.println( "websocket服务器启动,端口" + s.getPort() );
 } catch (UnknownHostException e) {
 e.printStackTrace();
 }
 }
 //计时器
 public void timer() {
 Calendar calendar = Calendar.getInstance();
 calendar.set(Calendar.HOUR_OF_DAY, 9); // 控制时
 calendar.set(Calendar.MINUTE, 0); // 控制分
 calendar.set(Calendar.SECOND, 0); // 控制秒
 Date time = calendar.getTime(); // 得出执行任务的时间
 Timer timer = new Timer();
 timer.scheduleAtFixedRate(new TimerTask() {
 public void run() {
 //PersonService personService = (PersonService)ApplicationContext.getBean("personService");
 }
 }, time, 1000*60*60*24);// 这里设定将延时每天固定执行
 }
 public void destroy() {
 // TODO Auto-generated method stub
 }
 public void doFilter(ServletRequest arg0, ServletResponse arg1,
 FilterChain arg2) throws IOException, ServletException {
 // TODO Auto-generated method stub
 }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

在web.xml里配置:

 <filter>
 <filter-name>startFilter</filter-name>
 <filter-class>com.appms.filter.StartFilter</filter-class>
 </filter>
1
2
3
4

在jsp页面进行调用:

 <script type="text/javascript">var wimadress="127.0.0.1:8887";</script>
 <script type="text/javascript">var oladress="127.0.0.1:8889";</script>
 <link rel="stylesheet" type="text/css" href="plugins/websocket/ext4/resources/css/ext-all.css">
 <link rel="stylesheet" type="text/css" href="plugins/websocket/css/websocket.css" />
 <script type="text/javascript" src="plugins/websocket/ext4/ext-all-debug.js"></script>
 <script type="text/javascript" src="plugins/websocket/websocket.js"></script>
 <!--引入属于此页面的js -->
 <script type="text/javascript" src="source/js/jquery-1.8.3.js"></script>
1
2
3
4
5
6
7
8
9

点击li标签跳出聊天页面

ul class="am-avg-sm-1 am-avg-md-4 am-margin am-padding am-text-center admin-content-list ">
 <li onclick="creatw();"><a href="javascript:;"><span class="am-icon-btn am-icon-file-text"></span><br/>即时通讯<br/></a></li>
 <li><a href="fusioncharts/index.do" class="am-text-warning"><span class="am-icon-btn am-icon-briefcase"></span><br/>图表统计<br/></a></li>
 <li><a href="#" class="am-text-danger"><span class="am-icon-btn am-icon-recycle"></span><br/>昨日访问<br/>80082</a></li>
 <li><a href="#" class="am-text-secondary"><span class="am-icon-btn am-icon-user-md"></span><br/>在线用户<br/>3000</a></li>
 </ul>
1
2
3
4
5
6

私聊:


群聊:


基于ExtJS前端框架的Websocket即时通讯系统

Tags:

最近发表
标签列表