Skip to content

Commit 5180469

Browse files
authored
Create README.md
1 parent 70c48df commit 5180469

File tree

1 file changed

+329
-0
lines changed

1 file changed

+329
-0
lines changed

springboot-websocket/README.md

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
# springboot整合websocket
2+
websocket最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。 浏览器和服务器只需要要做一个握手的动作,在建立连接之后,服务器可以主动传送数据给客户端,客户端也可以随时向服务器发送数据。
3+
4+
实现功能:springboot整合websocket实现一对一,多对多聊天系统
5+
6+
**支持作者就Star Mua~**
7+
8+
## 依赖
9+
```xml
10+
<dependency>
11+
<groupId>org.springframework.boot</groupId>
12+
<artifactId>spring-boot-starter-websocket</artifactId>
13+
</dependency>
14+
15+
其他的还用到了thymeleaf,lombok,fastjson,自己加一下
16+
```
17+
## 配置类
18+
```java
19+
/**
20+
* websocket的配置
21+
*/
22+
@Configuration
23+
public class WebSocketConfig {
24+
25+
@Bean
26+
public ServerEndpointExporter serverEndpointExporter() {
27+
return new ServerEndpointExporter();
28+
}
29+
}
30+
```
31+
## WebSocket
32+
```java
33+
@Slf4j
34+
@Component
35+
@ServerEndpoint("/websocket/{username}")
36+
public class WebSocket {
37+
38+
/**
39+
* 在线人数
40+
*/
41+
public static int onlineNumber = 0;
42+
/**
43+
* 以用户的姓名为key,WebSocket为对象保存起来
44+
*/
45+
private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
46+
/**
47+
* 会话
48+
*/
49+
private Session session;
50+
/**
51+
* 用户名称
52+
*/
53+
private String username;
54+
55+
/**
56+
* OnOpen 表示有浏览器链接过来的时候被调用
57+
* OnClose 表示浏览器发出关闭请求的时候被调用
58+
* OnMessage 表示浏览器发消息的时候被调用
59+
* OnError 表示有错误发生,比如网络断开了等等
60+
*/
61+
62+
/**
63+
* 建立连接
64+
*
65+
* @param session
66+
*/
67+
@OnOpen
68+
public void onOpen(@PathParam("username") String username, Session session) {
69+
onlineNumber++;
70+
log.info("现在来连接的客户id:" + session.getId() + "用户名:" + username);
71+
this.username = username;
72+
this.session = session;
73+
log.info("有新连接加入! 当前在线人数" + onlineNumber);
74+
try {
75+
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
76+
//先给所有人发送通知,说我上线了
77+
Map<String, Object> map1 = new HashMap<>();
78+
map1.put("messageType", 1);
79+
map1.put("username", username);
80+
sendMessageAll(JSON.toJSONString(map1), username);
81+
82+
//把自己的信息加入到map当中去
83+
clients.put(username, this);
84+
//给自己发一条消息:告诉自己现在都有谁在线
85+
Map<String, Object> map2 = new HashMap<>();
86+
map2.put("messageType", 3);
87+
//移除掉自己
88+
Set<String> set = clients.keySet();
89+
map2.put("onlineUsers", set);
90+
sendMessageTo(JSON.toJSONString(map2), username);
91+
} catch (IOException e) {
92+
log.info(username + "上线的时候通知所有人发生了错误");
93+
}
94+
95+
96+
}
97+
98+
@OnError
99+
public void onError(Session session, Throwable error) {
100+
log.info("服务端发生了错误" + error.getMessage());
101+
//error.printStackTrace();
102+
}
103+
104+
/**
105+
* 连接关闭
106+
*/
107+
@OnClose
108+
public void onClose() {
109+
onlineNumber--;
110+
//webSockets.remove(this);
111+
clients.remove(username);
112+
try {
113+
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
114+
Map<String, Object> map1 = new HashMap<>();
115+
map1.put("messageType", 2);
116+
map1.put("onlineUsers", clients.keySet());
117+
map1.put("username", username);
118+
sendMessageAll(JSON.toJSONString(map1), username);
119+
} catch (IOException e) {
120+
log.info(username + "下线的时候通知所有人发生了错误");
121+
}
122+
log.info("有连接关闭! 当前在线人数" + onlineNumber);
123+
}
124+
125+
/**
126+
* 收到客户端的消息
127+
*
128+
* @param message 消息
129+
* @param session 会话
130+
*/
131+
@OnMessage
132+
public void onMessage(String message, Session session) {
133+
try {
134+
log.info("来自客户端消息:" + message + "客户端的id是:" + session.getId());
135+
JSONObject jsonObject = JSON.parseObject(message);
136+
String textMessage = jsonObject.getString("message");
137+
String fromusername = jsonObject.getString("username");
138+
String tousername = jsonObject.getString("to");
139+
//如果不是发给所有,那么就发给某一个人
140+
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
141+
Map<String, Object> map1 = new HashMap<>();
142+
map1.put("messageType", 4);
143+
map1.put("textMessage", textMessage);
144+
map1.put("fromusername", fromusername);
145+
if (tousername.equals("All")) {
146+
map1.put("tousername", "所有人");
147+
sendMessageAll(JSON.toJSONString(map1), fromusername);
148+
} else {
149+
map1.put("tousername", tousername);
150+
sendMessageTo(JSON.toJSONString(map1), tousername);
151+
}
152+
} catch (Exception e) {
153+
log.info("发生了错误了");
154+
}
155+
}
156+
157+
public void sendMessageTo(String message, String ToUserName) throws IOException {
158+
for (WebSocket item : clients.values()) {
159+
if (item.username.equals(ToUserName)) {
160+
item.session.getAsyncRemote().sendText(message);
161+
break;
162+
}
163+
}
164+
}
165+
166+
public void sendMessageAll(String message, String FromUserName) throws IOException {
167+
for (WebSocket item : clients.values()) {
168+
item.session.getAsyncRemote().sendText(message);
169+
}
170+
}
171+
172+
public static synchronized int getOnlineCount() {
173+
return onlineNumber;
174+
}
175+
176+
}
177+
```
178+
179+
## 控制器
180+
181+
```java
182+
@Slf4j
183+
@Controller
184+
public class WebSocketController {
185+
186+
@RequestMapping("/websocket/{name}")
187+
public String webSocket(@PathVariable String name, Model model) {
188+
try {
189+
log.info("跳转到websocket的页面上");
190+
model.addAttribute("username", name);
191+
return "websocket";
192+
} catch (Exception e) {
193+
log.info("跳转到websocket的页面上发生异常,异常信息是:" + e.getMessage());
194+
return "error";
195+
}
196+
}
197+
}
198+
```
199+
## html页面
200+
```html
201+
<!DOCTYPE html>
202+
<html xmlns:th="http://www.w3.org/1999/xhtml">
203+
<head>
204+
<title>websocket</title>
205+
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.min.js"></script>
206+
<script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
207+
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
208+
</head>
209+
210+
<body>
211+
<div style="margin: auto;text-align: center">
212+
<h1>Welcome to websocket</h1>
213+
</div>
214+
<br/>
215+
<div style="margin: auto;text-align: center">
216+
<select id="onLineUser">
217+
<option>--所有--</option>
218+
</select>
219+
<input id="text" type="text"/>
220+
<button onclick="send()">发送消息</button>
221+
</div>
222+
<br>
223+
<div style="margin-right: 10px;text-align: right">
224+
<button onclick="closeWebSocket()">关闭连接</button>
225+
</div>
226+
<hr/>
227+
<div id="message" style="text-align: center;"></div>
228+
<input type="text" th:value="${username}" id="username" style="display: none"/>
229+
</body>
230+
231+
232+
<script type="text/javascript">
233+
var webSocket;
234+
var commWebSocket;
235+
if ("WebSocket" in window) {
236+
webSocket = new WebSocket("ws://localhost:8080/websocket/" + document.getElementById('username').value);
237+
238+
//连通之后的回调事件
239+
webSocket.onopen = function () {
240+
//webSocket.send( document.getElementById('username').value+"已经上线了");
241+
console.log("已经连通了websocket");
242+
setMessageInnerHTML("已经连通了websocket");
243+
};
244+
245+
//接收后台服务端的消息
246+
webSocket.onmessage = function (evt) {
247+
var received_msg = evt.data;
248+
console.log("数据已接收:" + received_msg);
249+
var obj = JSON.parse(received_msg);
250+
console.log("可以解析成json:" + obj.messageType);
251+
//1代表上线 2代表下线 3代表在线名单 4代表普通消息
252+
if (obj.messageType == 1) {
253+
//把名称放入到selection当中供选择
254+
var onlineName = obj.username;
255+
var option = "<option>" + onlineName + "</option>";
256+
$("#onLineUser").append(option);
257+
setMessageInnerHTML(onlineName + "上线了");
258+
} else if (obj.messageType == 2) {
259+
$("#onLineUser").empty();
260+
var onlineName = obj.onlineUsers;
261+
var offlineName = obj.username;
262+
var option = "<option>" + "--所有--" + "</option>";
263+
for (var i = 0; i < onlineName.length; i++) {
264+
if (!(onlineName[i] == document.getElementById('username').value)) {
265+
option += "<option>" + onlineName[i] + "</option>"
266+
}
267+
}
268+
$("#onLineUser").append(option);
269+
270+
setMessageInnerHTML(offlineName + "下线了");
271+
} else if (obj.messageType == 3) {
272+
var onlineName = obj.onlineUsers;
273+
var option = null;
274+
for (var i = 0; i < onlineName.length; i++) {
275+
if (!(onlineName[i] == document.getElementById('username').value)) {
276+
option += "<option>" + onlineName[i] + "</option>"
277+
}
278+
}
279+
$("#onLineUser").append(option);
280+
console.log("获取了在线的名单" + onlineName.toString());
281+
} else {
282+
setMessageInnerHTML(obj.fromusername + "" + obj.tousername + "说:" + obj.textMessage);
283+
}
284+
};
285+
286+
//连接关闭的回调事件
287+
webSocket.onclose = function () {
288+
console.log("连接已关闭...");
289+
setMessageInnerHTML("连接已经关闭....");
290+
};
291+
} else {
292+
// 浏览器不支持 WebSocket
293+
alert("您的浏览器不支持 WebSocket!");
294+
}
295+
296+
//将消息显示在网页上
297+
function setMessageInnerHTML(innerHTML) {
298+
document.getElementById('message').innerHTML += innerHTML + '<br/>';
299+
}
300+
301+
function closeWebSocket() {
302+
//直接关闭websocket的连接
303+
webSocket.close();
304+
}
305+
306+
function send() {
307+
var selectText = $("#onLineUser").find("option:selected").text();
308+
if (selectText == "--所有--") {
309+
selectText = "All";
310+
} else {
311+
setMessageInnerHTML(document.getElementById('username').value + "" + selectText + "说:" + $("#text").val());
312+
}
313+
var message = {
314+
"message": document.getElementById('text').value,
315+
"username": document.getElementById('username').value,
316+
"to": selectText
317+
};
318+
webSocket.send(JSON.stringify(message));
319+
$("#text").val("");
320+
321+
}
322+
</script>
323+
324+
</html>
325+
326+
```
327+
## 效果图
328+
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190419190241179.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NzYyMjM3,size_16,color_FFFFFF,t_70)
329+
>特别感谢:https://blog.csdn.net/qq_38455201/article/details/80374712

0 commit comments

Comments
 (0)