WebSocket實現聊天室業務的具體代碼,供大家參考,具體內容如下
頁面效果圖
pom.xml
主要是spring-boot-starter-websocket包,websocket連接、發送信息。
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
|
< dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-web</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-websocket</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-thymeleaf</ artifactId > </ dependency > < dependency > <!--Webjars版本定位工具--> < groupId >org.webjars</ groupId > < artifactId >webjars-locator-core</ artifactId > </ dependency > < dependency > < groupId >org.webjars.npm</ groupId > < artifactId >mdui</ artifactId > < version >0.4.0</ version > </ dependency > < dependency > < groupId >org.webjars</ groupId > < artifactId >jquery</ artifactId > < version >3.3.1</ version > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-devtools</ artifactId > < scope >runtime</ scope > </ dependency > < dependency > < groupId >com.alibaba</ groupId > < artifactId >fastjson</ artifactId > < version >1.2.49</ version > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency > |
前臺
html + js
websocket 前臺主要包括四種方法:
- 打開連接:onopen
- 服務端發來消息:1.廣播消息 2.更新在線人數 : onmessage
- 關閉連接 :onclose
- 通信失敗 :onerror
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
|
<!DOCTYPE html> < html xmlns:th = "http://www.thymeleaf.org" > < head > < title >WebSocket簡單聊天室</ title > < meta charset = "utf-8" name = "viewport" content = "width=device-width" > < link rel = "stylesheet" th:href = "@{/webjars/mdui/dist/css/mdui.css}" > < script th:src = "@{/webjars/jquery/jquery.min.js}" ></ script > < script th:src = "@{/webjars/mdui/dist/js/mdui.js}" ></ script > </ head > < body class = "mdui-theme-primary-indigo mdui-theme-accent-pink" > < div class = "mdui-container" > < div class = "mdui-toolbar mdui-color-theme" > < a class = "mdui-btn mdui-btn-icon" >< i class = "mdui-icon material-icons" >menu</ i ></ a > < span class = "mdui-typo-title" >簡單聊天室</ span > < div class = "mdui-toolbar-spacer" ></ div > < a class = "mdui-btn mdui-btn-icon" href = "https://www.jianshu.com/p/964370d9374e" target = "_blank" >< i class = "mdui-icon material-icons" >search</ i ></ a > < a class = "mdui-btn mdui-btn-icon" th:href = "@{/}" >< i class = "mdui-icon material-icons" >exit_to_app</ i ></ a > < a class = "mdui-btn mdui-btn-icon" >< i class = "mdui-icon material-icons" >more_vert</ i ></ a > </ div > </ div > < div > < div class = "mdui-container container_text" > < div class = "mdui-row" > < div class = "mdui-col-xs-12 mdui-col-sm-6" > < div class = "mdui-col-xs-12 mdui-col-sm-10" > < div class = "mdui-textfield-floating-label" style = "margin-top:15px" > < i class = "mdui-icon material-icons" >歡迎:</ i > < i class = "mdui-icon" id = "username" th:text = "${username}" ></ i > </ div > </ div > < div class = "mdui-col-xs-12 mdui-col-sm-10" > < div class = "mdui-textfield mdui-textfield-floating-label" > < i class = "mdui-icon material-icons" >textsms</ i > < label class = "mdui-textfield-label" >發送內容</ label > < input class = "mdui-textfield-input" id = "msg" /> </ div > < div class = "mdui-container" style = "padding:20px 35px" > < button class = "mdui-btn mdui-color-theme-accent mdui-ripple" onclick = "sendMsgToServer()" >發送 (enter) </ button > < button class = "mdui-btn mdui-color-theme mdui-ripple" onclick = "clearMsg()" >清屏 </ button > </ div > </ div > </ div > < div class = "mdui-col-xs-6 mdui-col-sm-5" style = "padding:10px 0" > < div class = "mdui-chip" > < span class = "mdui-chip-icon mdui-color-blue" > < i class = "mdui-icon material-icons" ></ i ></ span > < span class = "mdui-chip-title" >聊天內容</ span > </ div > < div class = "mdui-chip" > < span class = "mdui-chip-icon mdui-color-blue" > < i class = "mdui-icon material-icons" >face</ i ></ span > < span class = "mdui-chip-title" >在線人數</ span > < span class = "mdui-chip-title chat-num" >0</ span > </ div > < div class = "message-container" > </ div > </ div > </ div > </ div > </ div > < script th:inline = "javascript" > /** * WebSocket客戶端 * * 使用說明: * 1、WebSocket客戶端通過回調函數來接收服務端消息。例如:webSocket.onmessage * 2、WebSocket客戶端通過send方法來發送消息給服務端。例如:webSocket.send(); */ function getWebSocket() { /** * WebSocket客戶端 PS:URL開頭表示WebSocket協議 中間是域名端口 結尾是服務端映射地址 */ var webSocket = new WebSocket(/*[[${webSocketUrl}]]*/ 'ws://localhost:8080/chat'); /** * 當服務端打開連接 */ webSocket.onopen = function (event) { console.log('WebSocket打開連接'); }; /** * 當服務端發來消息:1.廣播消息 2.更新在線人數 */ webSocket.onmessage = function (event) { console.log('WebSocket收到消息:%c' + event.data, 'color:green'); //獲取服務端消息 var message = JSON.parse(event.data) || {}; var $messageContainer = $('.message-container'); //喉嚨發炎 if (message.type === 'SPEAK') { $messageContainer.append( '< div class = "mdui-card" style = "margin: 10px 0;" >' + '< div class = "mdui-card-primary" >' + '< div class = "mdui-card-content message-content" >' + message.username + ":" + message.msg + '</ div >' + '</ div ></ div >'); } $('.chat-num').text(message.onlineCount); //防止刷屏 var $cards = $messageContainer.children('.mdui-card:visible').toArray(); if ($cards.length > 5) { $cards.forEach(function (item, index) { index < $cards.length - 5 && $(item).slideUp('fast'); }); } }; /** * 關閉連接 */ webSocket.onclose = function (event) { console.log('WebSocket關閉連接'); }; /** * 通信失敗 */ webSocket.onerror = function (event) { console.log('WebSocket發生異常'); }; return webSocket; } var webSocket = getWebSocket(); /** * 通過WebSocket對象發送消息給服務端 */ function sendMsgToServer() { var $message = $('#msg'); if ($message.val()) { webSocket.send(JSON.stringify({username: $('#username').text(), msg: $message.val()})); $message.val(null); } } /** * 清屏 */ function clearMsg() { $(".message-container").empty(); } /** * 使用ENTER發送消息 */ document.onkeydown = function (event) { var e = event || window.event || arguments.callee.caller.arguments[0]; e.keyCode === 13 && sendMsgToServer(); }; </ script > </ body > </ html > |
后臺
WebSocketChatApplication - 啟動類
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
|
@SpringBootApplication @RestController public class WebSocketChatApplication { /** * 登陸界面 */ @GetMapping ( "/" ) public ModelAndView login() { return new ModelAndView( "/login" ); } /** * 聊天界面 */ @GetMapping ( "/index" ) public ModelAndView index(String username, String password, HttpServletRequest request) throws UnknownHostException { if (StringUtils.isEmpty(username)) { username = "匿名用戶" ; } ModelAndView mav = new ModelAndView( "/chat" ); mav.addObject( "username" , username); mav.addObject( "webSocketUrl" , "ws://" +InetAddress.getLocalHost().getHostAddress()+ ":" +request.getServerPort()+request.getContextPath()+ "/chat" ); return mav; } public static void main(String[] args) { SpringApplication.run(WebSocketChatApplication. class , args); } } |
WebSocketConfig - WebSocket配置類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Configuration public class WebSocketConfig { /** * 用于掃描和注冊所有攜帶ServerEndPoint注解的實例。 * <p> * PS:若部署到外部容器 則無需提供此類。 */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } |
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
|
/** * WebSocket 聊天消息類 */ public class Message { public static final String ENTER = "ENTER" ; public static final String SPEAK = "SPEAK" ; public static final String QUIT = "QUIT" ; private String type; //消息類型 private String username; //發送人 private String msg; //發送消息 private int onlineCount; //在線用戶數 public static String jsonStr(String type, String username, String msg, int onlineTotal) { return JSON.toJSONString( new Message(type, username, msg, onlineTotal)); } public Message(String type, String username, String msg, int onlineCount) { this .type = type; this .username = username; this .msg = msg; this .onlineCount = onlineCount; } public static String getENTER() { return ENTER; } public static String getSPEAK() { return SPEAK; } public static String getQUIT() { return QUIT; } public String getType() { return type; } public void setType(String type) { this .type = type; } public String getUsername() { return username; } public void setUsername(String username) { this .username = username; } public String getMsg() { return msg; } public void setMsg(String msg) { this .msg = msg; } public int getOnlineCount() { return onlineCount; } public void setOnlineCount( int onlineCount) { this .onlineCount = onlineCount; } } |
WebSocketChatServer - 聊天服務端
前臺對應的四種傳輸,后臺進行處理操作
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
|
/** * WebSocket 聊天服務端 * * @see ServerEndpoint WebSocket服務端 需指定端點的訪問路徑 * @see Session WebSocket會話對象 通過它給客戶端發送消息 */ @Component @ServerEndpoint ( "/chat" ) public class WebSocketChatServer { /** * 全部在線會話 PS: 基于場景考慮 這里使用線程安全的Map存儲會話對象。 */ private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>(); /** * 當客戶端打開連接:1.添加會話對象 2.更新在線人數 */ @OnOpen public void onOpen(Session session) { onlineSessions.put(session.getId(), session); sendMessageToAll(Message.jsonStr(Message.ENTER, "" , "" , onlineSessions.size())); } /** * 當客戶端發送消息:1.獲取它的用戶名和消息 2.發送消息給所有人 * <p> * PS: 這里約定傳遞的消息為JSON字符串 方便傳遞更多參數! */ @OnMessage public void onMessage(Session session, String jsonStr) { Message message = JSON.parseObject(jsonStr, Message. class ); sendMessageToAll(Message.jsonStr(Message.SPEAK, message.getUsername(), message.getMsg(), onlineSessions.size())); } /** * 當關閉連接:1.移除會話對象 2.更新在線人數 */ @OnClose public void onClose(Session session) { onlineSessions.remove(session.getId()); sendMessageToAll(Message.jsonStr(Message.QUIT, "" , "" , onlineSessions.size())); } /** * 當通信發生異常:打印錯誤日志 */ @OnError public void onError(Session session, Throwable error) { error.printStackTrace(); } /** * 公共方法:發送信息給所有人 */ private static void sendMessageToAll(String msg) { onlineSessions.forEach((id, session) -> { try { session.getBasicRemote().sendText(msg); } catch (IOException e) { e.printStackTrace(); } }); } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/weixin_45395031/article/details/107497176