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>