大纲
- 依赖
- 自动注册端点
- 端点
- 测试
在 《Websocket在Java中的实践——握手拦截器》中我们使用握手拦截器实现了路径解析的工作。这个过程略显复杂,因为路径解析这样比较底层的工作应该由框架来解决,而不应该交由开发者来做。本文介绍的自动注册端点的功能就可以很优雅的解决这个问题。
依赖
在pom.xml中新增
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
自动注册端点
当Spring容器启动时,serverEndpointExporter会扫描所有带有@ServerEndpoint注解的类,并将这些类注册为WebSocket端点,这样客户端就可以通过相应的URL与这些端点建立WebSocket连接。
package com.nyctlc.endpointexporter.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
端点
@ServerEndpoint是一个注解,用于声明一个类为WebSocket服务器端点。在Java中,特别是在使用Jakarta WebSocket API(之前称为Java API for WebSocket)时,这个注解非常关键。通过使用@ServerEndpoint注解,可以将一个普通的类转变为WebSocket服务器端点,从而能够处理WebSocket连接、消息和其他事件。
package com.nyctlc.endpointexporter.handler;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.stereotype.Component;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocketHandler {
private static final ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();
// WebSocket handler implementation
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId){
sessionPools.put(userId, session);
// WebSocket onOpen implementation
}
@OnClose
public void onClose(Session session, @PathParam(value = "userId") String userId){
// WebSocket onClose implementation
}
// Other WebSocket methods
@OnMessage
public void onMessage(Session session, String message, @PathParam(value = "userId") String userId){
// WebSocket onMessage implementation
for (Session s : sessionPools.values()) {
if (s.equals(session)) {
continue;
}
s.getAsyncRemote().sendText(userId+" said: " + message);
}
}
@OnError
public void onError(Session session, Throwable throwable, @PathParam(value = "userId") String userId){
// WebSocket onError implementation
}
}
测试