一、导包
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.6.4</version>
</dependency>
二、编写WebSocketConfig
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
三、编写WebSocketServer
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
*/
@Component
@Slf4j
@ServerEndpoint("/v1/websocket/connect/{userId}")
public class WebSocketServer{
// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的
private static int onlineCount = 0;
// concurrent包的线程安全Set,用来存放每个客户端对应的webSocket对象
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
// 与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
// 接收userId
private Long userId;
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") Long userId) {
this.session = session;
this.userId = userId;
// 加入set中
webSocketSet.add(this);
addOnlineCount();
log.info("【websocket】有新的连接,连接的userId为:{},当前在线人数为:{}", userId, getOnlineCount());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
// 从set中删除
webSocketSet.remove(this);
subOnlineCount();
log.info("【websocket】断开连接,释放的userId为:{},当前在线人数为:{}", userId, getOnlineCount());
}
/**
* 连接错误调用的方法
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("【websocket】连接发生错误");
error.printStackTrace();
}
/**
* 收到客户端消息后调用的方法
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("【websocket】接收到来自客户端:{} 的消息:{}", userId, message);
//群发消息
// for (WebSocketServer item : webSocketSet) {
// try {
// item.sendMessage(message);
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
}
/**
* 服务端推送消息
*/
private void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 群发消息
* @param message 推送消息
*/
public void sendInfo(String message){
log.info("【websocket】群发消息,推送内容:{}",message);
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
/**
* 指定发送消息(一个)
* @param message 推送消息
* @param userId 接收人userId
*/
public void sendDesignateInfo(String message, Long userId){
log.info("【websocket】指定发送消息(一个),接收userId:{},推送内容:{}", userId, message);
for (WebSocketServer item : webSocketSet) {
if (item.userId.equals(userId)){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 指定发送消息(多个)
* @param message 推送消息
* @param userIds 接收人userId集
*/
public void sendDesignateInfo(String message, List<Long> userIds){
log.info("【websocket】指定发送消息(多个),接收userIds:{},推送内容:{}", userIds.toString(), message);
for (WebSocketServer item : webSocketSet) {
if (userIds.contains(item.userId)){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 获取在线人数
*/
private static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* 在线人数+1
*/
private static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
/**
* 在线人数-1
*/
private static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
/**
* 获取websocket集
*/
private static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
return webSocketSet;
}
@Override
public int hashCode() {
return Objects.hash(session, userId);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
WebSocketServer that = (WebSocketServer) o;
return Objects.equals(session, that.session) && Objects.equals(userId, that.userId);
}
}
四、ApiPost简单测试
五、简单使用
webSocketServer.sendDesignateInfo(JSON.toJSONString(sysMsg),userIdList);