DeepSeekApi对接流式输出异步聊天功能:基于Spring Boot和OkHttp的SSE应用实现

实现异步聊天功能:基于Spring Boot和OkHttp的SSE应用

在现代Web应用程序开发中,实时更新的能力对于增强用户体验至关重要。本文将详细介绍如何利用Spring Boot框架结合OkHttp库实现一个简单的异步聊天服务,该服务能够接收用户输入并通过Server-Sent Events (SSE) 向客户端推送实时更新。

一、技术栈选择

为了构建这个服务,我们选择了以下技术:

  • Spring Boot:用于快速搭建RESTful API服务。
  • OkHttp:一款高效的HTTP客户端库,适用于Java应用,支持异步请求处理。
  • SSE(Server-Sent Events):一种允许服务器向浏览器推送更新的技术,特别适合于需要实时更新的应用场景。

二、核心逻辑详解

ChatController 类概览

我们的ChatController类主要包含了一个名为oneShot的方法,它负责接收POST请求,处理请求,并通过SSE返回结果给客户端。以下是该方法的具体实现细节。

定义HttpClient实例

首先,我们定义了一个OkHttpClient实例,设置了读取、写入和连接超时时间为60秒,以确保在网络状况不佳时仍有足够的时间完成操作。

private final OkHttpClient client = new OkHttpClient.Builder()
        .readTimeout(60, TimeUnit.SECONDS)
        .writeTimeout(60, TimeUnit.SECONDS)
        .connectTimeout(60, TimeUnit.SECONDS)
        .build();
oneShot 方法

oneShot方法是一个POST请求映射方法,它接收来自客户端的JSON格式数据,并转发至另一个API进行处理,最后通过SSE将结果推送给客户端。

@PostMapping(value = "/chat/oneShot", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter oneShot(@RequestBody String requestBody) {
    SseEmitter emitter = new SseEmitter(); // 创建一个新的SseEmitter实例用于异步事件流传输。

    // 使用OkHttp创建请求体,设置媒体类型为application/json,内容为requestBody。
    RequestBody body = RequestBody.create(MediaType.APPLICATION_JSON_VALUE, requestBody);
    // 构造一个HTTP POST请求,目标URL为http://10.155.28.19:11434/api/chat,携带body作为请求体。
    Request request = new Request.Builder()
            .url("http://DeepSeek地址")
            .post(body)
            .build();

    // 异步执行HTTP请求,并注册回调处理响应或错误。
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) { // 请求失败时调用此方法。
            handleError(emitter, e); // 调用handleError处理错误。
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException { // 请求成功时调用此方法。
            if (!response.isSuccessful()) { // 检查响应是否成功。
                handleError(emitter, new IOException("Unexpected code " + response)); // 如果不成功,则处理错误。
                return;
            }

            try (ResponseBody responseBody = response.body()) { // 获取响应体。
                if (responseBody != null) { // 确保响应体非空。
                    processResponseStream(responseBody.byteStream(), emitter); // 处理响应流。
                }
            } catch (Exception e) { // 捕获可能的异常。
                handleError(emitter, e); // 出现异常时处理错误。
            }
        }
    });

    return emitter; // 返回SseEmitter实例,开始向客户端发送事件流。
}
错误处理方法

当发生网络错误或其他异常情况时,我们通过handleError方法将错误信息发送给客户端。

private void handleError(SseEmitter emitter, Exception e) {
    try {
        emitter.send(SseEmitter.event().id("error").data(e.getMessage())); // 发送错误事件。
        emitter.completeWithError(e); // 完成SseEmitter,并附带错误。
    } catch (IOException ex) { // 捕获可能的IO异常。
        ex.printStackTrace(); // 打印堆栈跟踪。
    }
}
响应流处理方法

该方法负责从响应流中读取数据,并将其分割成单独的JSON对象,然后通过SSE发送给客户端。

private void processResponseStream(java.io.InputStream inputStream, SseEmitter emitter) {
    try {
        byte[] buffer = new byte[1024]; // 创建一个1024字节的缓冲区。
        int bytesRead; // 存储每次读取的字节数。
        while ((bytesRead = inputStream.read(buffer)) != -1) { // 循环读取输入流直到结束。
            String data = new String(buffer, 0, bytesRead); // 将读取的字节转换为字符串。
            // 假设每条消息是以换行符分隔的JSON对象。
            for (String line : data.split("\n")) { // 分割字符串,按行处理。
                if (!line.trim().isEmpty()) { // 忽略空行。
                    emitter.send(SseEmitter.event().data(line)); // 发送每一行数据作为事件。
                }
            }
        }
        emitter.complete(); // 完成SseEmitter,表示所有数据已发送完毕。
    } catch (IOException e) { // 捕获可能的IO异常。
        handleError(emitter, e); // 出现异常时处理错误。
    }
}

三、实践示例与代码解释

通过上述步骤,我们可以看到如何有效地集成Spring Boot与OkHttp,以及如何利用SSE为用户提供流畅的交互体验。整个过程包括接收客户端请求、转发请求到后端服务、处理响应并将结果实时推送给客户端。

关键点总结

  • 异步请求处理:使用OkHttp的异步请求机制避免了阻塞主线程,提高了程序的响应速度。
  • 错误处理:无论是网络问题还是响应处理过程中出现的异常,都被妥善处理并通过SSE通知客户端。
  • 流式传输:通过SSE机制实现了对响应流的逐行解析和实时推送,增强了用户体验。

四、结论

本文详细介绍了如何使用Spring Boot结合OkHttp和SSE技术构建一个简易但功能强大的异步聊天服务。这种方法不仅提高了开发效率,还增强了用户体验,非常适合需要实时更新的应用场景。希望这篇文章能为你的项目带来灵感,并帮助你更好地理解和运用这些技术。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/969815.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【教程】MySQL数据库学习笔记(七)——多表操作(持续更新)

写在前面: 如果文章对你有帮助,记得点赞关注加收藏一波,利于以后需要的时候复习,多谢支持! 【MySQL数据库学习】系列文章 第一章 《认识与环境搭建》 第二章 《数据类型》 第三章 《数据定义语言DDL》 第四章 《数据操…

国自然地区基金|影像组学联合病理组学预测进展期胃癌术后预后的研究|基金申请·25-02-13

小罗碎碎念 今天和大家分享一个国自然地区科学项目,执行年限为2020.01~2023.12,直接费用为34万元。 胃癌在我国发病形势严峻,现有TNM分期预后评估存在局限,难以满足精准医疗需求。本项目运用“医工结合,学科…

nvm下载安装教程(node.js 下载安装教程)

前言 nvm 官网地址:https://nvm.uihtm.com nvm 是一个 node.js 的版本管理工具,相比于仅安装 node.js,我们可以使用 nvm 直接下载或卸载 node.js,可以同时安装多个 node.js 版本,并动态的切换本地环境中的 node.js 环…

项目BUG

项目BUG 前言 我创作这篇博客的目的是记录学习技术过程中的笔记。希望通过分享自己的学习经历,能够帮助到那些对相关领域感兴趣或者正在学习的人们。 项目BUG 1.低频率信号(100k或 200K以下)可以直接用一根导线焊接出几根导线来分几路,高频率信号只能…

Apollo 9.0 速度动态规划决策算法 – path time heuristic optimizer

文章目录 1. 动态规划2. 采样3. 代价函数3.1 障碍物代价3.2 距离终点代价3.3 速度代价3.4 加速度代价3.5 jerk代价 4. 回溯 这一章将来讲解速度决策算法,也就是SPEED_HEURISTIC_OPTIMIZER task里面的内容。Apollo 9.0使用动态规划算法进行速度决策,从类名…

吴恩达深度学习——词嵌入

内容来自https://www.bilibili.com/video/BV1FT4y1E74V,仅为本人学习所用。 文章目录 词表特征词嵌入的类比推理嵌入矩阵词嵌入Word2Vec跳字模型模型细节负采样 GloVe词向量(了解) 情绪分类 词表特征 使用 one-hot 对词汇进行编码时&#x…

数据结构——Makefile、算法、排序(2025.2.13)

目录 一、Makefile 1.功能 2.基本语法和相关操作 (1)创建Makefile文件 (2)编译规则 (3)编译 (4)变量 ①系统变量 ②自定义变量 二、 算法 1.定义 2.算法的设计 &#xff…

达梦:TPCC 压测

目录 造数1. 脚本启动2. 检查数据库信息3. 删除旧用户和表空间4. 创建新的表空间5. 创建用户和表6. 数据加载7. 创建索引8. 创建存储过程和序列9. 检查数据空间使用情况10. 启用表的快速访问池11. 数据加载完成总结 压测1. 脚本启动2. 检查数据表空间3. 设置表的快速池标志4. 检…

2024 StoryDiffusion 文字/文字+图像----->视频

基于扩散模型的生成模型在生成长序列图像和视频时面临内容一致性的重大挑战,尤其是涉及复杂主题和细节的场景中,角色身份、服饰风格等元素难以保持连贯。传统方法通常依赖潜在空间的运动预测,但长视频生成时易出现不稳定性。针对这些问题&…

在带有Intel Arc GPU的Windows上安装IPEX-LLM

在带有Intel Arc GPU的Windows上安装IPEX-LLM 在带有Intel Arc GPU的Windows上安装IPEX-LLM先决条件安装 GPU 驱动安装 Visual Studio 2022 社区版安装 Intel oneAPI Base Toolkit安装 IPEX-LLM创建虚拟环境环境验证 可能遇到的问题 在带有Intel Arc GPU的Windows上安装IPEX-LL…

流程控制(if—elif—else,while , for ... in ...)

1. 流程控制 流程:计算机执行代码的顺序 流程控制:对计算机执行代码的顺序的管理 2. 流程控制分类 流程控制分类: 顺序流程:自上而下的执行结构,即 Python 默认流程 选择/分支流程:根据某一步的判断&am…

SpringBoot实战:高效获取视频资源

文章目录 前言技术实现SpringBoot项目构建产品选取配置数据采集 号外号外 前言 在短视频行业高速发展的背景下,海量内容数据日益增长,每天都有新的视频、评论、点赞、分享等数据涌现。如何高效、精准地获取并处理这些庞大的数据,已成为各大平…

SSL域名证书怎么申请?

在数字化时代,网络安全已成为企业和个人不可忽视的重要议题。SSL(Secure Sockets Layer,安全套接层)域名证书,作为保障网站数据传输安全的关键工具,其重要性日益凸显。 一、SSL域名证书:网络安…

用大模型学大模型04-模型与网络

目前已经学完深度学习的数学基础,开始学习各种 模型和网络阶段,给出一个从简单到入门的,层层递进的学习路线。并给出学习每种模型需要的前置知识。增加注意力机制,bert, 大模型,gpt, transformer, MOE等流行…

DeepSeek4j 已开源,支持思维链,自定义参数,Spring Boot Starter 轻松集成,快速入门!建议收藏

DeepSeek4j Spring Boot Starter 快速入门 简介 DeepSeek4j 是一个专为 Spring Boot 设计的 AI 能力集成启动器,可快速接入 DeepSeek 大模型服务。通过简洁的配置和易用的 API,开发者可轻松实现对话交互功能。 环境要求 JDK 8Spring Boot 2.7Maven/Gr…

graphRAG的原理及代码实战(2)基本原理介绍(中)

graphRAG-结果解读 1、简介 前文中,graphRAG项目index索引建立完成后,会生成7个parquet文件。 为什么用 Parquet 格式保存知识图谱? 高效存储: 知识图谱中的数据通常是结构化的,包含大量的实体、关系、嵌入等。Parq…

TLQ-CN10.0.2.0 (TongLINK/Q-CN 集群)部署指引 (by lqw)

文章目录 安装准备虚拟机部署部署zk集群安装zk集群启动zk集群初始化元数据(zk)关闭zk集群 部署BookKeeper集群安装BookKeeper集群初始化元数据(bk)启动BookKeeper停止 BookKeeper 部署Brokers集群安装Brokers集群启动 broker停止 …

深入剖析推理模型:从DeepSeek R1看LLM推理能力构建与优化

著名 AI 研究者和博主 Sebastian Raschka 又更新博客了。原文地址:https://sebastianraschka.com/blog/2025/understanding-reasoning-llms.html。这一次,他将立足于 DeepSeek 技术报告,介绍用于构建推理模型的四种主要方法,也就是…

【Sceneform-EQR】实现3D场景背景颜色的定制化(背景融合的方式、Filament材质定制)

写在前面的话 Sceneform-EQR是基于(filament)扩展的一个用于安卓端的渲染引擎。故本文内容对Sceneform-EQR与Filament都适用。 需求场景 在使用Filament加载三维场景的过程中,一个3D场景对应加载一个背景纹理。而这样的话,即便…

Visual Studio 2022在配置远程调试服务器时无法连接到OpenEuler24.03

表现为在VS中为OpenEuler24.03创建远程服务器时,界面上直接报主机密钥算法失败,或直接提示无法连接到服务器,导致无法创建远程服务器。 经查询日志发现一些蛛丝马迹 09:25:15.2035105 [Info, Thread 53] liblinux.Local.Services.WslEnumer…