说到 WebSocket,估计不少开发者都有过这样的经历:在构建实时通信应用时,使用 WebSocket 的心情,简直就像是站在吃到一颗糖果的路口,盯着前方的一大堆 API 文档不知所措。😅
但是,WebSocket 真的很重要啊!它为我们提供了持久的全双工通信,特别适合实时聊天、即时通知、直播推送等应用场景。
你说,你想用 WebSocket 构建一个高效的实时系统,来个高并发、低延迟的数据传输,结果发现一堆框架和方式让你头晕转向,不知道从何下手。
这篇文章就来解开 WebSocket 集成的那点事儿,告诉你有哪些常见的集成方式,如何在 Spring Boot 中实现,甚至不止于此,还能聊聊那些不依赖 Spring 的集成方式。
1. Javax WebSocket:标准化的 WebSocket 方案
Javax WebSocket 是 Java 官方的 WebSocket 标准。它的最大优点是:简单、标准化,能支持原生的 WebSocket 客户端和服务器通信,适用于大多数纯 Java 应用。如果你是一个“纯净”主义者,想要一个不依赖 Spring 的方案,那 Javax WebSocket 完全能满足你。
服务端配置
我们可以使用 @ServerEndpoint
注解来定义 WebSocket 服务端点。并且提供了多种注解来处理连接、消息、错误等回调事件。
例如,定义一个简单的 WebSocket 服务端:
@Component
@ServerEndpoint("/websocket/{type}")
public class JavaxWebSocketServerEndpoint {
@OnOpen
public void onOpen(Session session, EndpointConfig config, @PathParam("type") String type) {
// 连接建立时的回调
System.out.println("连接建立:类型 = " + type);
}
@OnClose
public void onClose(Session session, CloseReason reason) {
// 连接关闭时的回调
System.out.println("连接关闭:" + reason.getReasonPhrase());
}
@OnMessage
public void onMessage(Session session, String message) {
// 接收消息的回调
System.out.println("收到消息: " + message);
}
@OnError
public void onError(Session session, Throwable e) {
// 错误处理
System.out.println("发生错误: " + e.getMessage());
}
}
为了启用 Javax WebSocket 端点,我们还需要配置 ServerEndpointExporter
:
@Configuration
public class JavaxWebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
客户端配置
客户端也可以使用类似的方式来处理 WebSocket 连接。我们使用 @ClientEndpoint
注解来定义客户端行为。
@ClientEndpoint
public class JavaxWebSocketClientEndpoint {
@OnOpen
public void onOpen(Session session) {
// 连接建立时的回调
System.out.println("连接已建立!");
}
@OnClose
public void onClose(Session session, CloseReason reason) {
// 连接关闭时的回调
System.out.println("连接关闭:" + reason.getReasonPhrase());
}
@OnMessage
public void onMessage(Session session, String message) {
// 接收到消息时的回调
System.out.println("接收到消息: " + message);
}
@OnError
public void onError(Session session, Throwable e) {
// 错误处理
System.out.println("发生错误: " + e.getMessage());
}
}
客户端的连接过程则是通过 WebSocketContainer
完成的:
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
Session session = container.connectToServer(JavaxWebSocketClientEndpoint.class, uri);
2. Spring WebMVC:经典的 WebSocket 集成
如果你已经在 Spring Boot 中使用了 WebMVC(大多数人都是),那么你可以利用 Spring 提供的 WebSocket 集成支持,使用 WebSocketHandler
来处理消息。
服务端配置
你需要实现一个 WebSocketHandler
,并注册到 Spring 的 WebSocket 配置中:
public class ServletWebSocketServerHandler implements WebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 连接建立
System.out.println("连接已建立");
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
// 接收消息
System.out.println("接收到消息: " + message.getPayload());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
// 连接关闭
System.out.println("连接关闭");
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
然后在 Spring 配置中,使用 @EnableWebSocket
启用 WebSocket 支持:
@Configuration
@EnableWebSocket
public class ServletWebSocketServerConfigurer implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new ServletWebSocketServerHandler(), "/websocket")
.setAllowedOrigins("*");
}
}
客户端配置
在客户端,Spring 也提供了 WebSocketHandler
方式来进行通信,示例如下:
public class ServletWebSocketClientHandler implements WebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 连接建立
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
// 接收消息
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
// 连接关闭
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
3. Spring WebFlux:适应高并发的 WebSocket 集成
如果你对反应式编程情有独钟,或者你的应用需要处理高并发、异步的请求,Spring WebFlux 会是一个不错的选择。
服务端配置
WebFlux 中的 WebSocket 集成与传统 WebMVC 很相似,不过,它使用的是反应式的 Mono
和 Flux
来处理消息的发送和接收。
public class ReactiveWebSocketServerHandler implements WebSocketHandler {
@NonNull
@Override
public Mono<Void> handle(WebSocketSession session) {
Mono<Void> send = session.send(Flux.create(sink -> {
// 发送消息
}));
Mono<Void> receive = session.receive()
.doOnNext(message -> {
// 处理接收到的消息
})
.doOnError(Throwable::printStackTrace)
.then();
return Mono.zip(send, receive).then();
}
}
然后,你需要通过 HandlerMapping
来注册 WebSocket 处理器:
@Component
public class ReactiveWebSocketServerHandlerMapping extends SimpleUrlHandlerMapping {
public ReactiveWebSocketServerHandlerMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/websocket/**", new ReactiveWebSocketServerHandler());
setUrlMap(map);
setOrder(100);
}
}
客户端配置
WebFlux 的客户端配置也是基于 WebSocketHandler
和 WebSocketSession
:
public class ReactiveWebSocketClientHandler implements WebSocketHandler {
@NonNull
@Override
public Mono<Void> handle(WebSocketSession session) {
Mono<Void> send = session.send(Flux.create(sink -> {
// 发送消息
}));
Mono<Void> receive = session.receive()
.doOnNext(message -> {
// 处理接收到的消息
})
.doOnError(Throwable::printStackTrace)
.then();
return Mono.zip(send, receive).then();
}
}
WebSocketClient client = new ReactorNettyWebSocketClient();
WebSocketHandler handler = new ReactiveWebSocketClientHandler();
client.execute(uri, handler).subscribe();
4. 总结:选择合适的 WebSocket 集成方式
不同的 WebSocket 集成方式适合不同的场景:
Javax WebSocket:适合纯 Java 应用,不依赖于 Spring,简单直接。 Spring WebMVC:适合传统基于 Servlet 的 Web 应用,容易上手,适合大多数 Spring Boot 项目。 Spring WebFlux:适合高并发、异步场景,特别适合反应式编程需求。
无论是哪种方式,WebSocket 都是实现实时通信的利器。在选择时,根据项目的需求、并发量、技术栈来决定使用哪种集成方式。总之,WebSocket 的优势,别说我没告诉你,真的是太爽了!😎
对编程、职场感兴趣的同学,可以链接我,微信:coder301 拉你进入“程序员交流群”。