SSE(Server-sent Events)实现Web消息推送(SpringBoot)

news2024/11/15 8:47:26

本文参考自:

  • Web消息推送之SSE_魅Lemon的博客-CSDN博客_sse推送

  • 【IT老齐237】超好用Web服务端主动推送技术SSE_哔哩哔哩_bilibili

1、Web消息推送简介

  • 短轮询

  • 长轮询

  • iframe流

  • SSE

  • MQTT

  • websocket

2、SSE原理介绍

2.1、概念

SSE(Server Sent Event),直译为服务器发送事件,顾名思义,也就是客户端可以获取到服务器发送的事件。我们常见的 http 交互方式是客户端发起请求,服务端响应,然后一次请求完毕;但是在 sse 的场景下,客户端发起请求,连接一直保持,服务端有数据就可以返回数据给客户端,这个返回可以是多次间隔的方式

2.2、SSE特点

  • 长连接

  • 服务端可以向客户端推送信息

从 sse 的特点出发,我们可以大致的判断出它的应用场景,需要轮询获取服务端最新数据的 case 下,多半是可以用它的。比如显示当前网站在线的实时人数,法币汇率显示当前实时汇率,电商大促的实时成交额等等

3、SpringBoot下实现SSE

3.1、环境搭建

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tuwer</groupId>
    <artifactId>server-sent-events</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>
  • 启动类
package com.tuwer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author 土味儿
 * Date 2023/1/28
 * @version 1.0
 */
@SpringBootApplication
public class SseApp {
    public static void main(String[] args) {
        SpringApplication.run(SseApp.class, args);
    }
}

在这里插入图片描述

3.2、页面端html

resources资源路径下新建static目录,再创建index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>SSE Demo</title>
</head>
<body>
<div id="sse"></div>
<script>
    //var sse = new EventSource("http://localhost:8080/sse");
    //var sse = new EventSource("http://localhost:8080/sse-retry");
    var sse = new EventSource("http://localhost:8080/sse-retry-new");

    sse.onmessage = function (evt){
        var el = document.getElementById("sse");
        //el.innerHTML = evt.data;
        el.innerText = evt.data;
    };
</script>
</body>
</html>

3.3、服务端Controller

package com.tuwer.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalTime;
import java.util.concurrent.TimeUnit;

/**
 * @author 土味儿
 * Date 2023/1/28
 * @version 1.0
 */
@RestController
public class SseController {
    /**
     * 服务端循环发送
     * @param httpServletResponse
     * @return
     */
    @GetMapping("/sse")
    public String getStreamData(HttpServletResponse httpServletResponse) {
        httpServletResponse.setContentType("text/event-stream");
        httpServletResponse.setCharacterEncoding("utf-8");

        String s = "";
        while (true) {
            s = "data: " + LocalTime.now() + "\n\n";
            try {
                PrintWriter pw = httpServletResponse.getWriter();
                TimeUnit.SECONDS.sleep(1);
                pw.write(s);
                pw.flush();
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 客户端固定时间重试
     * @param httpServletResponse
     */
    @GetMapping("/sse-retry")
    public void getDataRetry(HttpServletResponse httpServletResponse){
        httpServletResponse.setContentType("text/event-stream");
        httpServletResponse.setCharacterEncoding("utf-8");

        String s = "retry: 2000\n";
        s += "data: "+LocalTime.now() +"\n\n";
        PrintWriter pw = null;
        try {
            pw = httpServletResponse.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }
        pw.write(s);
        pw.flush();
    }

    /**
     * 客户端固定时间重试(简洁版)
     * @return
     */
    @GetMapping("/sse-retry-new")
    public String getDataRetry(){
        /*
        * 数据格式:
        * --------------------------
        * retry: 重试时间(毫秒值)
        * 单换行\n
        * data: 具体数据
        * 双换行\n\n
        * --------------------------
        * retry和data后面是【半角冒号 + 空格】
        * --------------------------
        */
        String result = new StringBuilder()
                // retry: 重试毫秒值 单换行
                .append("retry: 2000\n")
                // data: 具体数据
                .append("data: 当前时间:")
                .append(LocalTime.now())
                // 双换行
                .append("\n\n")
                .toString();

        return result;
    }
}

在这里插入图片描述
在这里插入图片描述

3.4、演示

客户端固定时间重试(简洁版)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/181694.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

43.Isaac教程--图像变形

图像变形 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录图像变形几何畸变图像投影透视畸变校正径向畸变校正切向畸变校正其他相机固有参数焦距主点&#xff08;投影中心&#xff09;未失真输出的光学特性输出主点输出焦距输出图像大小输…

最快的树视图组件:Flexible TreeView.NET Crack

为什么要使用灵活的 TreeView&#xff1f; 灵活性 市场上其他类似树视图的组件所不具备的无与伦比的可扩展性和独特功能。 表现 市场上最快的树视图组件。 仅需 0.39 秒即可添加 100,000 个节点。 简单 尽管是一个非常强大的树视图组件&#xff0c;但 Flexible TreeView 被设计…

Java开发基于rmi的数据库中间件设计源码,并利用中间件建立一个数据库应用(Java web项目),分布式对象技术课程实践

基于rmi的数据库中间件设计 介绍 分布式对象技术课程实践&#xff1a;基于rmi的数据库中间件设计&#xff0c;并利用中间件建立一个数据库应用&#xff08;Java web项目&#xff09;。 软件架构 前端&#xff1a;React后端&#xff1a;Springboot数据库中间件&#xff1a;J…

【人脸检测】------MTCNN算法

MTCNN算法出自深圳先进技术研究院,乔宇老师组,是今年2016的ECCV。 正如上图所示,该MTCNN由3个网络结构组成(P-Net,R-Net,O-Net)。 Proposal Network (P-Net):该网络结构主要获得了人脸区域的候选窗口和边界框的回归向量。并用该边界框做回归,对候选窗口进行校准,然后通…

Ubuntu18.04下QT和MYSQL异常问题排查处理常用命令

问题场景 &#xff1a;开年第一天上班&#xff0c;使用GIT下载好项目代码到本地后&#xff0c;发现QT5.14.2无法正常启动&#xff0c;使用命令sudo /opt/Qt5.14.2/Tools/QtCreator/bin/qtcreator后没有任何反应&#xff0c;仔细回想应该是年前电脑修改环境变量导致无法进入系统…

微信小程序安全系列——文本内容安全识别

前言 相信很多朋友跟我遇到过相同的问题&#xff0c;就是在开发一些笔记或者博客的时候&#xff0c;会遇到一些过滤敏感、时政、黄、赌、毒这类词汇、句子等这种棘手问题。 今天我们看一下微信小程序提供的文本安全内容识别&#xff0c;也可以减少一些我们的工作量。通过微信…

【通信原理(含matlab程序)】实验二:FM的调制和解调

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; 本人持续分享更多关于电子通信专业内容以及嵌入式和单片机的知识&#xff0c;如果大家喜欢&#xff0c;别忘点个赞加个关注哦&#xff0c;让我们一起共同进步~ &#x…

bug解决:Uncaught (in promise) TypeError: Toast.loading is not a function

在使用vue3做项目时&#xff0c;在其中使用了vant框架&#xff0c;在使用toast的加载组件或者是一些其他组件时&#xff0c;出现了如下的错误&#xff1a;Uncaught (in promise) TypeError: Toast.loading is not a function错误代码如下&#xff1a;Toast.loading({ message: …

二本土木工程毕业四年,成功转行大数据

1、 自我介绍 大家好&#xff0c;我是临渊羡鱼。18年毕业与重庆的一所二本大学&#xff0c;至今4年有余&#xff0c;专业是土木工程&#xff0c;毕业后从事三年半的建筑结构设计工作&#xff0c;在此期间由于不看好设计行业前景&#xff0c;故而在21年底谋求转行。在朋友推荐下…

[C语言]文件操作

目录 1.文件 1.1程序文件 1.2数据文件 2.文件名 3.文件的打开和关闭 3.1文件指针 3.2文件的打开和关闭 4.文件的顺序读写 4.1fgetc 4.2fputc 4.3fgets 4.4fputs 4.5fscanf 4.6fprintf 4.7fread&#xff08;二进制输出&#xff09; 4.8fwriite&#xff08;二进制输…

Python【xpath】实战案例【中】

获取全国地级城市名称&#xff1a;案例准备&#xff1a;导入外部库 1.requests、2.lxml容易遇到的问题&#xff1a;网站SSL认证失效代码块&#xff1a;#导入第三方库 import requests from lxml import etree # 网页地址 url https://www.aqistudy.cn/historydata/ #U-A伪装 h…

SOFA Weekly|SOFANews、issue 精选

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展欢迎留言互动&#xff5e;SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&#…

论文投稿指南——中文核心期刊推荐(公路运输)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

Linux嵌入式开发——用户与用户组

文章目录Linux嵌入式开发——用户与用户组用户用户组创建用户和用户组1、图形化界面创建2、命令创建添加用户用户查询修改用户密码删除用户添加用户组显示组内用户名删除用户组Linux嵌入式开发——用户与用户组 用户 Linux是一个多用户操作系统&#xff0c;不同的用户拥有不同…

过年回家,你是否也像我一样努力生动的给别人解释软件开发是干啥滴?

这个年就这样&#xff0c;在喜气洋洋的气氛中&#xff0c;在我们依依不舍的留恋中&#xff0c;从我们身边溜走了。这次回家又碰见了亲戚们不厌其烦的问我&#xff0c;你做什么工作呐&#xff1f;于是就有了我以下生动的解释 目录 打字的 帮助传话&#xff0c;帮助卖东西 皮…

亚马逊云科技:强强联合助力中国头部车企打造优质服务体验

2023年1月9日在美国拉斯维加斯刚落幕的国际消费电子展&#xff08;CES 2023&#xff09;上&#xff0c;亚马逊云科技的2位重要合作伙伴BlackBerry和中国领先的车联网&#xff08;IoV&#xff09;技术服务与产品提供商博泰车联网共同宣布&#xff0c;由BlackBerry IVY™赋能的博…

.Net 7 托管Main入口的四种写法(茴香豆?)

前言&#xff1a; 按照CLR的规则,C#托管Main入口其实有四种写法。 写法 第一种&#xff1a;最常见的&#xff0c;也是VS默认的&#xff0c;返回值void,带一个参数 static void Main(string[] args) {Console.Write("Tian xia feng yun chu wo bei");Console.ReadLine…

python图像处理(均值滤波)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 在图像处理过程中,一个绕不开的话题就是噪声。其中比较经典的就是椒盐噪声。为了降低这些噪声对最终图像处理效果的影响,人们想了很多的方法,比如说均值滤波、中值滤波、高斯滤波…

java多线程-线程属性

线程属性 线程各属性 线程ID id从 1 开始计数&#xff0c;因为在源码中是如下实现的&#xff0c;初始值设置为0&#xff0c;id是先自增再返回 private volatile int threadStatus 0;private static synchronized long nextThreadID() {return threadSeqNumber; }现在来演示…

处理比赛数据记录

文章目录一、需求二、爬取阶段1.使用requests进行请求获取网页内容2.使用selenium模拟人操作浏览器获取网页内容(1)环境配置(2) 源码3.使用phantomjs模拟人操作浏览器获取网页内容浅浅记录一下自己在做一个比赛数据处理过程中的遇到的一些问题。一、需求 首先数据的格式是长下…