WebSocket的心跳机制可以用来解决这个问题。客户端和服务端都可以通过发送心跳消息来保持连接,如果一定时间内没有收到心跳消息,则认为连接已断开,可以进行相应的处理。

下面是一个简单的实现示例:

  1. 在WebSocketConfig中添加心跳处理器HeartbeatHandler:
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler(), "/ws").setAllowedOrigins("*");
    }

    @Bean
    public WebSocketHandler webSocketHandler() {
        return new MyWebSocketHandler();
    }

    @Bean
    public HeartbeatHandler heartbeatHandler() {
        return new HeartbeatHandler();
    }

}
  1. 在HeartbeatHandler中实现心跳处理逻辑:
public class HeartbeatHandler extends TextWebSocketHandler {

    private static final String HEARTBEAT_PAYLOAD = "ping";

    private ScheduledExecutorService executorService;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 连接建立时开始发送心跳消息
        executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(() -> {
            try {
                session.sendMessage(new TextMessage(HEARTBEAT_PAYLOAD));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 0, 10, TimeUnit.SECONDS);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 收到心跳消息,不做处理
        if (HEARTBEAT_PAYLOAD.equals(message.getPayload())) {
            return;
        }
        // 收到其他消息,重置心跳计时器
        executorService.shutdownNow();
        executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.schedule(() -> {
            try {
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 30, TimeUnit.SECONDS);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        // 连接关闭时停止发送心跳消息
        executorService.shutdownNow();
    }

}

该处理器在连接建立时开始发送心跳消息,每隔10秒发送一次ping消息。如果在30秒内没有收到心跳消息,则认为连接已断开,关闭连接。如果收到其他消息,则重置心跳计时器。在连接关闭时停止发送心跳消息。

  1. 在MyWebSocketHandler中添加心跳处理器:
public class MyWebSocketHandler extends TextWebSocketHandler {

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

    private HeartbeatHandler heartbeatHandler;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        logger.info("Connection established: ", session.getId());
        heartbeatHandler.afterConnectionEstablished(session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        logger.info("Received message: ", message.getPayload());
        heartbeatHandler.handleTextMessage(session, message);
        // 处理其他业务逻辑
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        logger.info("Connection closed: ", session.getId());
        heartbeatHandler.afterConnectionClosed(session, status);
    }

    @Autowired
    public void setHeartbeatHandler(HeartbeatHandler heartbeatHandler) {
        this.heartbeatHandler = heartbeatHandler;
    }

}
  1. 在前端代码中添加心跳处理逻辑:
var ws = new WebSocket("ws://localhost:8080/ws");

ws.onopen = function() {
    console.log("Connection established");
    setInterval(function() {
        if (ws.readyState === WebSocket.OPEN) {
            ws.send("ping");
        }
    }, 10000);
};

ws.onmessage = function(event) {
    console.log("Received message: " + event.data);
    // 处理其他业务逻辑
};

该代码在连接建立时开始发送心跳消息,每隔10秒发送一次ping消息。如果在30秒内没有收到心跳消息,则认为连接已断开,关闭连接。如果收到其他消息,则继续处理业务逻辑。

通过这种方式,就可以实现根据隔一段时间没有发送消息实现主动断开连接的功能了。

SpringBoot WebSocket 心跳机制:主动断开连接的实现

原文地址: https://www.cveoy.top/t/topic/nCsI 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录