Springboot -- Server-send Event(SSE)服务推送事件

什么是SSE

       Server-Sent Event 网页可以获取由服务器主动推送的数据。

SSE的作用

       从他的解释中可以看出,SSE可以实现由服务器主动向前端推送数据,因此可以实现某些需要持续获取数据的情形。
       比如在文件上传时,一些较大的文件可能上传缓慢,我们不可能让客户一直等待至上传结束才知道上传结果,这样对用户的体验是恐怖的,更是不合理的。我们需要让用户了解实时的上传进度,并在上传过程中出现异常时可以及时报错。
在这里插入图片描述       或许我们可以为本次上传任务记录唯一的任务ID,并将任务另起线程执行,计算本次任务的上传进度、获取任务之行的状态等信息,存入缓存。提供一个可以根据任务ID查询任务进度和状态的接口,并通知前端轮询查询任务进度。
       上面的方法,需要前端不断轮询并创建HTTP链接,而且一般还需要介入第三方数据库,如Redis来存储我们的任务信息,实现起来也比较麻烦。但是通过SSE我们可以很简单的来实现由服务端推送的实时数据。

SSE的优点

SSE部署在 HTTP协议之上,现有的服务器软件都支持。
SSE是一个轻量级协议,相对简单。
SSE默认支持断线重连。

简单示例代码

服务端
  • 服务端必须标注前端需要准备接受text/event-stream类型的数据,produces = MediaType.TEXT_EVENT_STREAM_VALUE
  • 服务端在最后返回一个stop事件,用作前端判断事件结束
    @GetMapping(value = "streamtest/{length}",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<Object>> streamtest(@PathVariable("length") int length){

			//返回一个流 根据传入的长度n,我们每间隔一秒返回n条信息
			//事件名称默认都是message,最后添加一个stop事件
        Flux result = Flux.fromStream(IntStream.rangeClosed(1,length+1).boxed().map(
                i->{
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                    }
                    if(i>length)
                        //最后增加一个事件信息 用来通知前端不要再重复请求后台了
                        return ServerSentEvent.<Object>builder()
                                .event("stop") //和前端addEventListener监听的事件一一对应
                                .data(-1)//ServerSentEvent必须要传data,否在前台接受不到
                                .build();
                    else
                        return String.format("测试数据%d",i);
                }
        ));

        return result;
    }
客户端
  • 前端在接受完服务端的数据后,会自动重连再次请求服务,因此我们需要手动关闭
//判断浏览器是不是支持SSE
if (window.EventSource) {
  // 创建 EventSource 对象连接服务器
  const source = new EventSource('http://localhost:8090/server/test/streamtest/3');

  // 连接成功窒触发open事件
  source.addEventListener('open', () => {
    console.log('Connected');
  }, false);

  // 服务器发送信息到客户端时,如果没有 event 字段,默认会触发 message 事件
  source.addEventListener('message', e => {
    console.log(`data: ${e.data}`);
  }, false);

  // 自定义 EventHandler,在收到 event 字段为 stop 的消息时触发
  //在这里我们将SSE关闭
  source.addEventListener('stop', e => {
    source.closed();
    console.log('Closed'); 
  }, false);

  // 连接异常时会触发 error 事件并自动重连
  source.addEventListener('error', e => {
    if (e.target.readyState === EventSource.CLOSED) {
      console.log('Disconnected');
    } else if (e.target.readyState === EventSource.CONNECTING) {
      console.log('Connecting...');
    }
  }, false);
} else {
  console.error('Your browser doesn\'t support SSE');
}
结果

>Connected
>data: 测试数据1
>data: 测试数据2
>data: 测试数据3
>Closed

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mingvvv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值