使用SpringBoot + SSE服务器数据推送
- 前景+解决方案
- 解决方案存在的问题
- 使用SSE注意事项
- 原生使用
- Spring 提供的 SseEmitter
- SseEmitter具体使用
- 使用思路
- 完结
前景+解决方案
项目中使用到了服务器向前端实时推送消息。场景解决方案:
1、前端使用短时间的定时器,轮训访问后端,每次访问更新数据或根据标识更新部分信息
2、众所周知的 WebSocket
3、比较新的技术,SSE
解决方案存在的问题
1、前端使用定时器轮训:
优点:一定程度上,减少代码开发维护,大部分中小公司都采取这种《敏捷》开发方案(个人经历)
缺点:实时性欠缺。虽然现在的HTTP默认长链接缓存,每次请求不需要经历多次握手,但是会有请求头+响应头等信息,还是浪费不必要的带宽(带宽是很宝贵的,财大气粗者忽略)。前端使用定时器不当,会造成页面卡顿或崩掉现象。
2、WebSocket 双向通道
优点:实时性,大众化,社区活跃,解决问题方便。
缺点:整合项目时稍重,引入依赖+添加相关配置+链接代码维护(忽略相关配置),功能过大,大部分的项目是服务器端向前端推送,webSocket是双向推送。
3、SSE
优点:单向推送,无需整合,spring boot 提供现成功能。
缺点:存在bug较多,社区较少,出现问题不好找到解决方案。
使用SSE注意事项
原生使用
原生的使用是基于对头信息的修改。
// 一般的使用方式
@RequestMapping(value="/push",produces="text/event-stream;charset=utf-8")
@ResponseBody
public String push() {
Random r = new Random();
try {
(5000);
} catch (InterruptedException e) {
// ignore
}
return "data:Testing 1,2,3" + () +"\n\n";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
注意:
1、SSE 头信息 produces=“text/event-stream;charset=utf-8” 是必须的
2、响应是以 \n\n 结尾
这里只是一个简单的Demo,基于原生使用,明显不足。
Spring 提供的 SseEmitter
简书上的demo使用spring提供的工具类使用方便。
问题:不能完成我们项目的业务,实时推送。
SseEmitter具体使用
send() - 发送消息
complete() - 如果调用此方法,再次发送数据消息时会报错。如果提送多次数据,尽量不要调用此方法。
onCompletion() - 监听消息发送完成/异常时会触发。
spring官方文档api解释
使用思路
问题:前端断开后,后台无法监听或接收到信息。
当获取一个链接时,将SseEmitter存储至容器中,并且主动推送一次消息。
在存储之前添加onCompletion(),会在发送数据完成或异常时,移除容器中的SseEmitter
当需要推送时,根据标识从容器中获取SseEmitter,调用send()【这里建议使用观察者模式】
完结
本篇章个人使用经验所得,对源码还没有进行分析。
如果有不对的地方,大家多多指点。