pr:增加webSocket支持

This commit is contained in:
抓蛙师 2023-03-30 12:18:47 +08:00
parent b4cf1dbb6d
commit ce8c038653
6 changed files with 293 additions and 1 deletions

View File

@ -83,6 +83,11 @@
<!-- 依赖声明 --> <!-- 依赖声明 -->
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- SpringBoot的依赖配置--> <!-- SpringBoot的依赖配置-->
<dependency> <dependency>

View File

@ -17,6 +17,11 @@
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>

View File

@ -0,0 +1,150 @@
package com.ruoyi.websocket;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserType;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
/*
*@WebSocket
*@author ye
*@create 2023/3/30 9:45
*/
@Slf4j
@Component
@ServerEndpoint("/webSocket/{token}")
public class WebSocket {
/*
* 存储session集合
* */
private static ConcurrentHashMap<Long, Session> sessionMap = new ConcurrentHashMap<>();
/**
* 存储用户集合
*/
private static ConcurrentHashMap<Long, LoginUser> userMap = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session, @PathParam(value = "token") String token){
System.out.println("【webSocket连接成功】token为" + token);
LoginUser loginUser = LoginHelper.getLoginUser(token);
if (ObjectUtil.isNull(loginUser)) {
log.error("token失效或无法解析");
}
setMap(session, loginUser);
}
private void setMap(Session session, LoginUser loginUser) {
//获取用户id
Long userId = loginUser.getUserId();
//存储会话到会话集合
sessionMap.put(userId, session);
//存储用户信息到用户集合
userMap.put(userId, loginUser);
//获取会话大小 即在线人数
int size = sessionMap.size();
log.warn("用户连接:{},昵称:{},当前在线人数为:{}", userId, loginUser.getUsername(), size);
}
@OnClose
public void onClose(Session session){
System.out.println("【webSocket退出成功】" );
removeMap(session);
}
private void removeMap(Session session) {
Long userId = getUserIdBySession(session);
if (ObjectUtil.isNull(userId)) {
return;
}
sessionMap.remove(userId);
userMap.remove(userId);
}
private Long getUserIdBySession(Session session) {
for (Long userId : sessionMap.keySet()) {
if (sessionMap.get(userId).getId().equals(session.getId())) {
return userId;
}
}
return null;
}
@OnError
public void onError(Session session, Throwable throwable){
System.out.println("error:");
throwable.printStackTrace();
}
@OnMessage
public void onMessage(Session session, String message){
System.out.println("【webSocket接收成功】内容为" + message);
LoginUser loginUser = getUserBySession(session);
if (ObjectUtil.isNull(loginUser)) {
return;
}
if (UserType.SYS_USER.getUserType().equals(loginUser.getUserType())) {
//系统用户
handlePCMsg(loginUser, message);
}else {
//app
handleAPPMsg(loginUser, message);
}
}
private void handleAPPMsg(LoginUser loginUser, String message) {
log.info("APP用户{},消息:", loginUser.getUsername(), message);
}
private void handlePCMsg(LoginUser loginUser, String message) {
log.info("系统用户:{},消息:", loginUser.getUsername(), message);
}
private LoginUser getUserBySession(Session session) {
Long userId = getUserIdBySession(session);
if (ObjectUtil.isNull(userId)) {
return null;
}
return userMap.get(userId);
}
/**
* 发送自定义消息
*/
public static void sendInfo(String message, Long toUserId) {
log.info("发送消息到:{},消息内容:{}", toUserId, message);
if (ObjectUtil.isNull(toUserId) || StringUtils.isBlank(message)) {
log.error("消息体不完整");
return;
}
if (sessionMap.contains(toUserId)) {
try {
sendMessage(sessionMap.get(toUserId), message);
} catch (Exception e) {
log.error("发送给用户{}的消息出错", toUserId);
}
}else {
//用户不在线
log.error("用户:{}不在线", toUserId);
//后续处理
}
}
public static void sendMessage(Session session, String message) throws IOException {
session.getBasicRemote().sendText(message);
}
}

View File

@ -0,0 +1,19 @@
package com.ruoyi.websocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/*
*@开启WebSocket支持
*@author ye
*@create 2023/3/30 9:43
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

View File

@ -1,5 +1,8 @@
<template> <template>
<div class="navbar"> <div class="navbar">
<WebSocket></WebSocket>
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/> <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
@ -56,6 +59,7 @@ import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch' import Search from '@/components/HeaderSearch'
import RuoYiGit from '@/components/RuoYi/Git' import RuoYiGit from '@/components/RuoYi/Git'
import RuoYiDoc from '@/components/RuoYi/Doc' import RuoYiDoc from '@/components/RuoYi/Doc'
import WebSocket from './WebSocket'
export default { export default {
components: { components: {
@ -66,7 +70,8 @@ export default {
SizeSelect, SizeSelect,
Search, Search,
RuoYiGit, RuoYiGit,
RuoYiDoc RuoYiDoc,
WebSocket
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([

View File

@ -0,0 +1,108 @@
<template>
<div>
</div>
</template>
<script>
import { getToken } from '@/utils/auth'
export default {
name: "WebSocket",
data() {
return {
webSocket: undefined,
wsUri: undefined,
lockReconnect: false,//
timeout: 60 * 1000,//60
timeoutObj:undefined,//
serverTimeoutObj:undefined,//
timeoutNum:undefined,//
};
},
created() {
this.initWebSocket();
},
methods: {
initWebSocket() {
this.initWebSocketUri();
//
if (typeof (WebSocket) == "undefined") {
console.log("你的浏览器不支持WebSocket");
}else {
this.webSocket = new WebSocket(this.wsUri);
console.log("this.websocket", this.webSocket);
this.webSocket.onopen = this.webSocketOnopen;
this.webSocket.onerror = this.webSocketOnerror;
this.webSocket.onmessage = this.webSocketOnmessage;
this.webSocket.onclose = this.webSocketOnclose;
}
},
initWebSocketUri() {
this.wsUri = "ws://127.0.0.1:8080/webSocket/" + getToken();
},
webSocketOnopen() {
console.log("连接成功");
this.start();
},
webSocketOnerror() {
console.log("出错")
this.reconnect();
},
webSocketOnmessage(res) {
console.log("接收消息",res)
this.reset();
},
webSocketOnclose() {
console.log("关闭连接")
this.reconnect();
},
reset() {
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
//
this.start();
},
//
start() {
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj= setTimeout(() => {
if (this.webSocket.readyState === 1) {
this.webSocketSend("heartCheck");
}else {
this.reconnect();
}
this.serverTimeoutObj = setTimeout(() => {
this.webSocket.close();
}, this.timeout);
}, this.timeout);
},
webSocketSend(msg) {
this.webSocket.send(msg)
},
reconnect() {
if (this.lockReconnect) {
return;
}
this.lockReconnect = true;
this.timeoutNum && clearTimeout(this.timeoutNum);
this.timeoutNum = setTimeout(() => {
this.initWebSocket();
this.lockReconnect = false;
}, 5000);
},
},
}
</script>
<style scoped lang="scss">
</style>