在 AI 应用开发中,流式输出早已成为提升用户体验的核心能力------像 ChatGPT 那样的打字机式实时回复,既能避免用户长时间干等,又能解决长连接超时问题,是 AI 产品的必备特性。
一、流式输出的两种技术,不是对立而是"底层+上层"
Spring AI 流式输出的底层实现只有一种,而上层部署传输技术有两种,二者是"发动机与公路"的关系------底层发动机(Reactor)固定不变,上层可根据项目场景选择不同的传输路径(MVC+SSE 或 WebFlux)。
Spring AI 流式输出的底层核心技术:统一基于 Reactor Streams(Project Reactor),通过 Flux 实现分块数据推送;
Spring AI 流式输出的上层部署技术:支持两种 Web 栈------Spring MVC(Servlet)+ SSE、Spring WebFlux + Reactor 原生流,可自动适配项目环境,无需额外改造代码。
二、两种上层部署技术
流式输出的"实时传输能力",本质依赖于 Web 层的技术选型。Spring AI 做了完美适配,开发者无需关注底层转换细节,只需根据项目类型选择对应的 Web 栈即可。
1. 方案一:Spring MVC(传统 Servlet)+ SSE 流式输出
这是最常见、最易落地的方案,适合绝大多数传统 Spring Boot 项目(基于 Servlet 容器,如 Tomcat、Jetty),无需引入额外响应式依赖,上手成本极低。
- 核心依赖:Spring MVC(Spring Boot Starter Web 已内置)、SSE(Server-Sent Events,服务端推送协议);
- 底层支撑:基于 Servlet 3.1 异步机制,Spring AI 自动将 Reactor Flux 数据流转为 SSE 流,无需手动转换;
- 返回格式:必须声明媒体类型 text/event-stream,用于告诉前端"当前接口返回的是实时流式数据";
- 适用场景:传统 Spring Boot 项目、中小并发场景、快速落地需求、现有项目改造;
- 核心特点:开发简单、兼容性强,无需改变现有项目架构,完美适配绝大多数存量项目。
2. 方案二:Spring WebFlux + Reactor Streams 流式输出
这是 Spring 官方推荐的响应式方案,基于 Netty 异步容器,适合高并发、高吞吐量、长连接场景,是云原生、微服务项目的首选。
- 核心依赖:Spring WebFlux(响应式 Web 框架)、Reactor Streams(Project Reactor);
- 底层支撑:Netty 异步容器 + Reactor Flux 原生响应式流,无需任何转换,直接实现非阻塞推送;
- 返回格式:可直接返回 Flux 原生流,无需强制声明 SSE 协议(但也支持 SSE 协议,兼容性拉满);
- 适用场景:高并发、高吞吐量、长连接场景、云原生/微服务项目、对性能要求较高的 AI 应用;
- 核心特点:非阻塞、高性能,完美契合 Reactor 底层逻辑,无 Servlet 容器依赖,可灵活部署于云环境。
三、底层核心:Reactor Streams + Flux(流式输出的"发动机")
不管是 Spring MVC + SSE,还是 Spring WebFlux,Spring AI 流式输出的底层核心永远是 Reactor Streams------这是从 Spring AI 核心源码中能明确看到的结论。Spring AI 没有自己造流式轮子,而是完全复用 Spring 全家桶的响应式生态,确保稳定性与兼容性。
1. Reactor Streams 是什么?
Reactor Streams 是 Spring 官方默认的响应式编程框架,也是 Spring 响应式生态的基石,核心解决三大问题:异步实时数据传输、分块数据连续推送、高并发长连接下的性能瓶颈,为流式输出提供了底层技术支撑。
2. 核心组件:Flux(流式输出的"数据管道")
Spring AI 所有流式接口的返回值,最终都会落到 Flux 上。我们可以用一句大白话理解:Flux 就是一个"实时数据管道",能异步发送 0~N 个数据块,来一个数据、推一个数据,无需等待全部数据生成完成。
对应到 AI 场景:AI 大模型生成文本时,不会一次性返回完整内容,而是分块(chunk)生成;每生成一个数据块,就会通过 Flux 这个"管道",实时推送给前端/客户端------这就是我们熟悉的"打字机效果"的核心原理。
3. 源码级结论
查看 Spring AI 核心源码(如 StreamingChatClient、ChatClient 接口的实现类)可以发现:所有流式方法的返回值,均为 Flux 或 Flux,底层均通过 Reactor 的 Flux.create() 或 Flux.from() 构建数据流,与上层 Web 栈(MVC 或 WebFlux)无关。
简单来说:Reactor Flux 是 Spring AI 流式输出的"核心载体",上层 Web 栈只是"传输通道",无论选择哪种通道,核心的"数据推送逻辑"完全一致。
四、Spring AI 流式输出的完整架构
架构核心逻辑拆解:
- AI 大模型生成文本时,采用"分块输出"模式,不会一次性返回完整内容;
- Spring AI 核心层通过 Reactor Streams 接收这些文本块,并用 Flux 封装成实时数据流;
- 如果项目是 Spring MVC 环境,Spring AI 自动将 Flux 数据流转为 SSE 流,以 text/event-stream 格式返回给前端;
- 如果项目是 Spring WebFlux 环境,Flux 数据流直接以原生响应式流返回,无需任何转换,实现非阻塞推送;
- 前端接收流式数据后,实时渲染展示,最终呈现"打字机式"的实时回复效果。
五、Spring AI 两种流式 API 实现
Spring AI 提供了两套上层流式 API------StreamingChatClient 和 ChatClient.stream(),二者均能同时适配 MVC 和 WebFlux 环境,底层统一基于 Reactor Flux,仅使用场景不同,开发者可根据业务需求灵活选择。
前置准备:依赖 + 配置(两种方案通用)
无论选择哪种 Web 栈、哪种 API,前置的依赖引入和配置都是通用的,只需根据 Web 栈类型调整依赖即可。
1. Maven 依赖
xml
<!-- Spring AI BOM 统一版本管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 核心依赖(二选一,根据 Web 栈选择) -->
<dependencies>
<!-- 方案1:Spring MVC 环境(默认,传统项目首选) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 方案2:Spring WebFlux 环境(高并发/云原生项目首选,替换上述 web 依赖) -->
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency> -->
<!-- Spring AI 对话核心依赖(必选,无论哪种方案都需引入) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
</dependencies>
2. 配置文件(application.yml)
yaml
spring:
ai:
openai:
api-key: 你的OpenAI/第三方兼容API Key # 替换为自己的API Key
base-url: https://api.example.com # 第三方接口地址(可选,如国内镜像)
chat:
options:
model: gpt-3.5-turbo # 模型名称(根据实际需求选择)
stream: true # 开启流式输出(底层核心配置,必选)
关键提醒:stream: true 必须开启,否则 AI 模型会一次性返回完整内容,无法实现流式输出效果。
实现方式 1:StreamingChatClient(极简快速版,适配两种 Web 栈)
适用场景:快速开发、无复杂配置、纯对话场景(如简单的 AI 问答),一行代码即可开启流式输出,自动适配 MVC/SSE 和 WebFlux 环境,无需额外调整。
java
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.ai.chat.client.StreamingChatClient;
import reactor.core.publisher.Flux;
/**
* Spring AI 流式输出 - 极简实现(适配 MVC + WebFlux 双环境)
*/
@RestController
public class AiStreamSimpleController {
// 自动注入 Spring AI 流式客户端(Spring 自动装配,无需手动创建)
private final StreamingChatClient streamingChatClient;
// 构造器注入(Spring 推荐,避免循环依赖,提升代码稳定性)
public AiStreamSimpleController(StreamingChatClient streamingChatClient) {
this.streamingChatClient = streamingChatClient;
}
/**
* 流式输出接口
* 1. MVC 环境:自动转为 SSE 流(text/event-stream),适配传统项目
* 2. WebFlux 环境:直接返回 Flux 原生流,实现非阻塞推送
*/
@GetMapping(value = "/ai/stream/simple", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamSimple(@RequestParam String message) {
// 核心:调用 stream() 方法,直接返回 Flux 流(底层基于 Reactor 实现)
return streamingChatClient.stream(message);
}
}
实现方式 2:ChatClient 链式 API(企业级推荐,适配两种 Web 栈)
适用场景:复杂业务场景(如自定义系统提示词、配置模型参数、实现上下文对话),是企业级开发的首选方案,灵活性和扩展性更强。
java
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
/**
* Spring AI 流式输出 - 企业级推荐实现(适配 MVC + WebFlux 双环境)
*/
@RestController
public class AiStreamStandardController {
private final ChatClient chatClient;
// 注入 ChatClient 构造器,支持自定义配置(如模型参数、超时时间等)
public AiStreamStandardController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
/**
* 标准流式输出接口
* 支持:系统提示词、用户消息、模型参数配置、流式返回,适配复杂业务场景
*/
@GetMapping(value = "/ai/stream/standard", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamStandard(@RequestParam String message) {
return chatClient.prompt()
// 系统提示词(可自定义 AI 角色、回答规则,按需调整)
.system("你是一个专业的 AI 助手,回答简洁、准确、有礼貌,贴合用户实际需求")
// 用户输入的问题(可结合上下文,实现多轮对话)
.user(message)
// 核心:开启流式输出(底层调用 Reactor Flux,与 Web 栈无关)
.stream()
// 只返回纯文本内容(也可返回 ChatResponse,获取完整响应信息如 token 数量)
.content();
}
}
六、关键注意点
结合实际开发经验,整理了 4 个高频避坑点,新手必看,老手自查:
- 媒体类型声明:MVC 环境必须声明 produces = MediaType.TEXT_EVENT_STREAM_VALUE(即 SSE 协议),否则前端无法识别流式数据;WebFlux 环境可省略,但声明后兼容性更好,建议统一添加。
- 返回值规范:流式接口的返回值必须是 Flux 或 Flux,不能用 String、List 等普通同步类型,否则会失去流式效果。
- 配置必选项:spring.ai.openai.chat.options.stream: true 必须开启,这是底层开启流式输出的关键配置,否则 AI 模型会一次性返回完整内容。
- 环境适配:无需修改代码,仅需更换依赖(spring-boot-starter-web / spring-boot-starter-webflux),Spring AI 会自动适配对应的流式传输方式,降低开发成本。
七、如何测试流式接口?
接口开发完成后,无需复杂测试工具,两种简单方式即可快速验证流式效果:
- 浏览器直接访问:打开浏览器,输入接口地址(如 http://localhost:8080/ai/stream/standard?message=请介绍一下Spring AI流式输出),即可看到文字逐字实时输出,直观验证流式效果。
- 接口工具测试:Postman、Apifox 等主流接口工具均支持 SSE 流式响应,发送 GET 请求后,可实时看到分块推送的内容,便于调试接口参数。
- 前端对接:MVC 环境用 EventSource 接收 SSE 流,WebFlux 环境可直接对接响应式流,均可轻松实现打字机效果(后续将单独更新前端对接完整代码)。
八、最终专业总结
Spring AI 流式输出的核心架构,是"底层统一 + 上层适配"的设计理念,既保证了核心逻辑的一致性,又兼顾了不同项目场景的灵活性:
底层统一基于 Reactor Streams 响应式流实现,通过 Flux 完成 AI 文本分块的接收与推送,确保流式输出的核心能力稳定、高效;上层自动适配 Spring MVC(Servlet)+ SSE 和 Spring WebFlux 两种部署技术,开发者可根据项目场景(传统/高并发)灵活选择,无需关注底层实现细节。
Spring AI 提供的 StreamingChatClient 和 ChatClient 流式 API,均能完美适配两种 Web 栈,代码可直接复制落地,大幅降低流式输出的开发成本,让开发者能快速实现 AI 产品的"打字机效果"。