如何在Spring Boot中集成SSE,实现ChatGPT的流式交互

🏡 博客首页:IT 派同学

⛳️ 欢迎关注 🐳 点赞 🎒 收藏 ✏️ 留言

🎢 本文由 IT 派同学原创编撰

🚧 系列专栏:《SpringBoot入门宝典》

🎈 本系列主要输出作者自创的开源项目

🔗 作品:前往《 AI 捣蛋屋》, 体验最新AI技术的平台,提供AI论文写作、多功能GPT智能体、智能UI生成以及计算机课程设计源码服务,助力学术研究与开发效率提升。


在这里插入图片描述


引言

最近做了一些对接 ChatGPT的应用,深入了解了一下使用 SSE 来实现接口流式打印的功能。那么接下来就跟着文章了解一下 ChatGPT 的流式功能是如何实现的吧。
目前市面上的 Web 应用中,实时数据传输是一个重要的功能需求。无论是在线聊天、股票行情更新,还是实时通知,实时通信技术都扮演着关键角色。SSE(Server-Sent Events)作为一种基于HTTP协议的轻量级实时推送技术,允许服务器向客户端单向传输数据,特别适合用于需要实时更新的场景。

相比WebSocket这种双向通信协议,SSE更简单,兼容性更好,且在多数应用场景下能够满足实时数据推送的需求。尤其是在需要从服务器向客户端频繁推送更新,但不需要客户端频繁回应的情况下,SSE无疑是一个理想的选择。

本文将详细介绍如何在Spring Boot中集成SSE,实现类似ChatGPT的流式交互功能。下面我们将从SSE的基础知识开始,逐步讲解如何配置项目依赖、实现核心功能,并最终完成一个能够进行实时流式交互的应用。

SSE基础知识

什么是SSE

SSE(Server-Sent Events)是一种允许服务器主动向客户端发送更新的技术。它建立在HTTP协议之上,通过简单的文本格式进行数据传输。与传统的请求-响应模式不同,SSE保持客户端与服务器之间的长连接,使得服务器能够实时向客户端推送数据。

SSE的几个关键特性包括:

  • 单向通信:服务器可以持续向客户端发送数据,但客户端不能主动向服务器发送数据。
  • 简单性SSE基于HTTP协议,易于集成和使用,特别适合Web应用。
  • 自动重连:当连接中断时,SSE支持自动重连,确保数据传输的连续性。
SSEWebSocket的对比

在实现实时通信时,WebSocket通常被视为更强大的选择,因为它支持双向通信。然而,在一些应用场景中,SSE却因其简单性和兼容性而更为适用。

  • SSE的优势
    • 简单性:基于HTTP协议,开发者无需引入复杂的协议处理。
    • 兼容性好SSE在浏览器端有更广泛的兼容性,尤其适用于那些不支持WebSocket的环境。
    • 轻量级:适合用于服务器到客户端的单向推送,特别是简单的实时通知场景。
  • WebSocket的优势
    • 双向通信WebSocket支持服务器与客户端之间的双向数据传输,适用于需要频繁互动的场景,如在线聊天或多人协作。
    • 低延迟WebSocket在维持长连接的情况下,能够实现低延迟的实时通信。

因此,如果你的应用需要实现复杂的双向交互,WebSocket可能是更合适的选择;而对于一些只需要简单、单向实时数据推送的场景,SSE则是一个更轻便的方案。

项目结构与依赖配置

Maven依赖配置

Spring Boot项目中使用SSE,我们需要添加相关的依赖。在pom.xml文件中,确保引入了Spring Boot的核心依赖,以及用于HTTP通信的依赖项。

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

在以上配置中,spring-boot-starter-web提供了Web应用的基础功能,hutool-all是一个实用的Java工具类库,lombok则简化了Java代码的编写。接下来,将重点介绍如何在Controller层和前端页面中实现SSE交互。

实现ChatGPT流式交互的核心代码

Controller层的实现

我们首先在Controller中实现SSE的消息推送逻辑。以下是一个简单的ChatController示例,它接受来自客户端的消息,并以流式的方式返回响应数据。

@RestController
public class ChatController {

    private final Map<String, String> msgMap = new ConcurrentHashMap<>();

    @PostMapping("/sendMsg")
    public String sendMsg(@RequestParam String msg) {
        String msgId = IdUtil.simpleUUID();
        msgMap.put(msgId, msg);
        return msgId;
    }

    @GetMapping(value = "/conversation/{msgId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter conversation(@PathVariable("msgId") String msgId) {
        SseEmitter emitter = new SseEmitter();
        String msg = msgMap.remove(msgId);

        new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    ChatMessage chatMessage = new ChatMessage("ChatGPT", "Message part " + i);
                    emitter.send(chatMessage);
                    Thread.sleep(1000);
                }
                emitter.send(SseEmitter.event().name("stop").data(""));
                emitter.complete();
            } catch (IOException | InterruptedException e) {
                emitter.completeWithError(e);
            }
        }).start();

        return emitter;
    }
}

在这个例子中,sendMsg方法接收并存储客户端的消息,conversation方法使用SSE与客户端保持长连接,并按顺序返回多个消息片段,模拟流式输出的效果。

前端页面的实现

前端页面通过HTMLJavaScript与服务器进行交互。以下是一个简单的HTML文件,用于展示与服务器的SSE交互。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ChatGPT Stream</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<h1>ChatGPT Stream</h1>
<div id="chatWindow">
    <div id="outputTxt"></div>
</div>
<input type="text" id="sendTxt" placeholder="Type a message">
<button id="sendBtn">Send</button>

<script>
    $('#sendBtn').on('click', function() {
        var msg = $('#sendTxt').val();
        $.post('/sendMsg', {msg: msg}, function(data) {
            var eventSource = new EventSource('/conversation/' + data);
            eventSource.onmessage = function(event) {
                $('#outputTxt').append('<p>' + event.data + '</p>');
            };
            eventSource.onerror = function() {
                eventSource.close();
            };
        });
    });
</script>
</body>
</html>

在这个页面中,用户可以输入消息并发送给服务器。服务器会通过SSE推送返回数据,并在页面上动态显示。

测试与验证

在本地启动我们新建的 SpringBoot 工程项目之后在浏览器端输入链接 http://localhost:8080/chat/index来访问我刚刚写的那个页面进行接口的测试工作,只需要在页面中的输入框中输入内容并点击发送按钮即可看到页面中数据的实时更新,以此来验证 SSE 的流式交互效果。效果图如下所示:
在这里插入图片描述

总结如下

通过集成SSE,我们在Spring Boot项目中实现了一个简单而高效的实时数据推送机制。SSE的轻量级和易用性使其成为处理实时通知和更新的理想选择。在未来的开发中,我们可以进一步优化该实现,或扩展到其他实时数据场景,如股票行情、实时监控等。

  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT派同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值