java WebSocket 使用

1、创建WebSocket配置类

java 复制代码
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(chatWebSocketHandler(), "/chat/ws")
                .setAllowedOrigins("https://yourdomain.com")  // 生产环境配置具体域名
                .withSockJS(); // 兼容不支持 WebSocket 的浏览器
    }

    @Bean
    public WebSocketHandler chatWebSocketHandler() {
        return new ChatWebSocketHandler();
    }
}

2、创建WebSocket和前端的通信类

java 复制代码
/*TextWebSocketHandler‌是 Spring 框架提供的用于处理 WebSocket 文本消息的处理器基类,通过继承该类
*	并重写特定方法,便可以在项目中实现 WebSocket 服务端逻辑。
*	
*	例:1、afterConnectionEstablished:当客户端与服务端成功建立 WebSocket 连接时触发,常用于记录在线用户、初始化会话属性或发送欢迎消息 。
*   2、handleTextMessage:当服务端收到客户端发送的文本消息时触发,是业务逻辑处理的主要入口,可在此解析消息并回复 。
*   3、afterConnectionClosed:当连接正常关闭时触发,用于清理资源、移除离线用户会话或记录日志 。
*   4、handleTransportError:当通信过程中出现异常(如网络中断)时触发,用于错误处理和告警 。
*/
public class ChatWebSocketHandler extends TextWebSocketHandler {
    // 存储所有在线客户端连接
    private final Set<WebSocketSession> sessions = ConcurrentHashMap.newKeySet();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        // 新客户端连接处理
        sessions.add(session);
        System.out.println("新客户端连接: " + session.getId());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 接收客户端消息并广播给所有在线用户
        String payload = message.getPayload();
        System.out.println("收到消息: " + payload);
        
        // 消息广播
        for (WebSocketSession webSocketSession : sessions) {
            if (webSocketSession.isOpen()) {
                webSocketSession.sendMessage(new TextMessage("广播消息: " + payload));
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        // 客户端连接关闭处理
        sessions.remove(session);
        System.out.println("客户端断开连接: " + session.getId());
    }
    
    @Override
    protected void handleTransportError(WebSocketSession session, TextMessage message) throws Exception {
        String userId = getUserIdFromSession(session);
        
        // 1. 记录详细错误日志
        log.error("WebSocket传输错误,用户ID:{},会话ID:{},错误信息:{}", 
                  userId, session.getId(), exception.getMessage(), exception);
    }
}

3、前端简单实现

javascript 复制代码
// 创建 WebSocket 连接
const socket = new WebSocket('wss://yourdomain.com/chat/ws');

// 连接成功回调
socket.onopen = function(event) {
    console.log('WebSocket 连接已建立');
    socket.send('Hello, Server!');
};

// 接收消息回调
socket.onmessage = function(event) {
    const message = event.data;
    console.log('收到服务器消息:', message);
    // 更新UI展示消息
};

// 连接关闭回调
socket.onclose = function(event) {
    console.log('WebSocket 连接已关闭');
    // 实现自动重连逻辑
    setTimeout(() => initWebSocket(), 5000);
};

// 错误处理回调
socket.onerror = function(error) {
    console.error('WebSocket 错误:', error);
};

4、简单使用

java 复制代码
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(photoWebSocketHandler(), "/photo/ws")
                //.setAllowedOrigins("https://localhost:8080")  // 生产环境配置具体域名
                .setAllowedOrigins("*");//也可配置适配所有域名,生产环境不建议
    }

    @Bean
    public WebSocketHandler photoWebSocketHandler() {
        return new PhotoWebSocketHandler();
    }
}

/**
 * 照片推送WebSocket处理器
 */
public class PhotoWebSocketHandler extends TextWebSocketHandler {
    private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        // 每3秒推送一次最新照片
        executor.scheduleAtFixedRate(() -> {
            try {
                // 1. 获取最新照片
                byte[] photoBytes = getLatestPhoto();
                
                // 2. 转换为Base64字符串
                String base64Photo = Base64.getEncoder().encodeToString(photoBytes);
                
                // 3. 推送给前端
                session.sendMessage(new TextMessage(base64Photo));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 0, 3, TimeUnit.SECONDS);
    }

    /**
     * 获取最新照片(示例方法)
     * @return 照片字节数组
     * @throws IOException IO异常
     */
    private byte[] getLatestPhoto() throws IOException {
        File latestPhoto = new File("photos/latest.jpg");
        return Files.readAllBytes(latestPhoto.toPath());
    }
}
javascript 复制代码
<img id="realTimePhoto" alt="实时照片">
<script>
    const ws = new WebSocket('ws://localhost:8080/photo/ws');
    const imgElement = document.getElementById('realTimePhoto');
    
    ws.onmessage = function(event) {
        // 接收Base64照片并更新
        imgElement.src = 'data:image/jpeg;base64,' + event.data;
    };
    
    ws.onclose = function() {
        console.log('WebSocket连接已关闭');
    };
</script>
相关推荐
小新讲网安7 分钟前
WiFi安全攻防实战:WPA3新协议与传统破解技术全解析
开发语言·网络·安全·php·漏洞·nmap·漏洞检测
必须会一定会6 小时前
Agent Plugins 1.0实战:plugin.json、skills、mcp.json目录结构与迁移
开发语言·人工智能·ai编程
St_rive6 小时前
Page Object设计模式
java·开发语言·设计模式
wp123_16 小时前
硬件元器件笔记|IPX8 防水 Type‑C 母座安费诺 124018802112A 与 TONEVEE TY48086‑24A 分析
c语言·开发语言·笔记
wuyk5556 小时前
4.树:一对多的层次数据结构
开发语言·数据结构·stm32·单片机
风流 少年7 小时前
Spring AI 2.0:SSE
java·人工智能·spring
凤山老林7 小时前
精细化流量治理:Spring Boot 动态特性开关与灰度发布体系
java·spring boot·后端
luj_17688 小时前
桥牌思维启示:系统设计的模块化架构
c语言·开发语言·c++·经验分享·算法
小小龙学IT9 小时前
Boost.Beast 深度实战:基于 Asio 的开源 C++ HTTP/WebSocket 协议库
c++·websocket·http