spring boot整合WebSocket实现群聊功能 通俗易懂教程
- 首先获取消息的内容,即payload。
- 将payload转换为JSONObject对象,并从中获取消息类型type。
- 如果消息类型是"join",则从消息中获取群组ID,并将当前WebSocketSession的ID加入到该群组对应的Set中。
- 如果消息类型是"leave",则从消息中获取群组ID,并从该群组对应的Set中移除当前WebSocketSession的ID。
- 如果消息类型是"message",则从消息中获取群组ID,并获取该群组对应的所有WebSocketSession,逐一向这些Session发送消息。
其中,groups和sessions是两个Map,分别用来存储群组与其对应的WebSocketSessions。computeIfAbsent和computeIfPresent方法分别用来向Map中添加元素和更新元素。sendMessage方法用来向客户端发送消息。
导入依赖
<!-- spring-boot-starter-websocket依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
创建MyWebSocketHandler类
import com.songzixain.service.MyWebSocketHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* <p>
* Description: WebSocketConfig配置类
* </p>
*
* @author songzixian
* @version v2.0.0
* @create 2023-03-11 15:57
* @see com.songzixain.config
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyWebSocketHandler(), "/ws").setAllowedOrigins("*");
创建MyWebSocketHandler类
这段代码是一个WebSocket处理器中的消息处理方法,用来处理WebSocket客户端发送的消息
/**
* <p>
* Description: MyWebSocketHandler用 来处理WebSocket客户端发送的消息
* </p>
*
* @author songzixian
* @version v2.0.0
* @create 2023-03-11 22:44
* @see com.songzixain.service
*/
@Slf4j
public class MyWebSocketHandler implements WebSocketHandler {
private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
private static final Map<String, Set<String>> groups = new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessions.put(session.getId(), session);
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
String payload = message.getPayload().toString();
log.info("接收到的用户消息 {}", payload);
JSONObject json = JSON.parseObject(payload);
String type = json.getString("type");
// 用户加入了群组
if ("join".equals(type)) {
String groupId = json.getString("groupId");
groups.computeIfAbsent(groupId, k -> new HashSet<>()).add(session.getId());
} else if ("leave".equals(type)) {
String groupId = json.getString("groupId");
groups.computeIfPresent(groupId, (k, v) -> {
v.remove(session.getId());
return v;
});
// 接收到了用户消息
} else if ("message".equals(type)) {
String groupId = json.getString("groupId");
Set<String> groupSessions = groups.get(groupId);
for (String sessionId : groupSessions) {
WebSocketSession s = sessions.get(sessionId);
if (s != null && s.isOpen()) {
s.sendMessage(new TextMessage(payload));
}
}
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
sessions.remove(session.getId());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
sessions.remove(session.getId());
groups.values().forEach(v -> v.remove(session.getId()));
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
前端的html测试页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Chat</title>
</head>
<body>
<div id="output"></div>
<input id="input" type="text" placeholder="Type your message">
<button id="send">Send</button>
<button id="join">Join Group</button>
<button id="leave">Leave Group</button>
<script>
var socket = new WebSocket("ws://localhost:8080/ws");
socket.onopen = function(event) {
console.log("WebSocket connected");
};
socket.onmessage = function(event) {
var message = event.data;
var output = document.getElementById("output");
var p = document.createElement("p");
p.innerText = message;
output.appendChild(p);
};
socket.onclose = function(event) {
console.log("WebSocket disconnected");
};
var sendButton = document.getElementById("send");
var input = document.getElementById("input");
var joinButton = document.getElementById("join");
var leaveButton = document.getElementById("leave");
sendButton.addEventListener("click", function() {
var message = {
userId: "1",
type: "message",
groupId: "group1",
content: input.value
};
socket.send(JSON.stringify(message));
input.value = "";
});
joinButton.addEventListener("click", function() {
var message = {
userId: "1",
type: "join",
groupId: "group1"
};
socket.send(JSON.stringify(message));
});
leaveButton.addEventListener("click", function() {
var message = {
userId: "1",
type: "leave",
groupId: "group1"
};
socket.send(JSON.stringify(message));
});
socket.onmessage = function(event) {
var message = event.data;
var output = document.getElementById("output");
var p = document.createElement("p");
p.innerText = message;
output.appendChild(p);
};
</script>
</body>
</html>
这个WebSocket处理器实现了群聊功能,并支持用户加入和离开群组时向群组中的其他用户发送通知。
启动Spring Boot项目.点击加入群主,然后就可以发送消息了