当前位置: 首页 > news >正文

主动推送数据到前端的SSE技术原理以及如何使用

前言

首先,SSE全称是Server-Sent Events,是一种服务器向客户端单向推送数据的技术。它基于HTTP协议,使用长连接,允许服务器主动发送消息到浏览器。相比WebSocket,SSE更简单,但只支持单向通信,适合服务器向客户端推送实时数据的场景,比如实时通知、股票行情等。

Spring MVC提供了对SSE的支持,主要是通过SseEmitter类。需要创建一个Controller,返回SseEmitter对象,然后通过这个对象发送数据。可能需要维护一个SseEmitter的列表,以便在需要的时候向所有客户端广播消息。

然后前端部分,Vue作为前端框架,需要用EventSource API来接收SSE的事件。在Vue组件中,可以在mounted生命周期钩子中创建EventSource实例,监听服务器的事件流,处理接收到的数据,并在组件销毁时关闭连接,防止内存泄漏。


SSE 技术原理

Server-Sent Events (SSE) 是一种基于 HTTP 的单向通信协议,允许服务器主动向客户端推送数据。其核心特点:

  1. 单向通信:仅服务端 → 客户端。
  2. 长连接:通过 text/event-stream 保持连接。
  3. 自动重连:客户端自动尝试重新连接。
  4. 轻量级:相比 WebSocket,无需复杂握手协议。

Spring Boot 后端实现

1. 添加依赖
<!-- Spring Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. 创建 SSE 控制器
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

@RestController
@CrossOrigin(origins = "*") // 允许跨域
public class SseController {
    private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();

    // 客户端订阅
    @GetMapping(path = "/sse/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter subscribe() {
        SseEmitter emitter = new SseEmitter(60_000L); // 超时时间 60秒
        String clientId = UUID.randomUUID().toString();
        emitters.put(clientId, emitter);

        // 监听连接关闭
        emitter.onCompletion(() -> emitters.remove(clientId));
        emitter.onTimeout(() -> emitters.remove(clientId));
        
        return emitter;
    }

    // 向所有客户端广播消息
    public void broadcast(String message) {
        emitters.forEach((id, emitter) -> {
            try {
                emitter.send(SseEmitter.event()
                    .data(message) // 发送数据
                    .id(id)       // 事件ID(可选)
                    .name("sse-event") // 事件名(可选)
                );
            } catch (IOException e) {
                emitter.completeWithError(e); // 处理异常
            }
        });
    }
}
3. 触发消息推送

在业务逻辑中调用 broadcast() 方法:

@Service
public class NotificationService {
    @Autowired
    private SseController sseController;

    public void sendRealTimeData(String data) {
        sseController.broadcast(data);
    }
}

Vue 前端实现

1. 连接 SSE

在 Vue 组件中建立 SSE 连接:

export default {
  data() {
    return {
      eventSource: null,
      messages: [],
    };
  },
  mounted() {
    this.connectSSE();
  },
  beforeDestroy() {
    if (this.eventSource) {
      this.eventSource.close(); // 组件销毁时关闭连接
    }
  },
  methods: {
    connectSSE() {
      this.eventSource = new EventSource('http://localhost:8080/sse/subscribe');

      // 监听消息事件
      this.eventSource.addEventListener('sse-event', (event) => {
        this.messages.push(JSON.parse(event.data));
      });

      // 处理错误
      this.eventSource.onerror = (error) => {
        console.error('SSE Error:', error);
        this.reconnect(); // 尝试重连
      };
    },
    reconnect() {
      if (this.eventSource) {
        this.eventSource.close();
        setTimeout(() => this.connectSSE(), 3000); // 3秒后重连
      }
    },
  },
};
2. 显示数据

在模板中渲染接收到的消息:

<template>
  <div>
    <h3>实时消息:</h3>
    <ul>
      <li v-for="(msg, index) in messages" :key="index">{{ msg }}</li>
    </ul>
  </div>
</template>

关键配置与优化

1. 跨域处理
  • 后端:使用 @CrossOrigin 或全局 CORS 配置。
  • 前端:开发环境下可通过 Vue 代理解决:
    // vue.config.js
    module.exports = {
      devServer: {
        proxy: {
          '/sse': {
            target: 'http://localhost:8080',
            ws: false, // SSE 不需要 WebSocket
            changeOrigin: true,
          },
        },
      },
    };
    
2. 消息格式
  • 标准 SSE 格式:每条消息以 data: 开头,以 \n\n 结束。
    emitter.send("data: " + message + "\n\n");
    
  • JSON 支持:发送结构化数据:
    emitter.send(SseEmitter.event().data(JSON.stringify({ user: "Alice", value: 42 })));
    
3. 性能优化
  • 心跳机制:定期发送空消息保持连接活跃。
  • 背压控制:避免高频消息导致客户端阻塞。
  • 连接池管理:限制最大并发连接数。

完整流程示例

  1. 客户端订阅:浏览器访问 http://localhost:8080/sse/subscribe
  2. 服务端存储连接:将 SseEmitter 存入 Map。
  3. 业务触发推送:调用 broadcast("New data")
  4. 前端接收更新:Vue 组件实时渲染消息列表。

对比 WebSocket

特性SSEWebSocket
通信方向单向(服务端 → 客户端)双向
协议HTTP自定义协议 (ws/wss)
自动重连需手动实现
复杂度
适用场景实时通知、日志流聊天室、游戏

通过 SSE 技术,可轻松实现后端到前端的实时数据推送,结合 Spring Boot 和 Vue 的生态,为前后端分离项目提供高效、简洁的实时通信方案。

相关文章:

  • Python从0到100(八十八):LSTM网络详细介绍及实战指南
  • vue3(笔记)4.0 vueRouter.导航守卫.ElementPuls知识点
  • node项目前后端密码加密传输及存储方案
  • SpringBoot调用DeepSeek
  • MySQL表连接详解
  • 爬虫(持续更新ing)
  • Thonny+MicroPython+ESP32开发环境搭建
  • 【leetcode hot 100 189】轮转数组
  • ChatVLA:基于视觉-语言-动作模型的统一多模态理解与机器人控制
  • (2025)Unity调用DeepSeek API (兼容OpenAI SDK)
  • 在Windows实现将Docker Desktop安装至非系统盘(2025年3月测试有效)
  • Kmeans算法来实现RFM指标计算步骤
  • 算法 并查集
  • Axure原型模板与元件库APP交互设计素材(附资料)
  • Bitmap -> Bitmap安卓设备上的显示和内存
  • 汽车轮胎损伤缺陷分割数据集labelme格式1957张3类别
  • iOS安全和逆向系列教程 第1篇: iOS逆向工程概述与学习路线图
  • 第七章:项目实战 - 第四节 - Tailwind CSS 移动端适配实践
  • 计算机毕业设计SpringBoot+Vue.js装饰工程管理系统(源码+文档+PPT+讲解)
  • 算数操作符、赋值操作符、单目操作符、强制类型转换
  • 怎样在织梦后台里面做网站地图/什么平台可以免费发广告
  • 亳州企业网站建设/最近最火的关键词
  • 电商网站开发工程师/atp最新排名
  • 网站备案网站名称/五个成功品牌推广案例
  • 单页网站制作程序/百度推广的定义
  • html5 手机网站模版/如何点击优化神马关键词排名