学 无 止 境 , 与 君 共 勉 。
用途
- 实时获取服务端的最新数据
- 查看调度任务的进度和执行状态
- 用户感知:修改数据后,相关用户收到信息
- 提升用户体验:耗时业务异步处理(Excel导入导出,复杂计算)
前端轮询
这种方式实现简单,前端通过setInterval
定时去请求接口来获取最新的数据,当实时性要求不高,更新频率低的情况下可以使用这种方式。但是当实时性很高的时候,我们的请求会很频繁,服务器的消耗非常大,而且每次请求的时候服务端的数据可能还没有改变,导致很多请求都是没有意义的。
setInterval(function () {
// 请求接口操作
// 。。。
},
3000
);
webSocket
WebSocket是基于TCP协议的,它是全双工通信的,服务端可以向客户端发送信息,客户端同样可以向服务器发送指令,常用于聊天应用中。
pom.xml
SpringBoot提供了websocket的starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
config类
注入ServerEndpointExporter
,这个bean会自动注册使用了@ServerEndpoint
注解声明的Websocket endpoint
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
server类
创建一个服务类:
- 加上
@ServerEndpoint
注解,设置WebSocket连接点的服务地址。 - 创建
AtomicInteger
用于记录连接数 - 创建
ConcurrentHashMap
用于存放连接信息 @OnOpen
注解表明该方法在建立连接后调用@OnClose
注解表明该方法在断开连接后调用@OnError
注解表明该方法在连接异常调用@OnMessage
注解表明该方法在收到客户端消息后调用- 创建推送信息的方法
- 创建移除连接的方法
@ServerEndpoint("/websocket/{userId}")
@Component
public class WebSocketServer {
private final static Logger logger = LoggerFactory.getLogger(WebSocketServer.class);
/**
* 当前连接数
*/
private static AtomicInteger count = new AtomicInteger(0);
/**
* 使用map对象,便于根据userId来获取对应的WebSocket,或者放redis里面
*/
private static Map<String, WebSocketServer> websocketMap = new ConcurrentHashMap<>();
/**
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
private Session session;
/**
* 对应的用户ID
*/
private String userId = "";
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
try {
this.session = session;
this.userId = userId;
websocketMap.put(userId, this);
// 数量+1
count.getAndIncrement();
logger.info("websocket 新连接:{}", userId);
} catch (Exception e) {
logger.error("websocket 新建连接 IO异常");
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
// 删除
websocketMap.remove(this.userId);
// 数量-1
count.getAndDecrement();
logger.info("close websocket : {}", this.userId);
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message) {
logger.info("来自客户端{}的消息:{}", this.userId, message);
}
@OnError
public void onError(Throwable error) {
logger.info("websocket 发生错误,移除当前websocket:{},err:{}", this.userId, error.getMessage()