作者:被摸的鱼
在我多年的开发生涯中,经常遇到需要实现实时通信的场景。早期我们通常使用轮询或长轮询方式,但这些方案都存在资源浪费的问题。直到遇见了 WebSocket,它让服务器和客户端之间的双向通信变得如此优雅。今天就和大家分享如何使用 Java WebSocket API 开发实时通信应用。
一、准备工作
1.1 环境要求
JDK 8+
Maven 3.6+
IDE(推荐使用 IDEA)
1.2 Maven 依赖
<dependency>
javax.websocket
javax.websocket-api
1.1
provided </dependency>
<!-- 如果是独立运行的项目,需要添加以下依赖 -->
<dependency>
org.glassfish.tyrus
tyrus-server
2.1.3 </dependency>
<dependency>
org.glassfish.tyrus
tyrus-container-grizzly-server
2.1.3 </dependency>
二、基本用法
2.1 创建 WebSocket 服务端
@ServerEndpoint(“/chat”)
public class ChatEndpoint {
private static final Set
sessions = Collections.synchronizedSet(new HashSet<>()); @OnOpen
public void onOpen(Session session) {
sessions.add(session);
System.out.println(“新连接加入,当前连接数:” + sessions.size());
}
@OnMessage
public void onMessage(String message, Session session) {
// 广播消息给所有连接的客户端
for (Session s : sessions) {
try {
s.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@OnClose
public void onClose(Session session) {
sessions.remove(session);
System.out.println(“连接断开,当前连接数:” + sessions.size());
}
@OnError
public void onError(Session session, Throwable error) {
System.err.println(“发生错误:” + error.getMessage());
}
}
2.2 启动 WebSocket 服务器
public class WebSocketServer {
public static void main(String[] args) {
Server server = new Server(“localhost”, 8025, “/websocket”, null, ChatEndpoint.class);
try {
server.start();
System.out.println(“WebSocket 服务器已启动,按回车键退出...”);
System.in.read();
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}
}
}
三、进阶用法
3.1 自定义消息处理
public class Message {
private String type;
private String content;
private String sender;
// getter 和 setter 略
}
@ServerEndpoint(value = “/chat”, decoders = {MessageDecoder.class}, encoders = {MessageEncoder.class})
public class EnhancedChatEndpoint {
@OnMessage
public void onMessage(Message message, Session session) {
switch (message.getType()) {
case “CHAT”:
broadcastMessage(message);
break;
case “JOIN”:
handleJoin(message, session);
break;
default:
// 处理其他类型消息
break;
}
}
// 其他方法略
}
3.2 心跳检测机制
@ServerEndpoint(“/chat”)
public class HeartbeatEndpoint {
private static final long HEARTBEAT_TIMEOUT = 30000; // 30秒
@Schedule(fixedRate = 10000) // 每10秒检查一次
public void checkHeartbeat() {
long now = System.currentTimeMillis();
sessions.forEach(session -> {
Long lastPing = (Long) session.getUserProperties().get(“lastPing”);
if (lastPing != null && now - lastPing > HEARTBEAT_TIMEOUT) {
try {
session.close(new CloseReason(
CloseReason.CloseCodes.GOING_AWAY,
“心跳超时”
));
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
四、实际案例
4.1 实时聊天室
@ServerEndpoint(“/chatroom”)
public class ChatRoomEndpoint {
private static final Map
rooms = new ConcurrentHashMap<>(); ,>@OnMessage
public void onMessage(String message, Session session) {
JsonObject jsonMessage = Json.createReader(
new StringReader(message)).readObject();
String roomId = jsonMessage.getString(“roomId”);
String content = jsonMessage.getString(“content”);
Room room = rooms.computeIfAbsent(roomId, k -> new Room());
room.broadcast(content, session);
}
private static class Room {
private final Set
sessions = CopyOnWriteArraySet<>(); public void broadcast(String message, Session sender) {
sessions.forEach(session -> {
try {
if (session != sender) {
session.getBasicRemote().sendText(message);
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
}
4.2 实时股票行情推送
@ServerEndpoint(“/stock/{symbol}”)
public class StockEndpoint {
private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
@OnOpen
public void onOpen(@PathParam(“symbol”) String symbol, Session session) {
scheduler.scheduleAtFixedRate(() -> {
try {
// 模拟获取股票数据
double price = 100 + Math.random() * 10;
session.getBasicRemote().sendText(
String.format(“股票%s: %.2f”, symbol, price)
);
} catch (IOException e) {
e.printStackTrace();
}
}, 0, 1, TimeUnit.SECONDS);
}
@OnClose
public void onClose() {
scheduler.shutdown();
}
}
五、总结
Java WebSocket API 为我们提供了一种优雅的实时通信解决方案。它的核心优势在于:
全双工通信,性能高效
API 简单直观,易于使用
基于事件驱动,代码结构清晰
可以轻松集成到现有项目中
在实际开发中,建议注意以下几点:
合理管理 WebSocket 连接,及时释放资源
实现心跳机制,保持连接稳定性
考虑并发安全,使用线程安全的集合
做好异常处理和日志记录
本文介绍了 Java WebSocket API 的核心特性和实践应用。在实际开发中,建议读者结合项目需求选择合适的特性,同时关注官方文档获取最新更新。如有问题,欢迎在评论区交流讨论。祝各位开发愉快!