【SpringBoot】WebSocket在线聊天
生活随笔
收集整理的這篇文章主要介紹了
【SpringBoot】WebSocket在线聊天
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
先看一下頁面效果,有點簡單粗暴!哈哈哈哈哈,別介意.
本文參考:SpringBoot2.0集成WebSocket,實現后臺向前端推送信息

新建一個springboot項目

引入相關依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
<!--com.alibaba/fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!--websocket依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Java代碼
WebSocketConfig
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
PageController
@RestController
public class PageController {
@GetMapping("chat")
public ModelAndView toChat(){
return new ModelAndView("/chat");
}
}
WebSocketServer
@ServerEndpoint("/chat/{userName}")
@Component
@Slf4j
public class WebSocketServer {
/**靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。*/
private static int onlineCount = 0;
/**concurrent包的線程安全Set,用來存放每個客戶端對應的MyWebSocket對象。*/
private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
/**與某個客戶端的連接會話,需要通過它來給客戶端發送數據*/
private Session session;
/**接收userId*/
private String userName="";
/**
* @Description: 連接建立成功調用的方法
* @params: [session, userId]
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:13 PM
*/
@OnOpen
public void onOpen(Session session,@PathParam("userName") String userName) {
this.session = session;
this.userName=userName;
if(webSocketMap.containsKey(userName)){
webSocketMap.remove(userName);
webSocketMap.put(userName,this);
//加入set中
}else{
webSocketMap.put(userName,this);
//加入set中
addOnlineCount();
//在線數加1
}
log.info("用戶連接:"+userName+",當前在線人數為:" + getOnlineCount());
try {
sendMessage("{\"msg\":\"連接成功\"}");
} catch (IOException e) {
log.error("用戶:"+userName+",網絡異常!!!!!!");
}
}
/**
* @Description: 連接關閉調用的方法
* @params: []
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:13 PM
*/
@OnClose
public void onClose() {
if(webSocketMap.containsKey(userName)){
webSocketMap.remove(userName);
//從set中刪除
subOnlineCount();
}
log.info("用戶退出:"+userName+",當前在線人數為:" + getOnlineCount());
}
/**
* @Description: 收到客戶端消息后調用的方法
* @params: [message, session]
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:13 PM
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("用戶消息:"+userName+",報文:"+message);
//可以群發消息
//消息保存到數據庫、redis
if(StringUtils.isNotBlank(message)){
try {
//解析發送的報文
JSONObject jsonObject = JSON.parseObject(message);
//追加發送人(防止串改)
jsonObject.put("sender",this.userName);
String receiver=jsonObject.getString("receiver");
//傳送給對應toUserId用戶的websocket
if(StringUtils.isNotBlank(receiver)&&webSocketMap.containsKey(receiver)){
webSocketMap.get(receiver).sendMessage(jsonObject.toJSONString());
}else{
log.error("請求的receiver:"+receiver+"不在該服務器上");
//否則不在這個服務器上,發送到mysql或者redis
}
}catch (Exception e){
e.printStackTrace();
}
}
}
/**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("用戶錯誤:"+this.userName+",原因:"+error.getMessage());
error.printStackTrace();
}
/**
* 實現服務器主動推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* @Description: 發送消息
* @params: [message, userId]
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:09 PM
*/
public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException {
log.info("發送消息到:"+userId+",報文:"+message);
if(StringUtils.isNotBlank(userId)&&webSocketMap.containsKey(userId)){
webSocketMap.get(userId).sendMessage(message);
}else{
log.error("用戶"+userId+",不在線!");
}
}
/**
* @Description: 獲取在線人數
* @params: []
* @return: int
* @Author: wangxianlin
* @Date: 2020/5/9 9:09 PM
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* @Description: 在線人數+1
* @params: []
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:09 PM
*/
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
/**
* @Description: 在線人數-1
* @params: []
* @return: void
* @Author: wangxianlin
* @Date: 2020/5/9 9:09 PM
*/
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
前端HTMl
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-md12">
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 25px;">
<legend style="margin-left: 40%;">簡單粗暴的聊天界面</legend>
</fieldset>
<div class="grid-demo grid-demo-bg2" style="text-align: center">
<form class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">接收者</label>
<div class="layui-input-block">
<input type="text" id="receiver" lay-verify="title" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">發送者</label>
<div class="layui-input-block">
<input type="text" id="sender" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">消息</label>
<div class="layui-input-block">
<textarea placeholder="請輸入內容" class="layui-textarea" id="msg"></textarea>
</div>
</div>
<div class="layui-col-md12" style="margin-left: 4%">
<div class="layui-tab layui-tab-card" style="height: 200px;overflow: auto">
<fieldset class="layui-elem-field layui-field-title">
<legend>消息記錄</legend>
</fieldset>
<div id="msgDiv">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" class="layui-btn layui-btn-primary" onclick="establishConnection()">
建立連接
</button>
<button type="button" class="layui-btn layui-btn-primary" onclick="sendMessage()">發送消息
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<script type="text/javascript" th:src="@{/javascript/jquery-2.1.4.js}"></script>
<!--layui-->
<script type="text/javascript" th:src="@{/plugins/layui/layui.js}"></script>
JavaScript代碼
var socket;
if (typeof(WebSocket) == "undefined") {
console.log("您的瀏覽器不支持WebSocket");
} else {
/***建立連接*/
function establishConnection() {
var userName = $("#sender").val();
if (userName == '' || userName == null) {
alert("請輸入發送者");
return;
}
//實現化WebSocket對象,指定要連接的服務器地址與端口 建立連接
var socketUrl = "" + window.location.protocol + "http://" + window.location.host + "/chat/" + userName;
socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
if (socket != null) {
socket.close();
socket = null;
}
socket = new WebSocket(socketUrl);
//打開事件
socket.onopen = function () {
console.log("開始建立鏈接....")
};
//關閉事件
socket.onclose = function () {
console.log("websocket已關閉");
};
//發生了錯誤事件
socket.onerror = function () {
console.log("websocket發生了錯誤");
};
/**
* 接收消息
* @param msg
*/
socket.onmessage = function (msg) {
msg = JSON.parse(msg.data);
if (msg.msg != '連接成功') {
$("#msgDiv").append('<p class="user">用戶名:' + msg.sender + '</p><p class="chat">' + msg.msg + '</p>');
}
};
}
/**
* 發送消息
*/
function sendMessage() {
var msg = $("#msg").val();
if (msg == '' || msg == null) {
alert("消息內容不能為空");
return;
}
var receiver = $("#receiver").val();
if (receiver == '' || receiver == null) {
alert("接收人不能為空");
return;
}
var msgObj = {
receiver: receiver,
msg: msg
};
socket.send(JSON.stringify(msgObj));
}
}
總結
以上是生活随笔為你收集整理的【SpringBoot】WebSocket在线聊天的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gitlab docker升级报错
- 下一篇: Mybatis_plus笔记