springboot如何整合SSE向客户端推送消息

后端 潘老师 3个月前 (11-14) 105 ℃ (0) 扫码查看

本文重点讲解springboot如何整合SSE实现服务端向客户端推送消息的内容,大家一起来学习下!

SSE是什么?

很多人可能不知道,除了WebSocket这种广为人知的机制,还有另一种服务器向客户端推送消息的技术,那就是服务器发送事件(Server-sent Events,简称SSE)。

SSE是基于HTTP协议的,我们知道一般的HTTP协议是无法实现服务端主动向客户端推送消息的,但SSE是个例外。它打破常规,在服务器和客户端之间建立了一个单向通道,服务端响应的不再是一次性的数据包,而是text/event-stream类型的数据流信息。一旦有数据变更,就会从服务器流式传输到客户端。

这个过程有点类似于在线视频播放,视频流会连续不断的推送到浏览器。你也可以想象成,客户端在完成一次长时间的下载。

SSE与WebSocket都能建立服务端与浏览器之间的通信,实现服务端向客户端推送消息。但是它们有些许不同:

  • 首先,SSE是基于HTTP协议的,这意味着它们不需要特殊的协议或服务器实现即可工作。然而,WebSocket需要单独的服务器来处理协议。
  • 其次,SSE是单向通信,只能由服务端向客户端单向通信。而WebSocket则是全双工通信,即通信的双方可以同时发送和接受信息。
  • 再者,SSE实现简单,开发成本低,无需引入其他组件。而WebSocket传输数据需做二次解析,开发门槛高一些。
  • 此外,SSE默认支持断线重连,而WebSocket则需要自己实现。
  • 最后,SSE只能传送文本消息,二进制数据需要经过编码后传送。而WebSocket默认支持传送二进制数据。

前端代码实现

<script>
    let source = null;
    let userId = 7777
    if (window.EventSource) {
        // 建立连接
        source = new EventSource('http://localhost:7777/sse/sub/'+userId);
        setMessageInnerHTML("连接用户=" + userId);
        /**
         * 连接一旦建立,就会触发open事件
         * 另一种写法:source.onopen = function (event) {}
         */
        source.addEventListener('open', function (e) {
            setMessageInnerHTML("建立连接。。。");
        }, false);
        /**
         * 客户端收到服务器发来的数据
         * 另一种写法:source.onmessage = function (event) {}
         */
        source.addEventListener('message', function (e) {
            setMessageInnerHTML(e.data);
        });
    } else {
        setMessageInnerHTML("你的浏览器不支持SSE");
    }
<script>

springboot代码实现

@RestController
@CrossOrigin
@RequestMapping
public class SSEControler {
    //建立之后根据订单id,将SseEmitter存到ConcurrentHashMap
    //正常应该存到数据库里面,生成数据库订单,这里我们只是模拟一下
    public static final ConcurrentHashMap<Long, SseEmitter> sseEmitters
            = new ConcurrentHashMap<>();
​
    //第2步:接受用户建立长连接,表示该用户已支付,已支付就可以生成订单(未确认状态)
    @GetMapping("/orderpay")
    public SseEmitter orderpay(Long payid) {
        //设置默认的超时时间60秒,超时之后服务端主动关闭连接。
        SseEmitter emitter = new SseEmitter(60 * 1000L);
        sseEmitters.put(payid,emitter);
        emitter.onTimeout(() -> sseEmitters.remove(payid));
        return emitter;
    }
​
    //第3步:接受支付系统的支付结果告知,表明用户支付成功
    @GetMapping("/payback")
    public void payback (Long payid){
        //把SSE连接取出来
        SseEmitter emitter = sseEmitters.get(payid);
        try {
            //第4步:由服务端告知浏览器端:该用户支付成功了
            emitter.send("用户支付成功"); //触发前端message事件。
            //触发前端自定义的finish事件
            emitter.send(SseEmitter.event().name("finish").id("6666").data("哈哈"));
        } catch (IOException e) {
            emitter.completeWithError(e);   //出发前端onerror事件
        }
    }
}

以上就是springboot如何整合SSE向客户端推送消息的全部内容,你学会了吗?


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/11198.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】