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…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
