預期效果
共開啟兩個頁面,實現(xiàn)一對一聊天。
服務端代碼:https://gitee.com/lianaozhe/springboot-websocket.git
代碼實現(xiàn)邏輯
服務端
導入相關(guān)依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- hutool 工具包,各種封裝功能 一應俱全-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
WebSocketConfig配置類:
package com.web.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @ClassName WebSocketConfig
* @Description TODO
* @Author laz
* @Date 2023/4/26 16:18
* @Version 1.0
*/
@Configuration
public class WebSocketConfig {
/**
* 注入ServerEndpointExporter,
* 這個bean會自動注冊使用了@ServerEndpoint注解聲明的Websocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
WebSocket操作類:
package com.web.websocket;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @ClassName WebSocket
* @Description TODO
* @Author laz
* @Date 2023/4/26 16:20
* @Version 1.0
*/
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {
//與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
private Session session;
/**
* 用戶ID
*/
private String userId;
/**
* 用來存放每個客戶端對應的MyWebSocket對象。
*/
private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();
// 用來存在線連接用戶信息
private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>();
/**
* 鏈接成功調(diào)用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam(value="userId")String userId) {
try {
this.session = session;
this.userId = userId;
webSockets.add(this);
sessionPool.put(userId, session);
log.info("【websocket消息】有新的連接,用戶id是【{}】總數(shù)為【{}】",userId,webSockets.size());
} catch (Exception e) {
}
}
/**
* 鏈接關(guān)閉調(diào)用的方法
*/
@OnClose
public void onClose() {
try {
webSockets.remove(this);
sessionPool.remove(this.userId);
log.info("【websocket消息】連接斷開,總數(shù)為:"+webSockets.size());
} catch (Exception e) {
}
}
/**
* 收到客戶端消息后調(diào)用的方法
*
* @param message
* @param message
*/
@OnMessage
public void onMessage(String message) {
log.info("【websocket消息】收到客戶端消息:"+message);
JSONObject jsonObject = JSONUtil.parseObj(message);
Object toUserId = jsonObject.get("toUserId");
Session session = sessionPool.get(toUserId);
session.getAsyncRemote().sendText(JSONUtil.toJsonStr(jsonObject.get("msg")));
}
/** 發(fā)送錯誤時的處理
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("用戶錯誤,原因:"+error.getMessage());
error.printStackTrace();
}
// 此為廣播消息
public void sendAllMessage(String message) {
log.info("【websocket消息】廣播消息:"+message);
for(WebSocket webSocket : webSockets) {
try {
if(webSocket.session.isOpen()) {
webSocket.session.getAsyncRemote().sendText(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 此為單點消息
public void sendOneMessage(String userId, String message) {
Session session = sessionPool.get(userId);
if (session != null&&session.isOpen()) {
try {
log.info("【websocket消息】 單點消息:"+message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 此為單點消息(多人)
public void sendMoreMessage(String[] userIds, String message) {
for(String userId:userIds) {
Session session = sessionPool.get(userId);
if (session != null&&session.isOpen()) {
try {
log.info("【websocket消息】 單點消息:"+message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
TestController測試接口類:
package com.web.controller;
import com.web.websocket.WebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName TestController
* @Description TODO
* @Author laz
* @Date 2023/4/26 16:23
* @Version 1.0
*/
@RestController
@RequestMapping("web")
public class TestController {
@Autowired
private WebSocket webSocket;
@RequestMapping("test")
public String test(String userId,String msg){
webSocket.sendOneMessage(userId,msg);
return "成功";
}
}
客戶端
test.html文件:
<!doctype html>
<html lang="zh-CN">
<head>
<!-- 必須的 meta 標簽 -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap 的 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<title>WebSocket1</title>
<style>
form {
width: 820px;
margin: auto;
}
.div1 {
width: 820px;
height: 500px;
border: #000000;
border-width: thin;
border-style: solid;
}
.div2 {
text-align: center;
width: 800px;
height: 50px;
}
</style>
<script>
function clearData() {
$("#div1").html("");
}
var socket;
function openSocket() {
if (typeof(WebSocket) == "undefined") {
console.log("您的瀏覽器不支持WebSocket");
} else {
console.log("您的瀏覽器支持WebSocket");
//websocket地址
var socketUrl = "ws://localhost:8088/websocket/20";
console.log(socketUrl);
if (socket != null) {
socket.close();
socket = null;
}
socket = new WebSocket(socketUrl);
//打開事件
socket.onopen = function() {
console.log("websocket已打開");
$("#div1").append("websocket已打開" + "<br \>");
};
//獲得消息事件
socket.onmessage = function(msg) {
console.log(msg.data);
$("#div1").append("接收到消息:" + msg.data + "<br \>");
};
//關(guān)閉事件
socket.onclose = function() {
console.log("websocket已關(guān)閉");
$("#div1").append("websocket已關(guān)閉" + "<br \>");
};
//發(fā)生了錯誤事件
socket.onerror = function() {
console.log("websocket發(fā)生了錯誤");
$("#div1").append("websocket發(fā)生了錯誤" + "<br \>");
}
}
}
function sendMsg() {
if (typeof(WebSocket) == "undefined") {
console.log("您的瀏覽器不支持WebSocket");
} else {
console.log("您的瀏覽器支持WebSocket");
console.log('{"toUserId":"' + $("#toUserId").val() + '","msg":"' + $("#msg").val() + '"}');
socket.send('{"toUserId":"' + $("#toUserId").val() + '","msg":"' + $("#msg").val() + '"}');
var msg = document.getElementById("msg").value;
$("#div1").append("發(fā)送消息:" + msg + "<br \>");
document.getElementById("msg").value = "";
}
}
</script>
</head>
<body>
<h1 align="center">WebSocket測試Demo</h1><br />
<form class="form-inline">
<div class="form-group mx-sm-3 mb-2">
<label for="toUserId" class="sr-only">toUserId</label>
<input type="text" class="form-control" id="toUserId" placeholder="toUserId">
</div>
<div class="form-group mb-2">
<label for="msg" class="sr-only">消息內(nèi)容</label>
<input type="text" class="form-control" id="msg" placeholder="消息內(nèi)容">
</div>
<div class="form-group mx-sm-3 mb-2">
<button type="button" class="btn btn-primary" onclick="openSocket()">開啟socket</button>
</div>
<div class="form-group mx-sm-3 mb-2">
<button type="button" class="btn btn-danger" onclick="sendMsg()">發(fā)送消息</button>
</div>
<div class="form-group mx-sm-3 mb-2">
<button type="button" class="btn btn-secondary" onclick="clearData()">清空內(nèi)容</button>
</div>
<div class="div2"></div>
<div class="div1" id="div1"></div>
</form>
</body>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-7ymO4nGrkm372HoSbq1OY2DP4pEZnMiA+E0F3zPr+JQQtQ82gQ1HPY3QIVtztVua" crossorigin="anonymous">
</script>
</html>
復制test.html文件為test2.html文件,將上面的userId由’20’改為’10’,后面測試使用。
測試
測試一
運行服務端項目,打開test.html,點擊’開啟socket’按鈕(一定要先開啟socket連接,否則無法接收到消息)。
可以看到,服務端與客戶端已建立了連接。
然后調(diào)用我們的測試接口:
然后觀察test.html頁面:
可以看到,客戶端的用戶20成功接收到服務端發(fā)來的信息。
測試二
打開test2.html,同樣點擊’開啟socket’,與服務端建立連接。
此時用test2.html給test.html發(fā)送一條消息。
可以看到,此時兩個頁面直接已經(jīng)可以進行一對一的聊天了。文章來源:http://www.zghlxwxcb.cn/news/detail-427703.html
代碼已上傳到git:https://gitee.com/lianaozhe/springboot-websocket.git文章來源地址http://www.zghlxwxcb.cn/news/detail-427703.html
到了這里,關(guān)于SpringBoot整合WebSocket詳細教程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!