1.修改WebSocketApi

2.修改Message模块WebSocket为Socket模块实现
pull/22/head
rays 2021-06-03 16:00:19 +08:00
parent 7858b13c29
commit 0fe4cbcd6b
34 changed files with 248 additions and 637 deletions

View File

@ -38,4 +38,10 @@ public interface SymbolConstant {
String RIGHT_SQUARE_BRACKETS = "]"; String RIGHT_SQUARE_BRACKETS = "]";
String DOLLAR = "$";
String PERCENT = "%";
String AND = "&";
} }

View File

@ -39,6 +39,12 @@
<version>${roses.version}</version> <version>${roses.version}</version>
</dependency> </dependency>
<!--WebSocket模块的Api-->
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>socket-api</artifactId>
<version>${roses.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -29,6 +29,7 @@ import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.auth.api.enums.DataScopeTypeEnum; import cn.stylefeng.roses.kernel.auth.api.enums.DataScopeTypeEnum;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.basic.SimpleRoleInfo; import cn.stylefeng.roses.kernel.auth.api.pojo.login.basic.SimpleRoleInfo;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.basic.SimpleUserInfo; import cn.stylefeng.roses.kernel.auth.api.pojo.login.basic.SimpleUserInfo;
import cn.stylefeng.roses.kernel.config.api.context.ConfigContext;
import cn.stylefeng.roses.kernel.rule.constants.RuleConstants; import cn.stylefeng.roses.kernel.rule.constants.RuleConstants;
import cn.stylefeng.roses.kernel.scanner.api.annotation.field.ChineseDescription; import cn.stylefeng.roses.kernel.scanner.api.annotation.field.ChineseDescription;
import lombok.Data; import lombok.Data;
@ -37,6 +38,8 @@ import java.io.Serializable;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import static cn.stylefeng.roses.kernel.socket.api.constants.SocketConstants.SOCKET_PORT;
/** /**
* *
* *
@ -162,9 +165,11 @@ public class LoginUser implements Serializable {
public String getWsUrl() { public String getWsUrl() {
AtomicReference<String> returnUrl = new AtomicReference<>(StrUtil.EMPTY); AtomicReference<String> returnUrl = new AtomicReference<>(StrUtil.EMPTY);
Integer socketPort = ConfigContext.me().getSysConfigValueWithDefault(SOCKET_PORT, Integer.class, 11130);
Optional.ofNullable(this.wsUrl).ifPresent(url -> { Optional.ofNullable(this.wsUrl).ifPresent(url -> {
Map<String, Long> user = new HashMap<>(1); Map<String, Long> user = new HashMap<>(1);
user.put("userId", this.userId); user.put("userId", this.userId);
user.put("port", Long.valueOf(socketPort));
returnUrl.set(StrUtil.format(url, user)); returnUrl.set(StrUtil.format(url, user));
}); });
return returnUrl.get(); return returnUrl.get();

View File

@ -1,5 +1,8 @@
package cn.stylefeng.roses.kernel.socket.api; package cn.stylefeng.roses.kernel.socket.api;
import cn.stylefeng.roses.kernel.socket.api.enums.ServerMessageTypeEnum;
import cn.stylefeng.roses.kernel.socket.api.message.SocketMsgCallbackInterface;
/** /**
* Socket * Socket
* <p> * <p>
@ -13,12 +16,12 @@ public interface SocketOperatorApi {
/** /**
* *
* *
* @param sessionId ID(IDWebSocket使formId) * @param userId ID
* @param msg * @param msg
* @author majianguo * @author majianguo
* @date 2021/6/2 9:35 * @date 2021/6/2 9:35
**/ **/
void sendMsgOfSession(String sessionId, Object msg); void sendMsgOfUserSession(ServerMessageTypeEnum msgType, String userId, Object msg);
/** /**
* *
@ -27,7 +30,7 @@ public interface SocketOperatorApi {
* @author majianguo * @author majianguo
* @date 2021/6/2 9:35 * @date 2021/6/2 9:35
**/ **/
void sendMsgOfAllSession(Object msg); void sendMsgOfAllUserSession(ServerMessageTypeEnum msgType, Object msg);
/** /**
* *

View File

@ -0,0 +1,35 @@
package cn.stylefeng.roses.kernel.socket.api.enums;
import lombok.Getter;
/**
*
*
* @author majianguo
* @date 2021/6/3 9:14
*/
@Getter
public enum ClientMessageTypeEnum {
/**
*
* <p>
*
*/
USER_ADD_MSG_TYPE("200001", "用户添加一个监听的消息类型"),
/**
*
*/
USER_HEART("299999", "用户心跳"),
;
private final String code;
private final String name;
ClientMessageTypeEnum(String code, String name) {
this.code = code;
this.name = name;
}
}

View File

@ -0,0 +1,28 @@
package cn.stylefeng.roses.kernel.socket.api.enums;
import lombok.Getter;
/**
*
*
* @author majianguo
* @date 2021/6/3 9:14
*/
@Getter
public enum ServerMessageTypeEnum {
/**
*
*/
SYS_NOTICE_MSG_TYPE("100001", "系统通知消息类型"),
;
private final String code;
private final String name;
ServerMessageTypeEnum(String code, String name) {
this.code = code;
this.name = name;
}
}

View File

@ -1,4 +1,4 @@
package cn.stylefeng.roses.kernel.socket.api; package cn.stylefeng.roses.kernel.socket.api.message;
import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession; import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession;

View File

@ -28,7 +28,7 @@ package cn.stylefeng.roses.kernel.socket.api.session;
* socket * socket
* <p> * <p>
* *
* WebSocket{@link cn.stylefeng.roses.kernel.socket.websocket.channel} * WebSocket{@link cn.stylefeng.roses.kernel.socket.websocket.operator.channel}
* *
* @author majianguo * @author majianguo
* @date 2021/6/1 11:46 * @date 2021/6/1 11:46

View File

@ -3,6 +3,7 @@ package cn.stylefeng.roses.kernel.socket.api.session.pojo;
import cn.stylefeng.roses.kernel.socket.api.session.SocketSessionOperatorApi; import cn.stylefeng.roses.kernel.socket.api.session.SocketSessionOperatorApi;
import lombok.Data; import lombok.Data;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
/** /**
@ -17,12 +18,12 @@ public class SocketSession<T extends SocketSessionOperatorApi> {
/** /**
* *
*/ */
private String sessionId; private String userId;
/** /**
* *
*/ */
private Set<String> messageTypes; private Set<String> messageTypes = new HashSet<>();
/** /**
* *

View File

@ -1,17 +1,28 @@
package cn.stylefeng.roses.kernel.socket.business.websocket.spring; package cn.stylefeng.roses.kernel.socket.business.websocket.spring;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.config.api.constants.ConfigConstants; import cn.stylefeng.roses.kernel.config.api.constants.ConfigConstants;
import cn.stylefeng.roses.kernel.config.api.context.ConfigContext; import cn.stylefeng.roses.kernel.config.api.context.ConfigContext;
import cn.stylefeng.roses.kernel.socket.api.SocketOperatorApi;
import cn.stylefeng.roses.kernel.socket.api.enums.ServerMessageTypeEnum;
import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession;
import cn.stylefeng.roses.kernel.socket.websocket.message.WebSocketMessagePOJO;
import cn.stylefeng.roses.kernel.socket.websocket.operator.channel.GettySocketOperator;
import cn.stylefeng.roses.kernel.socket.websocket.server.WebSocketServer; import cn.stylefeng.roses.kernel.socket.websocket.server.WebSocketServer;
import cn.stylefeng.roses.kernel.socket.websocket.session.SessionCenter;
import com.gettyio.core.channel.config.ServerConfig; import com.gettyio.core.channel.config.ServerConfig;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.net.StandardSocketOptions; import java.net.StandardSocketOptions;
import java.util.HashSet;
import java.util.List;
import static cn.stylefeng.roses.kernel.socket.api.constants.SocketConstants.*; import static cn.stylefeng.roses.kernel.socket.api.constants.SocketConstants.*;
import static cn.stylefeng.roses.kernel.socket.api.enums.ClientMessageTypeEnum.*;
/** /**
* Spring BootWebSocket * Spring BootWebSocket
@ -23,6 +34,9 @@ import static cn.stylefeng.roses.kernel.socket.api.constants.SocketConstants.*;
@Slf4j @Slf4j
public class WebSocketApplicationRunnerImpl implements ApplicationRunner { public class WebSocketApplicationRunnerImpl implements ApplicationRunner {
@Autowired
private SocketOperatorApi socketOperatorApi;
@Override @Override
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) throws Exception {
// 初始化配置对象 // 初始化配置对象
@ -48,5 +62,14 @@ public class WebSocketApplicationRunnerImpl implements ApplicationRunner {
WebSocketServer.run(aioServerConfig); WebSocketServer.run(aioServerConfig);
log.info("WebSocket Server Start Success!"); log.info("WebSocket Server Start Success!");
// 添加用户新增消息类型的回调
socketOperatorApi.msgTypeCallback(USER_ADD_MSG_TYPE.getCode(), (msgType, msg, socketSession) -> {
// 转换对象
WebSocketMessagePOJO webSocketMessage = (WebSocketMessagePOJO)msg;
// 维护会话中心的消息类型
SessionCenter.addSocketSessionMsgType(webSocketMessage.getData().toString(), webSocketMessage.getFormUserId());
});
} }
} }

View File

@ -1,6 +1,6 @@
package cn.stylefeng.roses.kernel.socket.websocket.message; package cn.stylefeng.roses.kernel.socket.websocket.message;
import cn.stylefeng.roses.kernel.socket.api.SocketMsgCallbackInterface; import cn.stylefeng.roses.kernel.socket.api.message.SocketMsgCallbackInterface;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -19,15 +19,15 @@ public class WebSocketMessagePOJO {
/** /**
* Id * Id
*/ */
private String toId; private String toUserId;
/** /**
* ID * ID
*/ */
private String formId; private String formUserId;
/** /**
* *
*/ */
private String data; private Object data;
} }

View File

@ -1,16 +1,20 @@
package cn.stylefeng.roses.kernel.socket.websocket.operator; package cn.stylefeng.roses.kernel.socket.websocket.operator;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.socket.api.SocketMsgCallbackInterface; import cn.stylefeng.roses.kernel.socket.api.message.SocketMsgCallbackInterface;
import cn.stylefeng.roses.kernel.socket.api.SocketOperatorApi; import cn.stylefeng.roses.kernel.socket.api.SocketOperatorApi;
import cn.stylefeng.roses.kernel.socket.api.enums.ServerMessageTypeEnum;
import cn.stylefeng.roses.kernel.socket.api.exception.SocketException; import cn.stylefeng.roses.kernel.socket.api.exception.SocketException;
import cn.stylefeng.roses.kernel.socket.api.exception.enums.SocketExceptionEnum; import cn.stylefeng.roses.kernel.socket.api.exception.enums.SocketExceptionEnum;
import cn.stylefeng.roses.kernel.socket.websocket.message.WebSocketMessagePOJO;
import cn.stylefeng.roses.kernel.socket.websocket.operator.channel.GettySocketOperator; import cn.stylefeng.roses.kernel.socket.websocket.operator.channel.GettySocketOperator;
import cn.stylefeng.roses.kernel.socket.websocket.message.SocketMessageCenter; import cn.stylefeng.roses.kernel.socket.websocket.message.SocketMessageCenter;
import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession; import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession;
import cn.stylefeng.roses.kernel.socket.websocket.session.SessionCenter; import cn.stylefeng.roses.kernel.socket.websocket.session.SessionCenter;
import com.alibaba.fastjson.JSON;
import com.gettyio.expansion.handler.codec.websocket.frame.TextWebSocketFrame;
import java.util.Collection; import java.util.List;
/** /**
* WebSocket * WebSocket
@ -23,26 +27,36 @@ import java.util.Collection;
public class WebSocketOperator implements SocketOperatorApi { public class WebSocketOperator implements SocketOperatorApi {
@Override @Override
public void sendMsgOfSession(String sessionId, Object msg) { public void sendMsgOfUserSession(ServerMessageTypeEnum msgType, String userId, Object msg) {
// 获取会话 // 根据用户ID获取会话
SocketSession<GettySocketOperator> socketSession = SessionCenter.getSessionById(sessionId); SocketSession<GettySocketOperator> socketSession = SessionCenter.getSessionByUserId(userId);
if (ObjectUtil.isEmpty(socketSession)) { if (ObjectUtil.isEmpty(socketSession)) {
throw new SocketException(SocketExceptionEnum.SESSION_NOT_EXIST); throw new SocketException(SocketExceptionEnum.SESSION_NOT_EXIST);
} }
// 发送内容 // 判断用户是否监听
socketSession.getSocketOperatorApi().writeAndFlush(msg); if (socketSession.getMessageTypes().contains(msgType.getCode())) {
WebSocketMessagePOJO webSocketMessagePOJO = new WebSocketMessagePOJO();
webSocketMessagePOJO.setData(msg);
webSocketMessagePOJO.setType(msgType.getCode());
// 发送内容
socketSession.getSocketOperatorApi().writeAndFlush(webSocketMessagePOJO);
}
} }
@Override @Override
public void sendMsgOfAllSession(Object msg) { public void sendMsgOfAllUserSession(ServerMessageTypeEnum msgType, Object msg) {
// 获取所有会话 // 获取监听该消息类型的所有会话
Collection<SocketSession<GettySocketOperator>> socketSessions = SessionCenter.getSocketSessionMap().values(); List<SocketSession<GettySocketOperator>> socketSessionList = SessionCenter.getSocketSessionByMsgType(msgType.getCode());
if (ObjectUtil.isNotEmpty(socketSessions)) {
if (ObjectUtil.isNotEmpty(socketSessionList)) {
// 给所有会话发送消息 // 给所有会话发送消息
for (SocketSession<?> socketSession : socketSessions) { for (SocketSession<GettySocketOperator> socketSession : socketSessionList) {
WebSocketMessagePOJO webSocketMessagePOJO = new WebSocketMessagePOJO();
webSocketMessagePOJO.setData(msg);
webSocketMessagePOJO.setType(msgType.getCode());
// 发送内容 // 发送内容
socketSession.getSocketOperatorApi().writeAndFlush(msg); socketSession.getSocketOperatorApi().writeAndFlush(webSocketMessagePOJO);
} }
} }
} }

View File

@ -1,5 +1,7 @@
package cn.stylefeng.roses.kernel.socket.websocket.operator.channel; package cn.stylefeng.roses.kernel.socket.websocket.operator.channel;
import cn.stylefeng.roses.kernel.socket.websocket.message.WebSocketMessagePOJO;
import com.alibaba.fastjson.JSON;
import com.gettyio.core.channel.SocketChannel; import com.gettyio.core.channel.SocketChannel;
import com.gettyio.expansion.handler.codec.websocket.frame.TextWebSocketFrame; import com.gettyio.expansion.handler.codec.websocket.frame.TextWebSocketFrame;
@ -24,23 +26,12 @@ public class GettySocketOperator implements GettyChannelExpandInterFace {
@Override @Override
public void writeAndFlush(Object obj) { public void writeAndFlush(Object obj) {
if (obj instanceof String) { TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(JSON.toJSONString(obj));
// 处理WebSocket的数据 socketChannel.writeAndFlush(textWebSocketFrame);
TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(obj.toString());
socketChannel.writeAndFlush(textWebSocketFrame);
return;
}
socketChannel.writeAndFlush(obj);
} }
@Override @Override
public void writeToChannel(Object obj) { public void writeToChannel(Object obj) {
if (obj instanceof String) {
// 处理WebSocket的数据
TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(obj.toString());
socketChannel.writeToChannel(textWebSocketFrame);
return;
}
socketChannel.writeToChannel(obj); socketChannel.writeToChannel(obj);
} }

View File

@ -1,7 +1,10 @@
package cn.stylefeng.roses.kernel.socket.websocket.server.handler; package cn.stylefeng.roses.kernel.socket.websocket.server.handler;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.socket.api.SocketMsgCallbackInterface; import cn.stylefeng.roses.kernel.rule.constants.RuleConstants;
import cn.stylefeng.roses.kernel.rule.constants.SymbolConstant;
import cn.stylefeng.roses.kernel.socket.api.enums.ClientMessageTypeEnum;
import cn.stylefeng.roses.kernel.socket.api.message.SocketMsgCallbackInterface;
import cn.stylefeng.roses.kernel.socket.websocket.message.SocketMessageCenter; import cn.stylefeng.roses.kernel.socket.websocket.message.SocketMessageCenter;
import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession; import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession;
import cn.stylefeng.roses.kernel.socket.websocket.session.SessionCenter; import cn.stylefeng.roses.kernel.socket.websocket.session.SessionCenter;
@ -55,13 +58,30 @@ public class WebSocketMessageHandler extends SimpleChannelInboundHandler<WebSock
// 转换为Java对象 // 转换为Java对象
WebSocketMessagePOJO webSocketMessagePOJO = JSON.toJavaObject(JSON.parseObject(data), WebSocketMessagePOJO.class); WebSocketMessagePOJO webSocketMessagePOJO = JSON.toJavaObject(JSON.parseObject(data), WebSocketMessagePOJO.class);
// 心跳包
if (ClientMessageTypeEnum.USER_HEART.getCode().equals(webSocketMessagePOJO.getType())) {
// 更新用户最后活跃时间
String userId = ChannelIdAndUserBindCenter.getUserId(socketChannel.getChannelId());
if (ObjectUtil.isNotEmpty(userId)) {
SocketSession<GettySocketOperator> session = SessionCenter.getSessionByUserId(userId);
session.setLastActiveTime(System.currentTimeMillis());
}
}
// 用户ID为空不处理直接跳过
if (ObjectUtil.isEmpty(webSocketMessagePOJO.getFormUserId())) {
ChannelIdAndUserBindCenter.closed(socketChannel.getChannelId());
socketChannel.close();
return;
}
// 维护通道和用户ID的绑定关系 // 维护通道和用户ID的绑定关系
if (!ChannelIdAndUserBindCenter.isBind(webSocketMessagePOJO.getFormId())) { if (!ChannelIdAndUserBindCenter.isBind(webSocketMessagePOJO.getFormUserId())) {
ChannelIdAndUserBindCenter.bind(socketChannel.getChannelId(), webSocketMessagePOJO.getFormId()); ChannelIdAndUserBindCenter.bind(socketChannel.getChannelId(), webSocketMessagePOJO.getFormUserId());
// 创建api的会话对象 // 创建api的会话对象
SocketSession<GettySocketOperator> socketSession = new SocketSession<>(); SocketSession<GettySocketOperator> socketSession = new SocketSession<>();
socketSession.setSessionId(webSocketMessagePOJO.getFormId()); socketSession.setUserId(webSocketMessagePOJO.getFormUserId());
socketSession.setSocketOperatorApi(new GettySocketOperator(socketChannel)); socketSession.setSocketOperatorApi(new GettySocketOperator(socketChannel));
socketSession.setConnectionTime(System.currentTimeMillis()); socketSession.setConnectionTime(System.currentTimeMillis());
socketSession.setLastActiveTime(System.currentTimeMillis()); socketSession.setLastActiveTime(System.currentTimeMillis());
@ -70,11 +90,15 @@ public class WebSocketMessageHandler extends SimpleChannelInboundHandler<WebSock
SessionCenter.addSocketSession(socketSession); SessionCenter.addSocketSession(socketSession);
} }
// 更新最后会话时间
SocketSession<GettySocketOperator> userSession = SessionCenter.getSessionByUserId(webSocketMessagePOJO.getFormUserId());
userSession.setLastActiveTime(System.currentTimeMillis());
// 找到该消息的处理器 // 找到该消息的处理器
SocketMsgCallbackInterface socketMsgCallbackInterface = SocketMessageCenter.getSocketMsgCallbackInterface(webSocketMessagePOJO.getType()); SocketMsgCallbackInterface socketMsgCallbackInterface = SocketMessageCenter.getSocketMsgCallbackInterface(webSocketMessagePOJO.getType());
if (ObjectUtil.isNotEmpty(socketMsgCallbackInterface)) { if (ObjectUtil.isNotEmpty(socketMsgCallbackInterface)) {
// 获取会话 // 获取会话
SocketSession<GettySocketOperator> session = SessionCenter.getSessionById(webSocketMessagePOJO.getFormId()); SocketSession<GettySocketOperator> session = SessionCenter.getSessionByUserId(webSocketMessagePOJO.getFormUserId());
// 触发回调 // 触发回调
socketMsgCallbackInterface.callback(webSocketMessagePOJO.getType(), webSocketMessagePOJO, session); socketMsgCallbackInterface.callback(webSocketMessagePOJO.getType(), webSocketMessagePOJO, session);

View File

@ -4,9 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession; import cn.stylefeng.roses.kernel.socket.api.session.pojo.SocketSession;
import cn.stylefeng.roses.kernel.socket.websocket.operator.channel.GettySocketOperator; import cn.stylefeng.roses.kernel.socket.websocket.operator.channel.GettySocketOperator;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@ -26,9 +24,9 @@ public class SessionCenter {
private static ConcurrentMap<String, SocketSession<GettySocketOperator>> socketSessionMap = new ConcurrentHashMap<>(); private static ConcurrentMap<String, SocketSession<GettySocketOperator>> socketSessionMap = new ConcurrentHashMap<>();
/** /**
* ID * ID
*/ */
private static ConcurrentMap<String, List<String>> messageTypeSessionMap = new ConcurrentHashMap<>(); private static ConcurrentMap<String, Set<String>> messageTypeSessionMap = new ConcurrentHashMap<>();
/** /**
* *
@ -42,26 +40,26 @@ public class SessionCenter {
} }
/** /**
* ID * ID
* *
* @return {@link ConcurrentMap< String, List< String>>} * @return {@link ConcurrentMap< String, Set<String>>}
* @author majianguo * @author majianguo
* @date 2021/6/1 2:14 * @date 2021/6/1 2:14
**/ **/
public static ConcurrentMap<String, List<String>> getMessageTypeSessionMap() { public static ConcurrentMap<String, Set<String>> getMessageTypeSessionMap() {
return messageTypeSessionMap; return messageTypeSessionMap;
} }
/** /**
* ID * ID
* *
* @param sessionId ID * @param userId ID
* @return {@link SocketSession <GettySocketOperator>} * @return {@link SocketSession <GettySocketOperator>}
* @author majianguo * @author majianguo
* @date 2021/6/1 1:48 * @date 2021/6/1 1:48
**/ **/
public static SocketSession<GettySocketOperator> getSessionById(String sessionId) { public static SocketSession<GettySocketOperator> getSessionByUserId(String userId) {
return socketSessionMap.get(sessionId); return socketSessionMap.get(userId);
} }
/** /**
@ -72,18 +70,19 @@ public class SessionCenter {
* @date 2021/6/1 1:49 * @date 2021/6/1 1:49
**/ **/
public static void addSocketSession(SocketSession<GettySocketOperator> socketSession) { public static void addSocketSession(SocketSession<GettySocketOperator> socketSession) {
// 维护会话 // 维护会话
socketSessionMap.put(socketSession.getSessionId(), socketSession); socketSessionMap.put(socketSession.getUserId(), socketSession);
// 维护会话所有的消息类型和会话的关系 // 维护会话所有的消息类型和会话的关系
if (ObjectUtil.isNotEmpty(socketSession.getMessageTypes())) { if (ObjectUtil.isNotEmpty(socketSession.getMessageTypes())) {
for (String messageType : socketSession.getMessageTypes()) { for (String messageType : socketSession.getMessageTypes()) {
List<String> sessionIds = messageTypeSessionMap.get(messageType); Set<String> userIds = messageTypeSessionMap.get(messageType);
if (ObjectUtil.isEmpty(sessionIds)) { if (ObjectUtil.isEmpty(userIds)) {
sessionIds = new ArrayList<>(); userIds = new HashSet<>();
messageTypeSessionMap.put(messageType, sessionIds); messageTypeSessionMap.put(messageType, userIds);
} }
sessionIds.add(socketSession.getSessionId()); userIds.add(socketSession.getUserId());
} }
} }
} }
@ -99,10 +98,10 @@ public class SessionCenter {
List<SocketSession<GettySocketOperator>> res = new ArrayList<>(); List<SocketSession<GettySocketOperator>> res = new ArrayList<>();
// 获取监听该消息所有的会话 // 获取监听该消息所有的会话
List<String> stringList = messageTypeSessionMap.get(msgType); Set<String> userIds = messageTypeSessionMap.get(msgType);
if (ObjectUtil.isNotEmpty(stringList)) { if (ObjectUtil.isNotEmpty(userIds)) {
for (String sessionId : stringList) { for (String userId : userIds) {
SocketSession<GettySocketOperator> socketSession = socketSessionMap.get(sessionId); SocketSession<GettySocketOperator> socketSession = socketSessionMap.get(userId);
res.add(socketSession); res.add(socketSession);
} }
} }
@ -113,29 +112,37 @@ public class SessionCenter {
/** /**
* *
* *
* @param msgType * @param msgType
* @param sessionId ID * @param userId ID
* @author majianguo * @author majianguo
* @date 2021/6/1 2:11 * @date 2021/6/1 2:11
**/ **/
public static void addSocketSessionMsgType(String msgType, String sessionId) { public static void addSocketSessionMsgType(String msgType, String userId) {
SocketSession<GettySocketOperator> socketSession = socketSessionMap.get(sessionId); // 维护Session信息
SocketSession<GettySocketOperator> socketSession = socketSessionMap.get(userId);
if (ObjectUtil.isNotEmpty(socketSession)) { if (ObjectUtil.isNotEmpty(socketSession)) {
socketSession.getMessageTypes().add(msgType); socketSession.getMessageTypes().add(msgType);
} }
// 维护消息列表
Set<String> userIds = messageTypeSessionMap.get(msgType);
if (ObjectUtil.isEmpty(userIds)) {
userIds = new HashSet<>();
messageTypeSessionMap.put(msgType, userIds);
}
userIds.add(userId);
} }
/** /**
* *
* *
* @param sessionId * @param userId ID
* @author majianguo * @author majianguo
* @date 2021/6/1 3:25 * @date 2021/6/1 3:25
**/ **/
public static void closed(String sessionId) { public static void closed(String userId) {
socketSessionMap.remove(sessionId); socketSessionMap.remove(userId);
for (Map.Entry<String, List<String>> stringListEntry : messageTypeSessionMap.entrySet()) { for (Map.Entry<String, Set<String>> stringListEntry : messageTypeSessionMap.entrySet()) {
stringListEntry.getValue().removeIf(item -> item.equals(sessionId)); stringListEntry.getValue().removeIf(item -> item.equals(userId));
} }
} }
} }

View File

@ -33,8 +33,8 @@ import org.springframework.context.annotation.Configuration;
/** /**
* Socket * Socket
* *
* @author fengshuonan * @author majianguo
* @date 2020/12/1 21:18 * @date 2021/6/2 5:48
*/ */
@Configuration @Configuration
public class GunsSocketAutoConfiguration { public class GunsSocketAutoConfiguration {
@ -42,9 +42,9 @@ public class GunsSocketAutoConfiguration {
/** /**
* Socket * Socket
* *
* @return {@link SocketOperatorApi} * @return {@link cn.stylefeng.roses.kernel.socket.api.SocketOperatorApi}
* @author majianguo * @author majianguo
* @date 2021/6/2 11:02 * @date 2021/6/2 5:48
**/ **/
@Bean @Bean
@ConditionalOnMissingBean(SocketOperatorApi.class) @ConditionalOnMissingBean(SocketOperatorApi.class)

View File

@ -1,49 +0,0 @@
/*
* Copyright [2020-2030] [https://www.stylefeng.cn]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* GunsAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Guns
* 3.
* 4. https://gitee.com/stylefeng/guns
* 5. https://gitee.com/stylefeng/guns
* 6.
*/
package cn.stylefeng.roses.kernel.message.api;
import cn.stylefeng.roses.kernel.message.api.pojo.request.MessageSendRequest;
import java.util.List;
/**
* websocket
*
* @author liuhanqing
* @date 2021/1/26 18:14
*/
public interface WebsocketApi {
/**
* websocket
*
* @param userIdList userId
* @param messageSendRequest
* @author liuhanqing
* @date 2021/1/26 18:17
*/
void sendWebSocketMessage(List<Long> userIdList, MessageSendRequest messageSendRequest);
}

View File

@ -81,6 +81,11 @@ public class MessageSendRequest extends BaseRequest {
@NotBlank(message = "业务类型不能为空", groups = {add.class, edit.class}) @NotBlank(message = "业务类型不能为空", groups = {add.class, edit.class})
private String businessType; private String businessType;
/**
*
*/
private String businessTypeValue;
/** /**
* *
*/ */

View File

@ -1 +0,0 @@
websocket业务模块

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>kernel-s-message</artifactId>
<version>7.0.4</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>message-business-websocket</artifactId>
<packaging>jar</packaging>
<dependencies>
<!--auth鉴权模块的api-->
<!--需要用auth模块的LoginContext获取当前登录用户然后返回ws-url-->
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>auth-api</artifactId>
<version>7.0.4</version>
</dependency>
<!--资源api模块-->
<!--用在资源控制器,资源扫描上-->
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>scanner-api</artifactId>
<version>7.0.4</version>
</dependency>
<!--参数校验模块-->
<!--用在控制器,参数校验-->
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>validator-api</artifactId>
<version>7.0.4</version>
</dependency>
<!--web模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,57 +0,0 @@
/*
* Copyright [2020-2030] [https://www.stylefeng.cn]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* GunsAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Guns
* 3.
* 4. https://gitee.com/stylefeng/guns
* 5. https://gitee.com/stylefeng/guns
* 6.
*/
package cn.stylefeng.roses.kernel.message.modular.websocket;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.rule.pojo.response.ResponseData;
import cn.stylefeng.roses.kernel.rule.pojo.response.SuccessResponseData;
import cn.stylefeng.roses.kernel.scanner.api.annotation.ApiResource;
import cn.stylefeng.roses.kernel.scanner.api.annotation.GetResource;
import org.springframework.web.bind.annotation.RestController;
/**
* websocket
*
* @author liuhanqing
* @date 2021/2/3 21:08
*/
@RestController
@ApiResource(name = "webSocket控制器")
public class WebSocketController {
/**
* ws-url
*
* @author liuhanqing
* @date 2021/2/3 21:15
*/
@GetResource(name = "获取登录用户ws-url", path = "/webSocket/getWsUrl")
public ResponseData getWsUrl() {
LoginUser loginUser = LoginContext.me().getLoginUser();
return new SuccessResponseData(loginUser.getWsUrl());
}
}

View File

@ -37,6 +37,13 @@
<version>7.0.4</version> <version>7.0.4</version>
</dependency> </dependency>
<!--引入WebSocket模块-->
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>socket-sdk-websocket</artifactId>
<version>7.0.4</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -32,7 +32,6 @@ import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult; import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.message.api.MessageApi; import cn.stylefeng.roses.kernel.message.api.MessageApi;
import cn.stylefeng.roses.kernel.message.api.WebsocketApi;
import cn.stylefeng.roses.kernel.message.api.constants.MessageConstants; import cn.stylefeng.roses.kernel.message.api.constants.MessageConstants;
import cn.stylefeng.roses.kernel.message.api.enums.MessageReadFlagEnum; import cn.stylefeng.roses.kernel.message.api.enums.MessageReadFlagEnum;
import cn.stylefeng.roses.kernel.message.api.exception.MessageException; import cn.stylefeng.roses.kernel.message.api.exception.MessageException;
@ -43,8 +42,11 @@ import cn.stylefeng.roses.kernel.message.api.pojo.response.MessageResponse;
import cn.stylefeng.roses.kernel.message.db.entity.SysMessage; import cn.stylefeng.roses.kernel.message.db.entity.SysMessage;
import cn.stylefeng.roses.kernel.message.db.service.SysMessageService; import cn.stylefeng.roses.kernel.message.db.service.SysMessageService;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum; import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.socket.api.SocketOperatorApi;
import cn.stylefeng.roses.kernel.socket.api.enums.ServerMessageTypeEnum;
import cn.stylefeng.roses.kernel.system.api.UserServiceApi; import cn.stylefeng.roses.kernel.system.api.UserServiceApi;
import cn.stylefeng.roses.kernel.system.api.pojo.user.request.SysUserRequest; import cn.stylefeng.roses.kernel.system.api.pojo.user.request.SysUserRequest;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -65,7 +67,7 @@ import java.util.stream.Collectors;
public class MessageDbServiceImpl implements MessageApi { public class MessageDbServiceImpl implements MessageApi {
@Resource @Resource
private WebsocketApi websocketApi; private SocketOperatorApi socketOperatorApi;
@Resource @Resource
private UserServiceApi userServiceApi; private UserServiceApi userServiceApi;
@ -111,7 +113,10 @@ public class MessageDbServiceImpl implements MessageApi {
} }
}); });
websocketApi.sendWebSocketMessage(ListUtil.toList(userIdSet), messageSendRequest); // 给用户发送通知
for (Long userId : userIdSet) {
socketOperatorApi.sendMsgOfUserSession(ServerMessageTypeEnum.SYS_NOTICE_MSG_TYPE, userId.toString(), messageSendRequest);
}
sysMessageService.saveBatch(sendMsgList); sysMessageService.saveBatch(sendMsgList);
} }
@ -134,10 +139,7 @@ public class MessageDbServiceImpl implements MessageApi {
LoginUser loginUser = LoginContext.me().getLoginUser(); LoginUser loginUser = LoginContext.me().getLoginUser();
Long userId = loginUser.getUserId(); Long userId = loginUser.getUserId();
LambdaUpdateWrapper<SysMessage> updateWrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<SysMessage> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(SysMessage::getReadFlag, MessageReadFlagEnum.READ.getCode()) updateWrapper.set(SysMessage::getReadFlag, MessageReadFlagEnum.READ.getCode()).eq(SysMessage::getReadFlag, MessageReadFlagEnum.UNREAD.getCode()).eq(SysMessage::getReceiveUserId, userId).set(SysMessage::getDelFlag, YesOrNotEnum.N.getCode());
.eq(SysMessage::getReadFlag, MessageReadFlagEnum.UNREAD.getCode())
.eq(SysMessage::getReceiveUserId, userId)
.set(SysMessage::getDelFlag, YesOrNotEnum.N.getCode());
sysMessageService.update(updateWrapper); sysMessageService.update(updateWrapper);
} }
@ -156,8 +158,7 @@ public class MessageDbServiceImpl implements MessageApi {
public void deleteByMessageId(Long messageId) { public void deleteByMessageId(Long messageId) {
LambdaUpdateWrapper<SysMessage> updateWrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<SysMessage> updateWrapper = new LambdaUpdateWrapper<>();
// 修改为逻辑删除 // 修改为逻辑删除
updateWrapper.eq(SysMessage::getMessageId, messageId) updateWrapper.eq(SysMessage::getMessageId, messageId).set(SysMessage::getDelFlag, YesOrNotEnum.Y.getCode());
.set(SysMessage::getDelFlag, YesOrNotEnum.Y.getCode());
sysMessageService.update(updateWrapper); sysMessageService.update(updateWrapper);
} }
@ -165,8 +166,7 @@ public class MessageDbServiceImpl implements MessageApi {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchDeleteByMessageIds(String messageIds) { public void batchDeleteByMessageIds(String messageIds) {
LambdaUpdateWrapper<SysMessage> updateWrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<SysMessage> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.inSql(SysMessage::getMessageId, messageIds) updateWrapper.inSql(SysMessage::getMessageId, messageIds).set(SysMessage::getDelFlag, YesOrNotEnum.Y.getCode());
.set(SysMessage::getDelFlag, YesOrNotEnum.Y.getCode());
sysMessageService.update(updateWrapper); sysMessageService.update(updateWrapper);
} }

View File

@ -1 +0,0 @@
系统消息websocket的sdk用于将消息发送给在线用户并提供相应接口

View File

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>kernel-s-message</artifactId>
<version>7.0.4</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>message-sdk-websocket</artifactId>
<packaging>jar</packaging>
<dependencies>
<!--消息模块的api-->
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>message-api</artifactId>
<version>7.0.4</version>
</dependency>
<!--websocket 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>auth-api</artifactId>
<version>7.0.4</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,79 +0,0 @@
/*
* Copyright [2020-2030] [https://www.stylefeng.cn]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* GunsAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Guns
* 3.
* 4. https://gitee.com/stylefeng/guns
* 5. https://gitee.com/stylefeng/guns
* 6.
*/
package cn.stylefeng.roses.kernel.message.websocket;
import cn.hutool.core.bean.BeanUtil;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.message.api.WebsocketApi;
import cn.stylefeng.roses.kernel.message.api.enums.MessageReadFlagEnum;
import cn.stylefeng.roses.kernel.message.api.pojo.request.MessageSendRequest;
import cn.stylefeng.roses.kernel.message.api.pojo.response.MessageResponse;
import cn.stylefeng.roses.kernel.message.websocket.manager.WebSocketManager;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* websocket
*
* @author liuhanqing
* @date 2021/1/2 22:00
*/
@Slf4j
@Service
public class WebSocketServiceImpl implements WebsocketApi {
public final static ObjectMapper MAPPER;
static {
MAPPER = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
@Override
public void sendWebSocketMessage(List<Long> userIdList, MessageSendRequest messageSendRequest) {
// 获取当前登录人
LoginUser loginUser = LoginContext.me().getLoginUser();
try {
MessageResponse sysMessage = new MessageResponse();
BeanUtil.copyProperties(messageSendRequest, sysMessage);
sysMessage.setReadFlag(MessageReadFlagEnum.UNREAD.getCode());
sysMessage.setSendUserId(loginUser.getUserId());
String msgInfo = MAPPER.writeValueAsString(sysMessage);
for (Long userId : userIdList) {
WebSocketManager.sendMessage(userId, msgInfo);
}
} catch (JsonProcessingException e) {
log.error("发送websocket异常", e);
}
}
}

View File

@ -1,129 +0,0 @@
/*
* Copyright [2020-2030] [https://www.stylefeng.cn]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* GunsAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Guns
* 3.
* 4. https://gitee.com/stylefeng/guns
* 5. https://gitee.com/stylefeng/guns
* 6.
*/
package cn.stylefeng.roses.kernel.message.websocket.manager;
import org.springframework.util.CollectionUtils;
import javax.websocket.Session;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* websocket
*
* @author liuhanqing
* @date 2021/1/24 22:08
*/
public class WebSocketManager {
private static final ConcurrentHashMap<Long, List<Session>> userIdSessionMap = new ConcurrentHashMap<>();
/**
* IDSession
*
* @param userId id
* @param session websocketSession
* @author liuhanqing
* @date 2021/1/24 22:08
*/
public static void add(Long userId, Session session) {
userIdSessionMap.computeIfAbsent(userId, v -> new ArrayList<>()).add(session);
}
/**
* IDSession
*
* @param userId id
* @return List<Session> websocketSession
* @author liuhanqing
* @date 2021/1/24 22:10
*/
public static List<Session> getSessionByUserId(Long userId) {
return userIdSessionMap.get(userId);
}
/**
* Session
*
* @param userId id
* @param session websocketSession
* @author liuhanqing
* @date 2021/1/24 22:11
*/
public static void removeSession(Long userId, Session session) {
if (session == null) {
return;
}
List<Session> webSessoin = userIdSessionMap.get(userId);
if (webSessoin == null || CollectionUtils.isEmpty(webSessoin)) {
return;
}
webSessoin.remove(session);
}
/**
*
*
* @author liuhanqing
* @date 2021/1/24 22:11
*/
public static Set<Long> getUserList() {
return userIdSessionMap.keySet();
}
/**
*
*
* @param userId id
* @param message
* @author liuhanqing
* @date 2021/1/24 22:11
*/
public static void sendMessage(Long userId, String message) {
List<Session> sessionList = getSessionByUserId(userId);
// 增加判断不为空
if (!CollectionUtils.isEmpty(sessionList)) {
for (Session userSession : sessionList) {
userSession.getAsyncRemote().sendText(message);
}
}
}
/**
*
*
* @param message
* @author liuhanqing
* @date 2021/1/24 22:11
*/
public static void sendMessageToAll(String message) {
for (Long userId : WebSocketManager.getUserList()) {
sendMessage(userId, message);
}
}
}

View File

@ -1,105 +0,0 @@
/*
* Copyright [2020-2030] [https://www.stylefeng.cn]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* GunsAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Guns
* 3.
* 4. https://gitee.com/stylefeng/guns
* 5. https://gitee.com/stylefeng/guns
* 6.
*/
package cn.stylefeng.roses.kernel.message.websocket.server;
import cn.stylefeng.roses.kernel.message.websocket.manager.WebSocketManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
/**
* websocket
*
* @author liuhanqing
* @date 2021/1/24 22:26
*/
@Slf4j
@Component
@ServerEndpoint("/message/websocket/{userId}")
public class WebSocketEndpoint {
/**
*
*
* @param userId id
* @param session websocketSession
* @author liuhanqing
* @date 2021/1/24 22:27
*/
@OnOpen
public void onOpen(@PathParam(value = "userId") Long userId, Session session) {
// 添加到链接管理
WebSocketManager.add(userId, session);
// 返回消息
session.getAsyncRemote().sendText("WebSocket连接成功");
}
/**
*
*
* @author liuhanqing
* @date 2021/1/24 22:29
*/
@OnClose
public void onClose(@PathParam(value = "userId") Long userId, Session session) {
// 从map中删除
WebSocketManager.removeSession(userId, session);
}
/**
*
*
* @param message
* @param session websocketSession
* @author liuhanqing
* @date 2021/1/24 22:29
*/
@OnMessage
public void onMessage(String message, Session session) {
log.debug("来自客户端的消息:" + message);
}
/**
*
*
* @param session
* @param error
* @author liuhanqing
* @date 2021/1/24 22:29
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("WebSocket发生错误");
if (log.isDebugEnabled()) {
error.printStackTrace();
}
}
}

View File

@ -24,13 +24,6 @@
<version>7.0.4</version> <version>7.0.4</version>
</dependency> </dependency>
<!--websocket管理-->
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>message-business-websocket</artifactId>
<version>7.0.4</version>
</dependency>
<!--消息默认记录到库中--> <!--消息默认记录到库中-->
<dependency> <dependency>
<groupId>cn.stylefeng.roses</groupId> <groupId>cn.stylefeng.roses</groupId>
@ -38,12 +31,6 @@
<version>7.0.4</version> <version>7.0.4</version>
</dependency> </dependency>
<dependency>
<groupId>cn.stylefeng.roses</groupId>
<artifactId>message-sdk-websocket</artifactId>
<version>7.0.4</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -24,11 +24,7 @@
*/ */
package cn.stylefeng.roses.kernel.message.starter; package cn.stylefeng.roses.kernel.message.starter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/** /**
* *
@ -39,20 +35,4 @@ import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration @Configuration
public class GunsMessageAutoConfiguration { public class GunsMessageAutoConfiguration {
public static final String WEB_SOCKET_PREFIX = "web-socket";
/**
* WebSocket
*
* @return serverEndpointExporter
* @author liuhanqing
* @date 2021/01/24 22:09
*/
@Bean
@ConditionalOnMissingBean(ServerEndpointExporter.class)
@ConditionalOnProperty(prefix = WEB_SOCKET_PREFIX, name = "open", havingValue = "true")
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
} }

View File

@ -18,9 +18,7 @@
<modules> <modules>
<module>message-api</module> <module>message-api</module>
<module>message-business</module> <module>message-business</module>
<module>message-business-websocket</module>
<module>message-sdk-db</module> <module>message-sdk-db</module>
<module>message-sdk-websocket</module>
<module>message-spring-boot-starter</module> <module>message-spring-boot-starter</module>
</modules> </modules>

View File

@ -194,6 +194,7 @@ public class SysNoticeServiceImpl extends ServiceImpl<SysNoticeMapper, SysNotice
// 消息业务类型 // 消息业务类型
message.setBusinessType(MessageBusinessTypeEnum.SYS_NOTICE.getCode()); message.setBusinessType(MessageBusinessTypeEnum.SYS_NOTICE.getCode());
message.setBusinessTypeValue(MessageBusinessTypeEnum.SYS_NOTICE.getName());
message.setBusinessId(sysNotice.getNoticeId()); message.setBusinessId(sysNotice.getNoticeId());
message.setMessageSendTime(new Date()); message.setMessageSendTime(new Date());

View File

@ -68,6 +68,9 @@ public class IndexService {
// 获取登录用户ws-url // 获取登录用户ws-url
renderMap.put("wsUrl", loginUser.getWsUrl()); renderMap.put("wsUrl", loginUser.getWsUrl());
// 获取登录用户ID
renderMap.put("userId", loginUser.getUserId());
// 未读消息数量 // 未读消息数量
MessageRequest messageRequest = new MessageRequest(); MessageRequest messageRequest = new MessageRequest();
messageRequest.setReadFlag(MessageReadFlagEnum.UNREAD.getCode()); messageRequest.setReadFlag(MessageReadFlagEnum.UNREAD.getCode());