springboot2.x使用SSE方式代理或者转发其他流式接口

news/2024/11/1 14:09:06/

文章目录

  • 1.需求描述
  • 2.代码
    • 2.1.示例controller
    • 2.2.示例service
    • 2.3.示例impl
  • 3.测试

1.需求描述

使用SSE的方式主要还是要跟前端建立一个EventSource的链接,有了这个连接,然后往通道里写入数据流,前端自然会拿到流式数据,写啥拿啥,后端这个对象叫做SseEmitter.

2.代码

2.1.示例controller

@Slf4j
@RestController
@RequestMapping("/proxy")
public class StreamForwardingController {@Autowiredprivate ModelService modelService;@GetMapping("/sse/reply")public SseEmitter sseReply(@RequestBody JSONObject req) {try {return modelService.call(req);} catch (IOException e) {log.error("SSE接口异常:{}", e.getMessage());return new SseEmitter();}}
}

2.2.示例service

public interface ModelService {SseEmitter call(JSONObject param) throws IOException;}

2.3.示例impl

@Service
@Slf4j
public class ModelServiceImpl implements ModelService {/*其实可以自己组装SSE流式数据给前端(参考上篇文章)也可以调用别的流式接口,拿到流数据给前端(下面是这种方式)*/@Overridepublic SseEmitter call(JSONObject param) throws IOException {log.info("[SSE]开始调用大模型...");log.info("[SSE]请求参数:{}",param.toString());// 这里是自己的一些参数定义String id = RandomUtil.randomString(32);String xxx = param.getString("xxx");String yyy = param.getString("yyy");// 根据过期时间创建SSE对象SseEmitter sseEmitter = new SseEmitter(0L);// 预处理if(StringUtils.isEmpty(xxx) || StringUtils.isEmpty(yyy)){log.error("[SSE]请求参数为空");sseEmitter.send("error: 请求参数为空");//这里可以不这么做,将报错信息可以发出去sseEmitter.complete();//发完有个结束的标识,目的是为了结束连接return sseEmitter;}//组装流式接口请求对象 这里是请求别人家的流式接口的JSONObject req = new JSONObject();String targetUrl = "http://xxx/x/x/xxx/x/x/x";log.info("[SSE]流式接口:{}", targetUrl);log.info("[SSE]请求报文:{}", req);HttpRequest request = HttpRequest.post(targetUrl).header("Content-Type", ContentType.JSON.toString()).body(JSONUtil.toJsonStr(req)).timeout(10000);// 使用异步请求获取实时数据HttpResponse response = request.executeAsync();log.info("[SSE]模型状态码:{}", response.getStatus());if(response.getStatus() != HttpStatus.HTTP_OK) {log.error("[SSE]模型接口异常:{}",response.body());}//使用新的线程处理响应结果,如果是自己想弄个流式数据给前端返回,也是这个原理//循环往sse对象里send就完事了new Thread(()->{try (BufferedReader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(response.bodyStream())))) {String line;while ((line = reader.readLine()) != null) {//System.out.println("line="+line);if(StringUtils.isNotEmpty(line)) sseEmitter.send(line);//else System.out.println("空行");}log.info("[SSE]模型接口解析完毕.");sseEmitter.complete();}catch (Exception e){log.error("[SSE]模型接口异常:{}", e.getMessage());}}).start();return sseEmitter;//最后记得把sse对象返回给前端}
}

3.测试

使用Postman测试即可,没啥特殊配置。
在这里插入图片描述


http://www.ppmy.cn/news/1543601.html

相关文章

同城行业交流圈子/交友圈子论坛系统有哪些开源架构与优势解析

开源架构 前端 Vue.js与uni-app框架:前端常采用Vue.js框架,特别是结合uni-app进行跨平台开发。uni-app是一个使用Vue.js开发所有前端应用的框架,支持编译为H5、小程序、App等多个平台,实现代码的一次编写,多端运行。…

【机器学习】有监督学习·由浅入深讲解分类算法·Fisher算法讲解

博主简介:努力学习的22级计算机科学与技术本科生一枚🌸博主主页: Yaoyao2024往期回顾: 【机器学习】深入浅出讲解贝叶斯分类算法每日一言🌼: Rivers know this:There is no hurry. We shall get there. 0、…

单例 C++ 懒汉+恶汉

单例设计模式是一种创建型设计模式,确保一个类只有一个实例,减少了内存的开销,并提供一个全局访问点访问该实例。 私有化构造函数、拷贝构造函数、赋值函数 ,定义一个类的私有静态对象成员,定义一个公共的访问该实例静…

一文解析——如何月入过万不是梦

在TikTok(简称TK)这个充满活力的短视频平台上,想要实现大规模的商业价值,有效的账号管理和引流策略至关重要。而TK防关联引流系统的出现,无疑为众多品牌和营销者提供了一个高效、低成本的管理和增长解决方案。通过这一…

【51单片机】矩阵键盘

学习使用的开发板:STC89C52RC/LE52RC 编程软件:Keil5 烧录软件:stc-isp 开发板实图: 文章目录 矩阵键盘 矩阵键盘 矩阵键盘位于开发板的右下角 在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键…

3des算法

使用3des算法,加密模式:CBC,填充:pkcs5padding /*** 3DES加解密类*/ class Des3phpService {//加密秘钥(base64加密)private $key ;//初始偏移向量private $iv;/*** 构造,传递二个已经进行base64_encode的KEY与IV** pa…

ETF申购赎回指南:详解注意事项与低费率券商推荐!

​ETF 申购&赎回 ETF申购赎回是个啥业务? 01 ETF申购、赎回是一种交易委托方式,指投资者通过申购方式(买入方向)获得ETF份额,通过赎回的方式(卖出方向)换掉/卖出ETF份额。ETF申购,通常是通过一篮子成…

基于Springboot的在线考试与学习交流平台的设计与实现

基于Springboot的在线考试与学习交流平台 开发语言:Java 框架:springboot JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:idea 源码获取:https://download.csdn.net/downlo…