SpringBoot WebSocket 实现单聊、群聊,支持离线消息和未读消息统计
以下是一个简单的使用 SpringBoot 和 WebSocket 实现单聊、群聊,包含离线信息,未读信息统计的示例代码,仅供参考。
- 创建 WebSocketConfig 类
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
}
}
- 创建 WebSocketController 类
@Controller
public class WebSocketController {
@Autowired
private ChatService chatService;
@MessageMapping("/chat/single")
public void singleChat(Principal principal, ChatMessage chatMessage) {
chatService.singleChat(principal.getName(), chatMessage);
}
@MessageMapping("/chat/group")
public void groupChat(Principal principal, ChatMessage chatMessage) {
chatService.groupChat(principal.getName(), chatMessage);
}
}
- 创建 ChatMessage 类
public class ChatMessage {
private String content;
private String sender;
private String receiver;
private Date sendTime;
// getters and setters
}
- 创建 ChatService 类
@Service
public class ChatService {
// 存储在线用户
private Map<String, WebSocketSession> onlineUsers = new ConcurrentHashMap<>();
// 存储离线消息
private Map<String, List<ChatMessage>> offlineMessages = new ConcurrentHashMap<>();
// 存储未读消息数量
private Map<String, Integer> unreadMessages = new ConcurrentHashMap<>();
// 单聊
public void singleChat(String sender, ChatMessage chatMessage) {
String receiver = chatMessage.getReceiver();
WebSocketSession receiverSession = onlineUsers.get(receiver);
if (receiverSession != null && receiverSession.isOpen()) {
// 如果接收者在线,则直接发送消息
try {
receiverSession.sendMessage(new TextMessage(new Gson().toJson(chatMessage)));
} catch (IOException e) {
e.printStackTrace();
}
} else {
// 如果接收者不在线,则存储离线消息
List<ChatMessage> messages = offlineMessages.get(receiver);
if (messages == null) {
messages = new ArrayList<>();
}
messages.add(chatMessage);
offlineMessages.put(receiver, messages);
// 存储未读消息数量
Integer unreadCount = unreadMessages.get(receiver);
if (unreadCount == null) {
unreadCount = 0;
}
unreadMessages.put(receiver, unreadCount + 1);
}
}
// 群聊
public void groupChat(String sender, ChatMessage chatMessage) {
onlineUsers.values().forEach(session -> {
if (session.isOpen()) {
try {
session.sendMessage(new TextMessage(new Gson().toJson(chatMessage)));
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
// 用户上线
public void userOnline(WebSocketSession session) {
onlineUsers.put(session.getPrincipal().getName(), session);
// 发送离线消息
List<ChatMessage> messages = offlineMessages.get(session.getPrincipal().getName());
if (messages != null) {
messages.forEach(msg -> {
try {
session.sendMessage(new TextMessage(new Gson().toJson(msg)));
} catch (IOException e) {
e.printStackTrace();
}
});
// 清空离线消息
offlineMessages.remove(session.getPrincipal().getName());
}
// 清空未读消息数量
unreadMessages.remove(session.getPrincipal().getName());
}
// 用户下线
public void userOffline(WebSocketSession session) {
onlineUsers.remove(session.getPrincipal().getName());
}
// 获取未读消息数量
public Integer getUnreadMessageCount(String username) {
return unreadMessages.get(username);
}
}
- 创建 WebSocketEventListener 类
@Component
public class WebSocketEventListener implements ApplicationListener<SessionConnectEvent>, ApplicationListener<SessionDisconnectEvent> {
@Autowired
private ChatService chatService;
@Override
public void onApplicationEvent(SessionConnectEvent event) {
chatService.userOnline((WebSocketSession) event.getSource());
}
@Override
public void onApplicationEvent(SessionDisconnectEvent event) {
chatService.userOffline((WebSocketSession) event.getSource());
}
}
- 创建 WebSocketSecurityConfig 类
@Configuration
@EnableWebSocket
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages.simpDestMatchers("/app/**").authenticated()
.simpSubscribeDestMatchers("/topic/**").authenticated()
.anyMessage().authenticated();
}
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
- 使用 WebSocket
在前端页面中,可以使用以下代码来连接 WebSocket:
var stompClient = null;
function connect() {
var socket = new SockJS('/chat');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/user/topic/unread', function (message) {
console.log(message.body);
});
});
}
function sendSingleChat() {
var chatMessage = {
content: 'Hello',
sender: 'user1',
receiver: 'user2',
sendTime: new Date()
};
stompClient.send('/app/chat/single', {}, JSON.stringify(chatMessage));
}
function sendGroupChat() {
var chatMessage = {
content: 'Hello',
sender: 'user1',
receiver: '',
sendTime: new Date()
};
stompClient.send('/app/chat/group', {}, JSON.stringify(chatMessage));
}
其中,connect() 函数用于连接 WebSocket,sendSingleChat() 函数用于发送单聊消息,sendGroupChat() 函数用于发送群聊消息。
另外,可以使用以下代码来获取未读消息数量:
function getUnreadMessageCount() {
stompClient.send('/app/unread', {}, {}, function (response) {
console.log(response.body);
});
}
原文地址: http://www.cveoy.top/t/topic/nI9D 著作权归作者所有。请勿转载和采集!