在《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 {@Beanpublic 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@OnOpenpublic void onOpen(Session session, @PathParam(value = "userId") String userId){sessionPools.put(userId, session);// WebSocket onOpen implementation}@OnClosepublic void onClose(Session session, @PathParam(value = "userId") String userId){// WebSocket onClose implementation}// Other WebSocket methods@OnMessagepublic void onMessage(Session session, String message, @PathParam(value = "userId") String userId){// WebSocket onMessage implementationfor (Session s : sessionPools.values()) {if (s.equals(session)) {continue;}s.getAsyncRemote().sendText(userId+" said: " + message);}}@OnErrorpublic void onError(Session session, Throwable throwable, @PathParam(value = "userId") String userId){// WebSocket onError implementation}
}
测试