springboot webscoket示例:增加定时心跳逻辑

websocket服务端增加定时发送心跳机制

@ServerEndpoint(value = "/websocket/{uuid}")
@Component
public class DevMessageHandleController {

    private static final Logger logger = LoggerFactory.getLogger(DevMessageHandleController.class);

    //concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketController对象。
    public static CopyOnWriteArraySet<DevMessageHandleController> webSocketSet = new CopyOnWriteArraySet<>();

    // 使用ConcurrentHashMap来存储用户ID和WebSocket会话对象的映射。
    private static ConcurrentHashMap<String, DevMessageHandleController> webSocketMap = new ConcurrentHashMap<>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    private String uuid;
    // 心跳尝试次数
    private AtomicInteger heartbeatAttempts;

    @OnOpen
    public void onOpen(@PathParam("uuid") String uuid, Session session) {
        logger.info("uuid: {}, sessionId: {}", uuid, session.getId());
        // 将新建立的会话添加到webSocketMap中
        try {
            if (webSocketMap.containsKey(uuid)) {
                //如果有旧连接就先断开
                webSocketMap.get(uuid).session.close();
                webSocketSet.remove(webSocketMap.get(uuid));
            }
            this.session = session;
            this.uuid = uuid;
            heartbeatAttempts = new AtomicInteger(0);
            webSocketSet.add(this); //加入set中
            webSocketMap.put(uuid, this); //加入map中
            // 其他代码...
        } catch (Exception e) {
            logger.error("onOpen error:" + e.getMessage());
        }
    }

    @OnClose
    public void onClose(@PathParam("uuid") String uuid, Session session) {
        logger.info("会话关闭");
        // 当会话关闭时,从webSocketSet中移除该会话
        webSocketSet.remove(this);
        // 当会话关闭时,从webSocketMap中移除该会话
        webSocketMap.remove(uuid);
    }

    // 收到客户端消息后调用的方法
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("Message from client: " + message);
        if ("pong".equals(message)) {
            // 重置为0
            this.heartbeatAttempts.set(0);
            System.out.println("Received pong from: " + session.getId());
        }
    }

    // 发生错误时调用
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误 session:" + session.getId() + ",error:" + error);
        try {
            session.close();
            // 当会话关闭时,从webSocketSet中移除该会话
            webSocketSet.remove(this);
            // 当会话关闭时,从webSocketMap中移除该会话
            webSocketMap.remove(this.uuid);
        } catch (IOException e) {
            logger.error("onError error:" + e.getMessage());
        }
    }

    public void sendMessage(Session session, String msg) {
        logger.info("发送消息");
        try {
            //判断当前人员是否连接websocket
            if (session.isOpen()) {
                session.getAsyncRemote().sendText(msg);
            } else {
                session.close();
                webSocketSet.remove(this); //从set中删除
                webSocketMap.remove(this.uuid); //从map中删除
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static CopyOnWriteArraySet<DevMessageHandleController> getWebSocketSet() {
        return webSocketSet;
    }

    public static void setWebSocketSet(CopyOnWriteArraySet<DevMessageHandleController> webSocketSet) {
        DevMessageHandleController.webSocketSet = webSocketSet;
    }

    public static ConcurrentHashMap<String, DevMessageHandleController> getWebSocketMap() {
        return webSocketMap;
    }

    public static void setWebSocketMap(ConcurrentHashMap<String, DevMessageHandleController> webSocketMap) {
        DevMessageHandleController.webSocketMap = webSocketMap;
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public AtomicInteger getHeartbeatAttempts() {
        return heartbeatAttempts;
    }

    public void setHeartbeatAttempts(AtomicInteger heartbeatAttempts) {
        this.heartbeatAttempts = heartbeatAttempts;
    }
}

每间隔10s向客户端发送一次心跳

    private static final int MAX_HEARTBEAT_ATTEMPTS = 3;

	@Scheduled(fixedDelay = 10000)
    public void sendHeartBeat() {
        CopyOnWriteArraySet<DevMessageHandleController> webSocketSet;
        try {
            webSocketSet = DevMessageHandleController.getWebSocketSet();
            logger.info("连接数量:" + webSocketSet.size());
            if(webSocketSet.size() == 0){
                return;
            }
            logger.info("定时发送心跳");
            // 遍历所有连接,发送心跳
            webSocketSet.forEach(obj -> {
                Session session = obj.getSession();
                logger.info("sessionId:" + session.getId() +" 心跳ping发送次数:" + obj.getHeartbeatAttempts().get());
                if(obj.getHeartbeatAttempts().get() >= MAX_HEARTBEAT_ATTEMPTS) {
                    try {
                        session.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        logger.error("session close error:" + e.getMessage());
                    }
                } else {
                    obj.getHeartbeatAttempts().incrementAndGet();
                    if (session.isOpen()) {
                        session.getAsyncRemote().sendText("ping");
                    }
                }
            });
        }catch (Exception e){
            logger.error("发送心跳 error:" + e.getMessage());
        }
    }
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Spring Boot WebSocket示例: 1. 创建一个Spring Boot项目并添加以下依赖项: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建一个WebSocket配置类并实现WebSocketConfigurer接口: ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/myHandler").setAllowedOrigins("*"); } @Bean public WebSocketHandler myHandler() { return new MyHandler(); } } ``` 3. 创建一个WebSocket处理程序类并实现WebSocketHandler接口: ``` public class MyHandler implements WebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // 连接建立时的处理逻辑 } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { // 处理消息的逻辑 } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { // 处理传输错误的逻辑 } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { // 连接关闭时的处理逻辑 } @Override public boolean supportsPartialMessages() { return false; } } ``` 4. 在控制器中添加一个WebSocket端点: ``` @RestController public class MyController { @GetMapping("/websocket") public String websocket() { return "websocket"; } } ``` 5. 在前端页面添加WebSocket连接: ``` var socket = new WebSocket("ws://localhost:8080/myHandler"); ``` 6. 运行应用程序并打开浏览器控制台,您将看到WebSocket连接已建立。 以上就是一个简单的Spring Boot WebSocket示例。您可以根据自己的需要修改它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值