一、业务场景
@Slf4j
@Component
@ServerEndpoint("/ws/{userId}")
public class WebSocketServer {@Autowiredprivate IChatService chatService;public static Map<Long, Session> sessionMap = new ConcurrentHashMap<>();@OnOpenpublic void onOpen(Session session, @PathParam("userId") Long userId) {log.info("用户: {} 与服务器建立连接", userId);sessionMap.put(userId, session);}@OnMessagepublic void onMessage(String message, Session senderSession, @PathParam("userId") Long senderUserId) {ChatMessage receivedMessage = JSON.parseObject(message, ChatMessage.class);sendAndPersistMessage(receivedMessage);}@OnClosepublic void onClose(Session session, @PathParam("userId") Long userId) {log.info("用户: {} 与服务器断开连接", userId);sessionMap.remove(userId);}private void sendAndPersistMessage(ChatMessage message) {log.info("用户: {} 向用户: {} 发送了如下消息: {}", message.getSenderId(), message.getReceiverId(), message.getContent());if (chatService != null) {Chat chat = Chat.builder().userId1(message.getSenderId()).userId2(message.getReceiverId()).content(message.getContent()).createTime(LocalDateTime.now()).build();chatService.save(chat);} else {log.info("消息持久化失败...");}String jsonMessage = JSON.toJSONString(message);Session receiverSession = sessionMap.get(message.getReceiverId());if (receiverSession != null) {try {receiverSession.getBasicRemote().sendText(jsonMessage);} catch (IOException e) {e.printStackTrace();}}}
}
22:47:05 INFO 14040 --- [io-8080-exec-10] com.lichun.websocket.WebSocketServer : 用户: 1 与服务器建立连接
22:47:09 INFO 14040 --- [nio-8080-exec-1] com.lichun.websocket.WebSocketServer : 用户: 2 与服务器建立连接
22:47:14 INFO 14040 --- [nio-8080-exec-2] com.lichun.websocket.WebSocketServer : 用户: 1 向用户: 2 发送了如下消息: 你好
22:47:14 INFO 14040 --- [nio-8080-exec-2] com.lichun.websocket.WebSocketServer : 消息持久化失败...
二、解决方案
(1)修改AccompanyApplication.java
ConfigurableApplicationContext applicationContext = SpringApplication.run(AccompanyApplication.class, args);WebSocketServer.setApplicationContext(applicationContext);
@EnableTransactionManagement
@SpringBootApplication
public class AccompanyApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext = SpringApplication.run(AccompanyApplication.class, args);WebSocketServer.setApplicationContext(applicationContext);}}
(2)修改WebSocketServer.java
private static ApplicationContext applicationContext;public static void setApplicationContext(ApplicationContext applicationContext) {WebSocketServer.applicationContext = applicationContext;
}
IChatService chatService = (IChatService) applicationContext.getBean("chatServiceImpl");
Chat chat = Chat.builder().userId1(message.getSenderId()).userId2(message.getReceiverId()).content(message.getContent()).createTime(LocalDateTime.now()).build();
chatService.save(chat);
@Slf4j
@Component
@ServerEndpoint("/ws/{userId}")
public class WebSocketServer {public static Map<Long, Session> sessionMap = new ConcurrentHashMap<>();private static ApplicationContext applicationContext;public static void setApplicationContext(ApplicationContext applicationContext) {WebSocketServer.applicationContext = applicationContext;}@OnOpenpublic void onOpen(Session session, @PathParam("userId") Long userId) {log.info("用户: {} 与服务器建立连接", userId);sessionMap.put(userId, session);}@OnMessagepublic void onMessage(String message, Session senderSession, @PathParam("userId") Long senderUserId) {ChatMessage receivedMessage = JSON.parseObject(message, ChatMessage.class);sendAndPersistMessage(receivedMessage);}@OnClosepublic void onClose(Session session, @PathParam("userId") Long userId) {log.info("用户: {} 与服务器断开连接", userId);sessionMap.remove(userId);}private void sendAndPersistMessage(ChatMessage message) {log.info("用户: {} 向用户: {} 发送了如下消息: {}", message.getSenderId(), message.getReceiverId(), message.getContent());IChatService chatService = (IChatService) applicationContext.getBean("chatServiceImpl");Chat chat = Chat.builder().userId1(message.getSenderId()).userId2(message.getReceiverId()).content(message.getContent()).createTime(LocalDateTime.now()).build();chatService.save(chat);String jsonMessage = JSON.toJSONString(message);Session receiverSession = sessionMap.get(message.getReceiverId());if (receiverSession != null) {try {receiverSession.getBasicRemote().sendText(jsonMessage);} catch (IOException e) {e.printStackTrace();}}}public void noticeTimingTimeOut(Long userId1, Long userId2) {for (Long id : sessionMap.keySet()) {if (id.equals(userId1) || id.equals(userId2)) {Session session = sessionMap.get(id);if (session != null) {try {session.getBasicRemote().sendText("时间到...");} catch (IOException e) {e.printStackTrace();}}}}}
}
三、测试
23:00:43 INFO 12252 --- [nio-8080-exec-8] com.lichun.websocket.WebSocketServer : 用户: 1 与服务器建立连接
23:00:47 INFO 12252 --- [nio-8080-exec-5] com.lichun.websocket.WebSocketServer : 用户: 2 与服务器建立连接
23:00:56 INFO 12252 --- [nio-8080-exec-4] com.lichun.websocket.WebSocketServer : 用户: 1 向用户: 2 发送了如下消息: 你好啊
23:00:56 ERROR 12252 --- [nio-8080-exec-4] c.a.druid.pool.DruidAbstractDataSource : discard long time none received connection. , jdbcUrl : jdbc:mysql://127.0.0.1:13306/accompany?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true, jdbcUrl : jdbc:mysql://127.0.0.1:13306/accompany?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true, lastPacketReceivedIdleMillis : 296332
23:00:56 DEBUG 12252 --- [nio-8080-exec-4] com.lichun.mapper.ChatMapper.insert : ==> Preparing: INSERT INTO chat ( user_id1, user_id2, content, create_time ) VALUES ( ?, ?, ?, ? )
23:00:56 DEBUG 12252 --- [nio-8080-exec-4] com.lichun.mapper.ChatMapper.insert : ==> Parameters: 1(Long), 2(Long), 你好啊(String), 2024-01-03T23:00:56.867703800(LocalDateTime)
23:00:56 DEBUG 12252 --- [nio-8080-exec-4] com.lichun.mapper.ChatMapper.insert : <== Updates: 1