导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
使用@ServerEndpoint注解
使用@ServerEndpoint注解的类是由WebSocket容器管理的,而不是由Spring容器管理的。因此,在@ServerEndpoint注解的类中,你不能直接注入其他Spring管理的Bean。
如果需要使用其它的bean,可以通过ApplicationContext上下文来获取指定的bean,网络上有很多这样的工具类,就不拿出来了。
- 创建ConsoleWebSocket类
@Slf4j
@ServerEndpoint(value = "/websocket/1")
@Component
public class ConsoleWebSocket {
/**
* 记录当前在线连接数
*/
private static AtomicInteger onlineCount = new AtomicInteger(0);
/**
* 存放所有在线的客户端
*/
private static Map<String, Session> clients = new ConcurrentHashMap<>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
onlineCount.incrementAndGet(); // 在线数加1
clients.put(session.getId(), session);
log.info("有新连接加入:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
onlineCount.decrementAndGet(); // 在线数减1
clients.remove(session.getId());
log.info("有一连接关闭:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
/**
* 收到客户端消息 后调用的方法
*
* @param message
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
this.sendMessage("Hello, " + message, session);
}
/**
* 服务端发送消息给客户端
*/
public void sendMessage(String message, Session toSession) {
try {
log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getBasicRemote().sendText(message);
} catch (Exception e) {
log.error("服务端发送消息给客户端失败:{}", e);
}
}
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误");
error.printStackTrace();
}
/**
* 群发消息
*
* @param message
*/
public void sendMessageExcludeMe(String message, Session fromSession) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
Session toSession = sessionEntry.getValue();
// 排除掉自己
if (!fromSession.getId().equals(toSession.getId())) {
log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getAsyncRemote().sendText(message);
}
}
}
/**
* 群发消息,包括自己
*
* @param message
*/
public void sendMessageAll(String message) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
Session toSession = sessionEntry.getValue();
log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getAsyncRemote().sendText(message);
}
}
- 定义websocket配置类
注意:
ServerEndpointExporter是Spring对WebSocket的支持类,它会自动注册被@ServerEndpoint注解标记的类作为WebSocket端点。你可以将它作为一个@Bean来配置和启用WebSocket端点。
@Configuration
public class WebSocketConfig{
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
使用 WebSocketConfigurer 配置方式
这种方式是由spring容器管理的,所以可以在WebSocketHandler放心的注入Bean
- WebSocketConfig
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Resource
private WebSocketHandler webSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler, "/websocket").setAllowedOrigins("*");
}
}
- WebSocketHandler
@Slf4j
@Component
public class WebSocketHandler extends TextWebSocketHandler {
@Resource
HelloService helloService;
@Override
public void afterConnectionEstablished(WebSocketSession session) {
// 连接建立时调用该方法
// 可以在这里进行一些初始化操作
log.info("链接了来了:{}", session);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
// 处理接收到的文本消息
String payload = message.getPayload();
// 可以在这里进行消息处理和发送消息给客户端
log.info("接受到文本消息:{}", payload);
sendMessageClient(session, "hello");
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// 客户端断开连接时调用该方法
// 可以在这里进行一些清理操作或者记录日志等
log.info("断开链接:{}", session);
}
private void sendMessageClient(WebSocketSession session, String message) throws IOException {
session.sendMessage(new TextMessage(message));
}
}
评论区