下面是一个 基于 Spring Boot 3.x + WebFlux + WebClient 的大模型(如 OpenAI) SSE 接口调用完整示例,适合对接 GPT 接口,并将其 原样或加工后返回给前端,支持类似 ChatGPT 的逐词流式输出体验。
✅ 技术选型
技术 | 用途 |
---|---|
Spring Boot 3.x | 后端框架 |
WebClient(Spring WebFlux) | 异步 HTTP 客户端 |
Flux<String> | 流式响应 |
text/event-stream | 前端接收 SSE |
GPT/OpenAI API | 模拟大模型返回 |
📦 1. Maven 依赖(Spring Boot 3)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 解析 JSON 响应 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
🚀 2. WebClient 配置类(可选)
@Configuration
public class WebClientConfig {
@Bean
public WebClient openAiWebClient() {
return WebClient.builder()
.baseUrl("https://api.openai.com")
.defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer YOUR_OPENAI_API_KEY")
.build();
}
}
🧠 3. GPT SSE 调用服务(返回 Flux<String>
)
@Service
public class OpenAiService {
@Autowired
private WebClient openAiWebClient;
public Flux<String> streamChat(String prompt) {
Map<String, Object> requestBody = Map.of(
"model", "gpt-3.5-turbo",
"stream", true,
"messages", List.of(
Map.of("role", "user", "content", prompt)
)
);
return openAiWebClient.post()
.uri("/v1/chat/completions")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(requestBody)
.retrieve()
.bodyToFlux(String.class)
.flatMap(this::parseSseLine) // 🔁 解析每一行 data: ...
.onErrorResume(e -> Flux.just("【出错】" + e.getMessage()));
}
// 提取 "data: ..." 中的 content
private Flux<String> parseSseLine(String line) {
if (line == null || !line.startsWith("data: ")) {
return Flux.empty();
}
String data = line.substring(6).trim();
if ("[DONE]".equals(data)) {
return Flux.empty();
}
try {
JsonNode root = new ObjectMapper().readTree(data);
JsonNode contentNode = root
.path("choices").get(0)
.path("delta").path("content");
if (contentNode != null && !contentNode.isMissingNode()) {
return Flux.just(contentNode.asText());
}
} catch (Exception e) {
return Flux.just("【解析出错】");
}
return Flux.empty();
}
}
🌐 4. 控制器返回 Flux<String>
,前端以 SSE 接收
@RestController
@RequestMapping("/api")
public class ChatController {
@Autowired
private OpenAiService openAiService;
@GetMapping(value = "/chat-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String prompt) {
return openAiService.streamChat(prompt);
}
}
🖥️ 5. 前端使用 JavaScript 接收 SSE
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>GPT SSE Demo</title></head>
<body>
<h3>GPT 实时回答:</h3>
<div id="output"></div>
<script>
const source = new EventSource("/api/chat-stream?prompt=你好,介绍一下Java");
source.onmessage = function(event) {
document.getElementById("output").innerHTML += event.data;
};
source.onerror = function(err) {
console.error("SSE 连接出错", err);
source.close();
};
</script>
</body>
</html>
✅ 最终效果
- 客户端页面打开后会逐行显示 GPT 输出的文本;
- 后端使用
WebClient
异步消费 GPT SSE 数据; - 使用
Flux<String>
直接推送给前端,前端无需等待整段文本。
🛠️ 可扩展点(建议)
功能 | 实现建议 |
---|---|
支持 GPT-4 | 修改 model 字段 |
上下文记忆 | 加入历史 messages |
Markdown 渲染 | 前端使用 marked.js |
JSON 格式化输出 | 改成 Flux<SseEmitter.event().data(...)> |
如果你希望我:
- 添加请求体 JSON 封装对象(DTO);
- 实现一个 ChatGPT 聊天历史上下文;
- 添加多用户身份识别支持;
✅ 已为你生成一个可运行的 Spring Boot 项目骨架,文件名为 Springboot Gpt Sse
,包含:
main
方法;WebClient
配置;- 支持
Flux<String>
SSE 输出的控制器; - 对接 OpenAI 的流式 API 调用;
- JSON 内容解析与错误处理。
🧪 测试方式:
- 修改你的
application.yml
或application.properties
; - 替换
YOUR_OPENAI_API_KEY
; - 运行后访问:
GET http://localhost:8080/api/chat-stream?prompt=你好,请介绍Java
浏览器或 curl 都能看到逐字输出。
🧠 如需扩展(可继续添加):
- ✅ 自定义 message 请求 DTO;
- ✅ 多轮对话上下文管理;
- ✅ 支持 GPT-4 模型;
- ✅ 完整的前端聊天窗口(HTML 页面 + JS);
- ✅ 使用 SSE Event 类型返回更强结构性消息。
需要哪一块我可以继续为你添加,是否需要前端配套页面或更复杂的聊天会话逻辑?
发表回复