SpringBoot中WebSokcet无法注入Bean对象的解决方案

一、业务场景

@Slf4j
@Component
@ServerEndpoint("/ws/{userId}")
public class WebSocketServer {

    @Autowired
    private IChatService chatService;

    public static Map<Long, Session> sessionMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) {
        log.info("用户: {} 与服务器建立连接", userId);
        sessionMap.put(userId, session);
    }

    @OnMessage
    public void onMessage(String message, Session senderSession, @PathParam("userId") Long senderUserId) {
        ChatMessage receivedMessage = JSON.parseObject(message, ChatMessage.class);
        sendAndPersistMessage(receivedMessage);
    }

    @OnClose
    public 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;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) {
        log.info("用户: {} 与服务器建立连接", userId);
        sessionMap.put(userId, session);
    }

    @OnMessage
    public void onMessage(String message, Session senderSession, @PathParam("userId") Long senderUserId) {
        ChatMessage receivedMessage = JSON.parseObject(message, ChatMessage.class);
        sendAndPersistMessage(receivedMessage);
    }

    @OnClose
    public 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

你可能感兴趣的:(spring,boot,后端,websocket)