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

Spring使用SseEmitter实现后端流式传输和前端Vue数据接收

4.1 前言

在构建web应用时,实时数据推送是一个非常重要的需求,比如AI对话流式想用、实时通知推送等。在SpringBoot项目中,SseEmitter是一个非常方便的工具,它可以让后端向前端进行流式数据传输(Server-> Sent Events,简称SSE)。

SseEmitter是SpringWeb提供的一个用于服务器推送事件(SSE,Server-Send Events)的工具。它可以让服务器端不断向客户端推送数据,而不需要客户端不断轮询。

相比于WebSocket,SSE具有以下优点:

  • 基于HTTP连接,无需额外的协议支持,前端可以直接使用EventSource进行接收。

  • 支持自动重连,如果连接断开,浏览器会自动尝试重新连接。

  • 更适合单向推送数据的场景,如AI生成流式文本、服务器消息推送等。

4.2 在SpringBoot项目中使用SseEmitter

(1)添加依赖

如果你的项目使用的是 Spring MVC(一般的SpringBoot项目),无需额外的依赖。但如果你使用的是 Spring WebFlux,请确保你的 pom.xml 中包含以下依赖(仅 WebFlux 需要):

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
​

(2)创建后端流式接口

Controller层

@RestController
@RequestMapping("/multiChat")
public class MultiChatController {
@AutowiredMultiChatService multiChatService;
@GetMapping(value = "/streamMore", produces = "text/event-stream;charset=UTF-8")public SseEmitter streamChatMore(@RequestParam(value = "userQuestion") String userQuestion,@RequestParam(value = "titleId") String titleId,@RequestParam(value = "createBy", required = false) String createBy) {ChatRecord chatRecord = new ChatRecord();chatRecord.setUserQuestion(userQuestion);chatRecord.setTitleId(Long.parseLong(titleId));chatRecord.setCreateBy(createBy);
​chatRecord.setRecordId(UIDCom.randomUUID());chatRecord.setQuestionTime(DateUtils.getNowDate());SseEmitter emitter = new SseEmitter(0L);// 综合框架multiChatService.chatStreamMoreMessage(chatRecord, emitter);return emitter;}
}

其中SseEmitter emitter = new SseEmitter(0L); // 0L 表示永不超时

MultiChatService层

public interface MultiChatService {/*** 多路聊天* deepseek聊天 + 系统菜单功能  + 报告检索* @param chatRecord* @param emitter*/void chatStreamMoreMessage(ChatRecord chatRecord, SseEmitter emitter);
​Result testChat(ChatRecord chatRecord);
}

MultiChatServiceImpl层

@Service
@Slf4j
public class MultiChatServiceImpl implements MultiChatService {@Overridepublic void chatStreamMoreMessage(ChatRecord chatRecord, SseEmitter emitter) {new Thread(() -> {try {Thread.sleep(1000);// 要输出的完整文本
//                String content = "9 × 9 的计算结果是 81。\n这是乘法表中的基本运算之一,也被称为“九九八十一”。 😊";// 按 codePoint 遍历,保证 emoji 不会被拆开int[] codePoints = chatRecord.getUserQuestion().codePoints().toArray();for (int cp : codePoints) {String chunk = new String(Character.toChars(cp)); // 把 codePoint 转回字符串emitter.send(SseEmitter.event().name("message").data(chunk));Thread.sleep(100);}Thread.sleep(3000); // 停留3s钟结束emitter.send(SseEmitter.event().name("message").data("[DONE]")); // 发送结束标记emitter.complete();// 回调if (onComplete != null) {onComplete.accept(content);}} catch (Exception e) {emitter.completeWithError(e);}}).start();}
}

(3)前端接收流式数据

使用fetch处理SSE(流式数据),fetch默认不会处理流式数据,因此我们需要手动解析ReadableStream以逐步接收数据。

const aiMsg = reactive({ sender: "AI助手", text: "", loading: true }); // ✅ 增加 loading 标志this.messages.push(aiMsg);const eventSource = new EventSource(`/searcher/multiChat/streamMore?userQuestion=${encodeURIComponent(text)}&titleId=${chatId}&createBy=99999`);eventSource.onmessage = (event) => {if(event.data === "[DONE]") {eventSource.close();return;}if (aiMsg.loading) {aiMsg.loading = false; // ✅ 第一次收到数据就关闭“正在输入”}aiMsg.text += event.data; // 逐步拼接eventSource.onerror = (err) => {// console.error("SSE 连接错误:", err);this.showTip("SSE 连接错误:"+err, 1);aiMsg.loading = false; // ✅ SSE 结束也要关掉eventSource.close();};

注意:/searcher 会先经过vue.config.js配置的服务器id然后转发到设置的后端服务器。

http://www.dtcms.com/a/398789.html

相关文章:

  • 湖南省新闻最新消息十条深圳seo网站推广方案
  • 语音交互接待服务机器人深度推荐
  • 创建学校网站吗网站搭建工具的种类
  • Linux-ARM-裸机开发-开发环境搭建
  • 2025年校园招聘平台怎么选?
  • 如何把视频放到自己的网站ftp怎么重新上传网站
  • minio文件迁移
  • 网站反链接是什么意思wordpress 侧边收起
  • docker-desktop 分发版不支持用户数据挂载
  • 部署LVS NAT集群
  • 使用 feature_engine库 提升你的机器学习特征工程效率
  • 做网站网络公司无收入域名管理系统
  • 2,GUI Guider的安装与导入STM32裸机工程
  • 上门代管宠物系统的设计与实现
  • 鸿蒙Next应用开发:ArkTS语言下的IPC与RPC通信指南
  • CTFSHOW 中期测评(二)web502 - web516
  • JVM-执行引擎
  • 企业手机网站源码网站建设相关资质
  • python项目: Thinkphp框架漏洞扫描器集成
  • 车载通信架构 ---新一代车载通信框架
  • 建设银行网站怎么注销网银网站建设网页制作
  • 【25软考网工】第五章(10) Internet应用
  • Android target35适配之窗口边衬区变更
  • 设计网站推荐百度贴吧装修设计比较好的网站
  • 营销网站四大要素谷歌做自己的网站
  • 【OpenGL】LearnOpenGL学习笔记27 - HDR、Bloom
  • MySQL 学习笔记 (Part.1)
  • 《代码大全》笔记
  • 【低代码】阿里Formily通用设计工具Designable学习记录
  • 网站建设客户wordpress如何看网页地址