springboot+webSocket对接chatgpt
webSocket对接参考
话不多说直接上代码
WebSocket
package com.student.config;import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;/*** @Description:* @Author: hwk* @Date: 2024-07-17 17:46* @Version: 1.0**/
@Slf4j
@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {/*** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/private Session session;/*** gpt密钥*/private static final String key = "";/*** 请求地址*/private static final String url = "";/*** 用户ID*/private String userId;//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。//虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。// 注:底下WebSocket是当前类名private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();// 用来存在线连接用户信息private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<String, Session>();/*** 链接成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam(value = "userId") String userId) {try {this.session = session;this.userId = userId;webSockets.add(this);sessionPool.put(userId, session);log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());} catch (Exception e) {}}/*** 链接关闭调用的方法*/@OnClosepublic void onClose() {try {webSockets.remove(this);sessionPool.remove(this.userId);log.info("【websocket消息】连接断开,总数为:" + webSockets.size());} catch (Exception e) {}}/*** 收到客户端消息后调用的方法** @param message*/@OnMessagepublic void onMessage(String message) {log.info("【websocket消息】收到客户端消息:" + message);JSONObject jsonObject = new JSONObject();JSONArray objects = new JSONArray();JSONObject messages = new JSONObject();messages.put("role", "user");messages.put("content", message);objects.add(messages);jsonObject.put("model", "gpt-3.5-turbo");jsonObject.put("messages", objects);jsonObject.put("max_tokens", 1024);jsonObject.put("temperature", 0);jsonObject.put("stream", true);Map<String, String> heads = new HashMap<>();heads.put("Content-Type", "application/json");heads.put("Accept", "application/json");heads.put("Authorization", "Bearer "+key);WebClient webClient = WebClient.create();Flux<String> stringFlux = webClient.post().uri(url).header("Content-Type", "application/json").header("Accept", "application/json").header("Authorization", "Bearer " + key).accept(MediaType.TEXT_EVENT_STREAM).bodyValue(jsonObject).retrieve().bodyToFlux(String.class);stringFlux.subscribe(s -> {if (!Objects.equals(s, "[DONE]")) {JSONObject parsed = JSONObject.parseObject(s);JSONArray choices = parsed.getJSONArray("choices");if (!choices.isEmpty()) {JSONObject dataJson = JSONObject.parseObject(choices.get(0).toString());String content = dataJson.getJSONObject("delta").getString("content");if (StringUtils.hasLength(content)) {try {content = content.replaceAll("\n", "<br>");content = content.replace(" ", "");log.info(content);if (sessionPool != null) {sessionPool.get(userId).getBasicRemote().sendText(content);}} catch (Exception e) {e.printStackTrace();}}}}});}/*** 发送错误时的处理** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("用户错误,原因:" + error.getMessage());error.printStackTrace();}/*** 此为广播消息** @param message*/public void sendAllMessage(String message) {log.info("【websocket消息】广播消息:" + message);for (WebSocket webSocket : webSockets) {try {if (webSocket.session.isOpen()) {webSocket.session.getAsyncRemote().sendText(message);}} catch (Exception e) {e.printStackTrace();}}}/*** 此为单点消息** @param userId* @param message*/public void sendOneMessage(String userId, String message) {Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {try {log.info("【websocket消息】 单点消息:" + message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}/*** 此为单点消息(多人)** @param userIds* @param message*/public void sendMoreMessage(String[] userIds, String message) {for (String userId : userIds) {Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {try {log.info("【websocket消息】 单点消息:" + message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}}
}
WebSocketConfig
package com.student.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @Description: WebSocketConfig配置* @Author: hwk* @Date: 2024-07-17 17:44* @Version: 1.0**/
@Configuration
public class WebSocketConfig {/*** 注入ServerEndpointExporter,* 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
html代码
<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><title>ChatGPT</title><script src="marked.min.js"></script><link rel="stylesheet" type="text/css" href="index.css"><style>.normal-text {color: black;}.rich-text {color: blue;font-weight: bold;}</style>
</head>
<body><h2>ChatGPT</h2><div id="message-container"><p id="message"></p></div><div id="footer"><input id="text" class="my-input" type="text" /><button onclick="send()">发送</button></div><div id="footer1"><br /><button onclick="closeWebSocket()">关闭WebSocket连接</button><button onclick="openWebSocket()">建立WebSocket连接</button></div><script>marked.setOptions({highlight: function (code, lang) {return hljs.highlightAuto(code).value;}});var websocket = null;// 判断当前浏览器是否支持WebSocket,是则创建WebSocketif ('WebSocket' in window) {console.log("浏览器支持WebSocket");websocket = new WebSocket("ws://127.0.0.1:8056/websocket/1");} else {alert('当前浏览器不支持WebSocket');}// 连接发生错误的回调方法websocket.onerror = function () {console.log("WebSocket连接发生错误");setMessageInnerHTML("WebSocket连接发生错误");};// 连接成功建立的回调方法websocket.onopen = function () {console.log("WebSocket连接成功");};// 接收到消息的回调方法websocket.onmessage = function (event) {if (event.data) {setMessageInnerHTML(event.data);}console.log(event.data);};// 连接关闭的回调方法websocket.onclose = function () {console.log("WebSocket连接关闭");};// 关闭WebSocket连接function closeWebSocket() {websocket.close();}// 发送消息function send() {var message = document.getElementById('text').value;websocket.send(message);}// 建立连接的方法function openWebSocket() {websocket = new WebSocket("ws://127.0.0.1:8056/websocket/1");websocket.onopen = function () {console.log("WebSocket连接成功");};}// 将消息显示在网页上function setMessageInnerHTML(innerHTML) {console.log(innerHTML);// var element = document.getElementById('message');// if (innerHTML.match(/```/g)) {// element.innerHTML += marked(innerHTML); // 使用marked渲染Markdown// } else {// element.innerHTML += innerHTML; // 直接添加普通文本消息// }document.getElementById('message').innerHTML += innerHTML;}// 如果websocket连接还没断开就关闭了窗口,后台server端会抛异常。// 所以增加监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接window.onbeforeunload = function () {closeWebSocket();};</script>
</body>
</html>
效果

相关文章:
springboot+webSocket对接chatgpt
webSocket对接参考 话不多说直接上代码 WebSocket package com.student.config;import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springfram…...
【ROS2】 默认的DDS通信中间件替换为Eclipse Cyclone_DDS (DDS配置方法)
ROS2替换中间件为Cyclone_DDS 1.一些介绍:)2.不同DDS的RMW实现3.默认的FastDDS替换为Cyclone DDSi.安装依赖ii.编译 cyclone-dds 4.配置网络 1.一些介绍:) 上一篇我们探讨了ros1和ros2编写launch的区别 【ROS2】launch启动文件编…...
迈向数智金融:机器学习金融科技新纪元的新风采
个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…...
Nginx+PHP+CI框架实现,访问静态文件带权限验证
1、访问来源验证配置nginx #文件访问来源校验 如路径:https://ys.test.com/test/api/uploads/test.png #不是该允许域名的将返回403页面 location /test/api/uploads/ {valid_referers ys.test.com ys.test2.com;if ($invalid_referer) {return 403;} }2、拦截访问…...
javascript 第二天
正则表达式 a/正则表达式内容/ a.test(“需要检测的内容”) 焦点事件 onfocus 获得焦点 onblur 失去焦点 他们都是事件,和onclick一样 onchange 内容改变 失去焦点时生效,多了内容检测,如果内容不变不触发,内容改变才触发 onk…...
unity2D游戏开发17战斗精灵
导入 将PlayerFight32x32.png拖Player文件夹进去 设置属性 创建动画剪辑 选中前四帧,右键Create|Animation,将动画命名为player-ire-east 其他几个动画也创建好后,将其拖到Animations|Animations文件夹 选中PlayerController,再点击Animator 创建新的Blend Tree Graph,并重…...
kafka架构+原理+源码
1.安装jdk17 sudo yum -y update sudo wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm sudo yum -y install ./jdk-17_linux-x64_bin.rpm sudo java -version 2.安装kafka How to easily install kafka without zookeeper | Aditya’s Blog 1.…...
实力共鉴!微风企斩获2024年浙江省专精特新中小企业
日前,微风企斩获2024年浙江省专精特新中小企业荣誉,这是继获得“国家高新技术企业”“浙江省科技中小企业”“杭州市雏鹰计划企业”等权威性认证后,微风企荣获的又一重磅殊荣。 “专精特新中小企业”是国家对具有“专业化、精细化、特色化、新…...
C#:枚举及位标志周边知识详解(小白入门)
文章目录 枚举为什么要有枚举?枚举的性质设置默认类型和显式设置成员的值 位标志(重要)位标记是什么及作用位标志周边知识HasFlag判断是否有该功能枚举前面加Flags的好处 关于枚举的更多知识using static简化代码获取枚举成员的字面量 枚举 为什么要有枚举? 为了增加代码的…...
这本vue3编译原理开源电子书,初中级前端竟然都能看懂
前言 众所周知vue提供了很多黑魔法,比如单文件组件(SFC)、指令、宏函数、css scoped等。这些都是vue提供的开箱即用的功能,大家平时用这些黑魔法的时候有没有疑惑过一些疑问呢。 我们每天写的vue代码一般都是写在*.vue文件中,但是浏览器却只…...
小白如何安装WNO(小波神经算子),需要安装python3.8,torch,ptwt,pywt等
下载项目 WNO在github上面的项目地址如下: https://github.com/csccm-iitd/WNO/tree/main 下载下来后,里面的数据集需要用matlab代码生成,也可以到里面提到的google云盘里面下载数据集 安装环境 然后需要安装环境 注意python版本一定要…...
Java HashMap 源码解读笔记(一)--xunznux
文章目录 HashMap介绍实现说明:源码解读静态常量和内部节点类 Node静态工具方法属性字段 Fields未完待续。。。 HashMap 本文主要是用于记录我在阅读Java1.8的 HashMap 源码所做的笔记。对于源码中的注释会进行翻译下来,并且会对其中部分源码进行注释。 这一篇文章…...
“等保测评下的数据加密与隐私保护“
在当今数字化时代,数据已成为企业最宝贵的资产之一。然而,数据泄露、隐私侵犯等事件频发,不仅给企业带来经济损失,更严重损害了公众信任。等保测评,作为国家信息安全等级保护制度的重要组成部分,对数据加密…...
Oat++ 后端实现跨域
这里记录在官方的例子中,加入跨域。Oat Example-CRUD 在官方的例子中,加入跨域。 Oat Example-CRUD 修改AppComponent.hpp文件中的代码,如下: #include "AppComponent.hpp"#include "controller/UserController…...
Three basic starting points to do AI
Computers have been based on memory/storage for so many years. Don’t try to come up with something else. For so many years, AI has been based on fixed precise rules or fuzzy matching rules. Don’t think about coming up with the third one by yourself. Vi…...
等保测评练习卷22
等级保护初级测评师试题22 姓名: 成绩: 一、判断题(10110分) 1. 在应用系统测试中,如果审计是一个独立的功能,那么应用系统应对审计进程进行保…...
Linux用户-普通用户
作者介绍:简历上没有一个精通的运维工程师。希望大家多多关注我,我尽量把自己会的都分享给大家,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux是一个多用户多任务操作系统,这意味着它可以同时支持多个用户登录并使用系统。…...
世界顶级思想家颜廷利:生命的升华,人类与动物的进化之道
世界顶级思想家颜廷利:生命的升华,人类与动物的进化之道 动物在于进化, 人类载于净化…(升命学说) 当代世界最著名的哲学家颜廷利教授指出,在探索生命奥秘的广阔旅程中,我们不禁惊叹于大自然…...
团队心脏:项目比赛中激发团队潜力的策略与技巧
团队心脏:项目比赛中激发团队潜力的策略与技巧 前言项目负责人的角色定位执行力的重要性提升个人执行力的策略团队协作的关键持续学习与创新应对挑战的态度总结与反思结语 前言 在项目管理的世界里,每一次比赛都是一场没有硝烟的战争。作为项目负责人&am…...
Qt安卓开发的一些概念
目录 1、Android 版本和 API 的对应关系? 2、ABI是什么 2.1、x86_64 2.2、x86 2.3、arm64-v8a 2.4、armeabi-v7a 3、不同架构的特点 3.1、32位 ARM 架构 (ARMv7) 3.2、64位 ARM 架构 (ARMv8-A) 3.3、32位 Intel 架构 (x86) 3.4、64位 Intel 架构 (x86-64…...
拆解、对比与优化:LLM工具智能体的五种任务规划与执行模式
大语言模型(LLM)驱动的 AI 智能体,特别是在借助Tools(工具)来完成复杂任务执行的过程中展现出了巨大的潜力。然而,让智能体能够合理规划任务步骤与执行、避免盲目行动是确保其高效可靠完成目标的关键。本篇…...
快图设计:5个理由告诉你为什么这款Vue图片编辑器值得尝试
快图设计:5个理由告诉你为什么这款Vue图片编辑器值得尝试 【免费下载链接】vue-fabric-editor 快图设计-基于fabric.js和Vue的开源图片编辑器,可自定义字体、素材、设计模板。fabric.js and Vue based image editor, can customize fonts, materials, de…...
ARM MPAM内存系统监控器架构与配置详解
1. ARM MPAM内存系统监控器架构解析在ARMv9架构中,MPAM(Memory Partitioning and Monitoring)作为关键的内存资源管控机制,为多租户环境提供了硬件级的资源隔离与性能监控能力。其核心设计理念是通过PARTID(Partition …...
ECharts地图渲染报错‘跨域’?别慌,一个本地静态服务器(anywhere)就能搞定
ECharts地图渲染报错‘跨域’?本地静态服务器解决方案全解析 当你兴奋地准备好本地GeoJSON数据文件,准备在ECharts中实现炫酷的地图可视化效果时,突然遭遇浏览器控制台抛出的"CORS policy"跨域错误,这感觉就像即将到达…...
作业4:独立按键+数码管实操
文章目录 1.测试代码视频2.流水灯视频3.独立按键视频(点亮四个灯)4.独立按键视频(思考题点亮8个灯)5.数码管显示“111111”6.数码管显示“123456”7.数码管显示“11.12.13”8.数码管显示“HH8800.” 1.测试代码视频 测试2.流水灯视频 流水灯#include <reg51.h> // 包含…...
Transformer注意力机制数据流优化与MMEE方法实践
1. 注意力机制数据流优化概述在Transformer架构和大型语言模型(LLM)中,注意力机制的计算开销通常占整体工作负载的60%以上。随着模型处理序列长度的不断增加,注意力计算面临的性能瓶颈日益凸显——其计算复杂度与序列长度呈二次方关系。这种特性使得传统…...
AI编程代理全景导航:从技术选型到实战评估指南
1. 项目概述:一个探索智能编码代理的“藏宝图”最近在GitHub上闲逛,发现了一个挺有意思的项目,叫tndata/CodingAgentExplorer。光看名字,你可能会觉得这又是一个关于AI代码生成或者大语言模型(LLM)的常规仓…...
终极兼容方案:让老旧游戏手柄在现代游戏中重获新生
终极兼容方案:让老旧游戏手柄在现代游戏中重获新生 【免费下载链接】XOutput DirectInput to XInput wrapper 项目地址: https://gitcode.com/gh_mirrors/xo/XOutput 还在为那些功能完好却被现代游戏抛弃的经典游戏手柄感到惋惜吗?我们深知那种无…...
【AI原生应用CI/CD黄金标准】:SITS2026权威白皮书首度解密——7大不可绕过的工程范式跃迁
更多请点击: https://intelliparadigm.com 第一章:SITS2026白皮书核心定位与范式革命性意义 SITS2026(Semantic-Integrated Trustworthy Systems 2026)白皮书并非传统技术路线图的延伸,而是面向AI原生时代构建可信系统…...
教育科技项目如何利用Taotoken平衡AI功能效果与研发成本
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 教育科技项目如何利用Taotoken平衡AI功能效果与研发成本 在在线教育平台的发展过程中,引入AI驱动的功能,如…...
