我把 SpringBoot + Vue3 整合 SSE 的文章写得更加详细,包括依赖引入、配置说明、完整代码、测试方法和注意事项,让你真正可以"一分钟开箱即用"。
一、技术原理简介
SSE(Server-Sent Events) 是一种基于 HTTP 的服务器向客户端单向实时通信技术。
特点:
- 基于标准 HTTP 协议,无需 WebSocket 复杂握手。
- 服务端保持长连接,随时推送数据。
- 浏览器原生支持
EventSourceAPI。 - 适合 通知推送、实时日志、股票行情、聊天消息(单向) 等场景。
二、后端:SpringBoot 实现 SSE
1. 引入依赖
使用 Maven 的 pom.xml引入 Spring Boot Web 依赖(Spring Boot 自带 SSE 支持,无需额外 jar):
xml
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 测试用:方便发 POST 请求 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
说明 :
spring-boot-starter-web已经包含了javax.servlet-api和 Spring MVC,SseEmitter类位于org.springframework.web.servlet.mvc.method.annotation.SseEmitter,无需额外引入 jar。
2. 配置文件
application.yml(或 application.properties)保持默认即可,无需特殊配置。
如果需要跨域,可以加:
yaml
spring:
web:
cors:
allowed-origins: "*"
3. SSE 控制器代码
less
package com.example.sse.controller;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@RestController
@RequestMapping("/sse")
public class SseController {
// 保存每个用户的 SSE 连接,生产环境可用 Redis 等分布式缓存
private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();
/**
* 客户端订阅接口
* GET /sse/subscribe/{userId}
*/
@GetMapping(value = "/subscribe/{userId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter subscribe(@PathVariable String userId) {
// 0 表示永不超时,如需超时可用 60_000 毫秒
SseEmitter emitter = new SseEmitter(0L);
emitters.put(userId, emitter);
// 完成时移除
emitter.onCompletion(() -> emitters.remove(userId));
// 超时移除
emitter.onTimeout(() -> emitters.remove(userId));
// 出错移除
emitter.onError((e) -> emitters.remove(userId));
return emitter;
}
/**
* 服务端推送消息接口
* POST /sse/push/{userId}
*/
@PostMapping("/push/{userId}")
public void push(@PathVariable String userId, @RequestBody String message) {
SseEmitter emitter = emitters.get(userId);
if (emitter != null) {
try {
// name("message") 对应前端的 event type
emitter.send(SseEmitter.event().name("message").data(message));
} catch (IOException e) {
emitters.remove(userId);
}
}
}
}
4. 启动类
typescript
package com.example.sse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SseApplication {
public static void main(String[] args) {
SpringApplication.run(SseApplication.class, args);
}
}
三、前端:Vue3 连接 SSE
1. 创建 Vue3 项目
sql
npm create vite@latest sse-demo -- --template vue
cd sse-demo
npm install
2. 组件代码
src/components/SseDemo.vue:
xml
<template>
<div>
<h3>SSE 实时消息推送</h3>
<ul>
<li v-for="(msg, index) in messages" :key="index">{{ msg }}</li>
</ul>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
const messages = ref([])
let eventSource = null
onMounted(() => {
// 替换为你的后端地址和 userId
eventSource = new EventSource('http://localhost:8080/sse/subscribe/user123')
// 接收消息
eventSource.onmessage = (event) => {
messages.value.push(event.data)
}
// 错误处理
eventSource.onerror = (err) => {
console.error('SSE connection error:', err)
eventSource.close()
}
})
onBeforeUnmount(() => {
if (eventSource) {
eventSource.close()
}
})
</script>
3. 在 App.vue 中使用
xml
<template>
<SseDemo />
</template>
<script setup>
import SseDemo from './components/SseDemo.vue'
</script>
四、测试方法
-
启动 SpringBoot 后端
默认端口 8080。
-
启动 Vue3 前端
arduinonpm run dev打开浏览器访问
http://localhost:5173。 -
发送测试消息
用 Postman 或 curl 发 POST 请求:
bashcurl -X POST http://localhost:8080/sse/push/user123 \ -H "Content-Type: application/json" \ -d '"Hello SSE 实时消息!"'前端页面会立刻收到并显示消息。
五、注意事项与优化
-
跨域问题
前后端分离时,后端需配置 CORS,否则浏览器会拦截 EventSource 连接。
-
心跳保活
长时间无消息时,连接可能被代理或浏览器断开。可在服务端定时推送注释行保持活跃:
lessemitter.send(SseEmitter.event().comment("heartbeat")); -
多用户广播
当前示例是点对点(一个用户一个连接),如需群发,可维护一个
List<SseEmitter>或按频道分组。 -
生产环境
- 使用 Redis 或消息队列管理连接,支持集群。
- 设置合理的超时时间与重连机制。
- 对敏感消息加密传输(HTTPS)。
✅ 总结
- 后端:
SseEmitter+@GetMapping(produces=TEXT_EVENT_STREAM_VALUE) - 前端:
new EventSource(url)+onmessage接收 - 引入 jar:仅需
spring-boot-starter-web,零额外依赖。