前端实现与Spring后端请求的实时流式响应,打造类 AI流式回复效果

在当今实时交互体验至上的时代,像ChatGPT那样流畅的流式回复体验越来越受欢迎。本文将深入浅出地讲解如何使用前端技术与Spring后端强强联手,打造令人惊艳的流式回复功能。

一、基本概念

在正式开始之前,我们先来了解一些基础概念:

  • 长连接: 区别于传统的HTTP请求-响应模式,长连接允许服务器主动向客户端推送数据,而无需等待客户端发起请求。
  • 流式传输: 数据并非一次性传输完毕,而是像流水一样持续地传输,让接收方可以实时处理。
  • WebSocket: HTML5提供的全双工通信协议,能够实现浏览器与服务器之间的双向实时通信。
  • SSE (Server-Sent Events): 服务端推送技术,浏览器通过HTTP连接接收服务器单向推送的数据流。
  • Spring WebFlux: Spring生态系统中用于构建反应式应用程序的框架,支持WebSocket和SSE,能够处理流式数据。

二、为什么需要实时流式响应

传统的HTTP请求-响应模式下,客户端必须不断地发送请求才能获取最新的数据,这种方式效率低下且资源消耗大。而长连接允许服务器主动推送数据,实时性更高,也更加节省资源。

三、技术选型与原理

1. 前端:

  • WebSocket: HTML5提供的全双工通信协议,完美契合长连接和流式数据传输的需求。
  • SSE (Server-Sent Events): 服务端推送技术,浏览器通过HTTP连接接收服务器单向推送的数据流。

2. 后端 (Spring):

  • Spring WebFlux: Spring生态系统中用于构建反应式应用程序的框架,支持WebSocket和SSE。

3. 原理:

  • 建立连接: 前端通过WebSocket或SSE与后端建立持久连接。
  • 发送请求: 前端发送消息请求到后端。
  • 流式处理: 后端接收请求后,不等待完整结果,而是将处理过程中的中间结果(例如逐字生成的回复)实时推送给前端。
  • 动态展示: 前端接收数据流,并动态更新页面内容,实现逐字显示的效果。

四、WebSocket方案实现

4.1 技术原理
  • 建立连接:
    • 前端使用 new WebSocket() 创建WebSocket对象,连接到后端指定的WebSocket地址。
    • 后端使用Spring WebFlux提供的 WebSocketHandler 接口处理WebSocket连接请求。
  • 数据传输:
    • 前端通过 WebSocket.send() 发送消息到后端。
    • 后端通过 WebSocketSession.send() 方法向客户端推送消息。
    • 前后端都可以监听 onmessage 事件来接收对方发送的消息。
  • 关闭连接:
    • 前端或后端都可以调用 WebSocket.close() 方法关闭连接。
4.2. 后端 (Spring WebFlux):
复制代码
@Component
public class ChatWebSocketHandler implements WebSocketHandler {

    @Override
    public Mono<Void> handle(WebSocketSession session) {
        // 接收消息
        return session.receive()
                .map(WebSocketMessage::getPayloadAsText)
                .flatMap(message -> {
                    // 处理消息,例如调用ChatGPT API
                    return processMessage(message);
                })
                .flatMap(reply -> {
                    // 将回复逐字发送
                    return Flux.fromIterable(reply.split(""))
                            .delayElements(Duration.ofMillis(50)) // 模拟延迟
                            .map(session::textMessage)
                            .map(session::send);
                })
                .then(); 
    }

    // 模拟调用ChatGPT API并逐字返回回复
    private Mono<String> processMessage(String message) {
        return Mono.just("收到消息:" + message + ",正在思考中...").delayElement(Duration.ofSeconds(1))
                .flatMap(initialReply -> {
                    return Flux.range(0, initialReply.length())
                            .map(i -> initialReply.substring(0, i + 1))
                            .delayElements(Duration.ofMillis(100)) // 模拟逐字生成
                            .reduce((a, b) -> b) // 只取最后一个结果
                            .cast(String.class);
                });
    }
}
4.3. 前端 (JavaScript):
复制代码
const socket = new WebSocket('ws://localhost:8080/chat');

socket.onopen = () => {
  console.log('WebSocket 连接已建立');
};

socket.onmessage = (event) => {
  const message = event.data;
  document.getElementById('chat-output').innerHTML += message; 
};

function sendMessage() {
  const message = document.getElementById('chat-input').value;
  socket.send(message);
}

五、SSE方案实现

4.1 技术原理
  • 建立连接: 前端使用 new EventSource() 创建EventSource对象,连接到后端指定的SSE接口。
  • 数据传输:
    • 后端通过 Flux<ServerSentEvent<T>> 返回数据流,Spring WebFlux会自动将数据流转换为SSE格式。
    • 前端监听 onmessage 事件接收后端推送的数据。
  • 关闭连接: 前端调用 EventSource.close() 关闭连接,或者后端停止发送数据。
4.2 代码示例

后端 (Spring WebFlux):

复制代码
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> streamEvents() {
    return Flux.interval(Duration.ofMillis(100))
            .map(sequence -> ServerSentEvent.<String>builder()
                    .data("数据流 - " + sequence)
                    .build());
}

前端 (JavaScript):

复制代码
const eventSource = new EventSource('/stream');

eventSource.onmessage = (event) => {
  const message = event.data;
  document.getElementById('output').innerHTML += message + '<br>';
};

六、方案比较

特点 WebSocket SSE
连接类型 全双工 单向(服务器到客户端)
数据传输 双向 单向
应用场景 需要双向实时通信,如聊天、游戏 服务器推送数据,如实时更新、通知
复杂度 较高 较低

七、总结

本文只是大概介绍了如何利用WebSocket和SSE两种技术实现前端与Spring后端的长连接,并以ChatGPT的流式回复为例,给出了具体的代码实现和技术原理分析。

在实际应用中,需要根据具体需求选择合适的方案。如果需要双向实时通信,WebSocket是更优选择;如果只需服务器单向推送数据,SSE则更为轻量级。无论选择哪种方案,掌握长连接和流式数据处理都是构建现代化实时交互应用的关键。

希望本文能帮助你更好地入门去理解和应用实时流式响应技术,为用户打造更加流畅、自然的交互体验!

后续还会有更加深入去理解和实现技术!

相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax