软件开发定制Springboot集成SSE实现消息推送之单工通信

前言

软件开发定制通常在一些web项目中,软件开发定制会涉及到想客户端推送消息,常见的有Ajax轮询、webSocket,软件开发定制本篇文章主要使用Springboot集成SSE软件开发定制实现向客户端持续推送信息。

SSE简介

软件开发定制服务发送事件SSE(Sever-Sent Event),就是基于 HTTP 的技术,软件开发定制浏览器向服务器发送一个保持长连接HTTP请求,服务器单向地向客户端以流形式持续传输数据 。这样可以节约网络资源,不需要建立新连接。

优点

服务端不需要其他的类库,开发难度较低。
不用每次建立新连接,延迟较低。
数据通过简单且广泛使用的HTTP协议而不是专有协议进行同步。

对重新建立连接和事件ID功能的内置支持。

对于利用单向通信的应用程序和服务非常有用。

缺点

客户端越多连接越多,会占用服务器大量内存和连接数。

SSE只支持UTF-8编码,不支持二进制数据。

对最大打开连接数的严格限制可能使事情变得困难,每个浏览器都设置了限制。

SSE是单向的。

Springboot集成SSE简约版

客户端发送请求到服务端,服务端以流的形式不断向客户端推送数据示例,增加帅气值。

xml依赖:

<dependency>	<groupId>org.springframework.boot</groupId>	<artifactId>spring-boot-starter-web</artifactId></dependency>
  • 1
  • 2
  • 3
  • 4

html代码:

<!DOCTYPE html><html><head>    <meta charset="UTF-8">    <title>Springboot集成SSE简约版</title>    <script type="text/javascript">        let source = new EventSource('/get');        source.onmessage = function (event) {            console.info(event.data);            document.getElementById('text').innerText = event.data        };    </script></head><body><div id="text"></div></body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

后端代码:

   @RequestMapping(value = "/get", produces = "text/event-stream;charset=UTF-8")    public void push(HttpServletResponse response) {        response.setContentType("text/event-stream");        response.setCharacterEncoding("utf-8");        int i = 0;        while (true) {            try {                Thread.sleep(1000);                PrintWriter pw = response.getWriter();                //注意返回数据必须以data:开头,"\"结尾                pw.write("data:xdm帅气值加" + i + "\");                pw.flush();                //检测异常时断开连接                if (pw.checkError()) {                    log.error("客户端断开连接");                    return;                }            } catch (Exception e) {                e.printStackTrace();            }            i++;        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

效果:

Springboot集成SSE升级版

演示SSE的连接建立、接收数据和异常情况监听处理。

注:若浏览器不兼容在页面引入。

<script src=/eventsource-polyfill.js></script>
  • 1

客户端代码:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title> Springboot集成SSE升级版</title></head><script>    let source = null;    const clientId = new Date().getTime();    if (!!window.EventSource) {        source = new EventSource('/sse/create?clientId=' + clientId);    	//建立连接        source.onopen = function (event) {            setMessageInnerHTML("建立连接" + event);        }        //接收数据        source.onmessage = function (event) {            setMessageInnerHTML(event.data);        }        //错误监听        source.onerror = function (event) {            if (event.readyState === EventSource.CLOSED) {                setMessageInnerHTML("连接关闭");            } else {                console.log(event);            }        }    } else {        setMessageInnerHTML("浏览器不支持SSE");    }    window.onbeforeunload = function () {        close();    };    // 关闭    function close() {        source.close();        const httpRequest = new XMLHttpRequest();        httpRequest.open('GET', '/sse/close/?clientId=' + clientId, true);        httpRequest.send();        console.log("close");    }    // 显示消息    function setMessageInnerHTML(innerHTML) {        document.getElementById('text').innerHTML += innerHTML + '<br/>';    }</script><body><button onclick="close()">关闭连接</button><div id="text"></div></body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

服务端代码:

private static Map<String, SseEmitter> cache = new ConcurrentHashMap<>();String clientId;int sseId;@GetMapping("/create")public SseEmitter create(@RequestParam(name = "clientId", required = false) String clientId) {    // 设置超时时间,0表示不过期。默认30000毫秒    //可以在客户端一直断网、直接关闭页面但未提醒后端的情况下,服务端在一定时间等待后自动关闭网络连接    SseEmitter sseEmitter = new SseEmitter(0L);    // 是否需要给客户端推送ID    if (Strings.isBlank(clientId)) {        clientId = UUID.randomUUID().toString();    }    this.clientId = clientId;    cache.put(clientId, sseEmitter);    log.info("sse连接,当前客户端:{}", clientId);    return sseEmitter;}@Scheduled(cron = "0/3 * *  * * ? ")public void pushMessage() {    try {        sseId++;        SseEmitter sseEmitter = cache.get(clientId);        sseEmitter.send(                SseEmitter                        .event()                        .data("帅气值暴增" + sseId)                        .id("" + sseId)                        .reconnectTime(3000)        );    } catch (Exception e) {        log.error(e.getMessage());        sseId--;    }}@GetMapping("/close")public void close(String clientId) {    SseEmitter sseEmitter = cache.get(clientId);    if (sseEmitter != null) {        sseEmitter.complete();        cache.remove(clientId);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

方法参数说明:

 SseEmitter          .event()          .data("帅气值暴增" + sseId)          .id("" + sseId)          .reconnectTime(3000)
  • 1
  • 2
  • 3
  • 4
  • 5

SseEmitter.event()
用来得到一个记录数据的容器。


.data("帅气值暴增" + sseId)
发送给客户端的数据。


.id("" + sseId)
记录发送数据的标识,服务端可以通过HttpServletRequest的请求头中拿到这个id,判断是否中间有误漏发数据。


.reconnectTime(3000)
定义在网络连接断开后,客户端向后端发起重连的时间间隔(以毫秒为单位)。

效果:

参考资料:

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发