当前位置: 首页 > news >正文

SpringBoot集成websocket(5)|(使用OkHttpClient实现websocket以及详细介绍)

SpringBoot集成websocket(5)|(使用OkHttpClient实现websocket以及详细介绍)


文章目录

  • SpringBoot集成websocket(5)|(使用OkHttpClient实现websocket以及详细介绍)
    • @[TOC]
  • 前言
  • 一、初始化OkHttpClient
    • 1.OkHttpClient实现
  • 二、websocket服务代码实现
    • 1.websocket服务端实现
    • 2.SparkClient4Chat 实现
  • 三、websocket客户端代码实现
    • 3.SparkChatServer实现
  • 总结

章节
第一章链接: SpringBoot集成websocket(1)|(websocket客户端实现)
第二章链接: SpringBoot集成websocket(2)|(websocket服务端实现以及websocket中转实现)
第三章链接: SpringBoot集成websocket(3)|(websocket调用websocket采用回调方式实现数据互传)
第四章链接: SpringBoot集成websocket(4)|(使用okhttp3实现websocket)
第五章链接: SpringBoot集成websocket(5)|(使用OkHttpClient实现websocket以及详细介绍)

前言

上篇文章介绍了为什么选用OkHttpClient来实现websocket,本篇章就不过多的讲述,本章主要介绍OkHttpClient实现websocket多级代理跳转中的问题优化以及springboot实现websocket的一些常见问题。

一、初始化OkHttpClient

每个client对象都有自己的线程池和连接池,如果为每个请求都创建一个client对象,自然会出现内存溢出。所以官方建议OkHttpClient应该单例化,重用连接和线程能降低延迟和减少内存消耗。

1.OkHttpClient实现

官方介绍了三种创建client的方式
1、new OkHttpClient()
该方式将创建一个使用默认设置的client单例对象。
2、new OkHttpClient.Builder()
该方式允许自定义配置自己的单例client对象。配置connectionTimeout, readTimeout, writeTimeout等参数。
3、okHttpclient.newBuilder()
该方式通过已经存在的client对象,创建特殊需要的client对象。如 我们通过上个方法创建了自定义配置的单例client对象,但是针对某些场景需要调整某些参数,那么就需要使用该方法创建定制的client。新client对象与旧client对象共享连接池,线程池和其他配置。

    @Beanpublic OkHttpClient getOkHttpClient() {return new OkHttpClient.Builder().connectTimeout(50L, TimeUnit.SECONDS)  // 超时连接时间.readTimeout(3*60L, TimeUnit.SECONDS)  // 超速读取时间.build();}

二、websocket服务代码实现

依赖上篇文章已经介绍过现在不做介绍

1.websocket服务端实现

springboot 服务端代码实现,用于给前端进行连接

@Component
@Data
@Slf4j
@ServerEndpoint(value = "/v1/chat")
public class DocChatServer {// 注意 此处定义的为静态变量,原因是ServerEndpoint 是多例的,不能用springBoo直接注入容器里的对象,static前提是变量都需要是单例,多例的话会有线程安全问题private static SparkClient4ChatBuild sparkClient4ChatBuild;private static OkHttpClient httpClient;@Autowiredprivate void setOriginMessageSender(SparkClient4ChatBuild sparkClient4ChatBuild,OkHttpClient httpClient) {log.debug("客户端连接 A chat 初始化");this.sparkClient4ChatBuild = sparkClient4ChatBuild;this.httpClient = httpClient;}@OnOpenpublic void OnOpen(Session session) {log.debug("客户端连接 A chat 接口");}@OnClosepublic void OnClose() {log.debug("---客户端关闭 A chat 接口");
//        log.info("结束调用cancel");
//        planetClient4Chat.cancel();}@OnErrorpublic void onError(Session session, Throwable t) {log.debug("---客户端连接 A chat 接口异常");t.printStackTrace();}@OnMessagepublic void OnMessage(Session session, String message) {log.debug("客户端连接 A chat 进行中");boolean b = sendGptMessage(session, message);log.debug("客户端连接 A chat 结束:{}", b);}/*** 收到gpt型响应数据处理** @param session 会话id* @return*/private boolean sendGptMessage(Session session, String message) {SparkClient4Chat planetClient4Chat = sparkClient4ChatBuild.build();// 连接第三方ws地址planetClient4Chat.connect(new ApiResponseObserver() {public void onReceive(String message) {log.debug("收到响应数据:{}", message);JsonParse jsonMessage = JSON.parseObject(message).toJavaObject(JsonParse.class);if (jsonMessage.header.status == 2) {try {log.info("运行中调用cancel");planetClient4Chat.cancel();} catch (Exception e) {throw new RuntimeException(e);}}}public void onError(Throwable throwable) {log.debug("会话异常:{}", throwable.getMessage());}public void onCompleted() {log.error("回调收到结束");}});//String messages2 = "{\"讲一个故事\"}";planetClient4Chat.send(message);return true;}}

注意:websocket 是多对象的,每个用户的聊天客户端对应 java 后台的一个 websocket 对象,前后台一对一(多对多)实时连接,所以 websocket 不可能像 servlet 一样做成单例的,让所有聊天用户连接到一个 websocket对象,这样无法保存所有用户的实时连接信息。可能 spring 开发者考虑到这个问题,没有让 spring 创建管理 websocket ,而是由 java 原来的机制管理websocket ,所以用户聊天时创建的 websocket 连接对象不是 spring 创建的,spring 也不会为不是他创建的对象进行依赖注入,所以如果不用static关键字,每个 websocket 对象的 service 都是 null

2.SparkClient4Chat 实现

用于处理第三方chat连接


@Slf4j
@Getter
@Setter
public class SparkClient4Chat {String chatUrl = "ws://xxx/v2.1/chat";private WebSocket webSocket;public void connect(OkHttpClient okHttpClient, ApiResponseObserver apiResponseObserver) {Request request = new Request.Builder().url(url).build();SparkChatServer sparkChatServer = new SparkChatServer(apiResponseObserver);this.webSocket = okHttpClient.newWebSocket(request, sparkChatServer);}public void send(String message) {log.debug("ApiRequest = {}", message);this.webSocket.send(message);}public void cancel() {log.debug("cancel begin...");if (this.webSocket != null) {this.webSocket.cancel();  // cancel暴力关闭(立马见效),用close是不能立马关闭的,管道中的数据还会持续发送过来this.webSocket = null;log.debug("cancel end.");}}public void close() throws Exception {log.debug("close begin...");if (this.webSocket != null) {log.debug("this.webSocket.close(1000, \"NORMAL_CLOSURE\")");this.webSocket.close(1000, "NORMAL_CLOSURE");this.webSocket = null;log.debug("close end...");}}
}

三、websocket客户端代码实现

主要用来连接第三方ws介绍

3.SparkChatServer实现

用于处理第三方chat连接 ,通过回调函数直接放回信息给客户端的连接


@Slf4j
public class SparkChatServer extends WebSocketListener {private ApiResponseObserver apiResponseObserver;public SparkChatServer(ApiResponseObserver apiResponseObserver) {this.apiResponseObserver = apiResponseObserver;}@Overridepublic void onOpen(WebSocket webSocket, Response response) {super.onOpen(webSocket, response);log.debug("连接GPT大模型");}@Overridepublic void onMessage(WebSocket webSocket, String message) {apiResponseObserver.onReceive(message);}@Overridepublic void onFailure(WebSocket webSocket, Throwable t, Response response) {apiResponseObserver.onError(t);log.error("chat连接出现异常:{}", t.getMessage());}
}

总结

本文主要介绍了为什么选用OkHttpClient来实现websocket,本篇章就不过多的讲述,本章主要介绍OkHttpClient实现websocket多级代理跳转中的问题优化以及springboot实现websocket的一些常见问题。

相关文章:

SpringBoot集成websocket(5)|(使用OkHttpClient实现websocket以及详细介绍)

SpringBoot集成websocket(5)|(使用OkHttpClient实现websocket以及详细介绍) 文章目录 SpringBoot集成websocket(5)|(使用OkHttpClient实现websocket以及详细介绍)[TOC] 前言一、初始…...

Kafka-Kafka基本原理与集群快速搭建(实践)

Kafka单机搭建 下载Kafka Apache Download Mirrors 解压 tar -zxvf kafka_2.12-3.4.0.tgz -C /usr/local/src/software/kafkakafka内部bin目录下有个内置的zookeeper(用于单机) 启动zookeeper(在后台启动) nohup bin/zookeeper-server-start.sh conf…...

Elasticsearch 进阶(索引、类型、字段、分片、副本、集群等详细说明)-06

笔记来源:Elasticsearch Elasticsearch进阶 进阶-核心概念 索引Index 一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字…...

hive的分区表和分桶表详解

分区表 Hive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录,每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区,这样的查询效率会提高很多。 静态分区表基本语法 创建分区表 create table dept_p…...

verilog语法进阶-分布式ram

概述: FPGA的LUT查找表是用RAM设计的,所以LUT可以当成ram来使用,也并不是所有的LUT都可以当成ram来使用,sliceM的ram可以当成分布式ram来使用,而sliceL的ram只能当成rom来使用,也就是只能读,不能写&#x…...

HarmonyOS使用HTTP访问网络

HTTP数据请求 1 概述 日常生活中我们使用应用程序看新闻、发送消息等,都需要连接到互联网,从服务端获取数据。例如,新闻应用可以从新闻服务器中获取最新的热点新闻,从而给用户打造更加丰富、更加实用的体验。 那么要实现这样一种…...

GZ015 机器人系统集成应用技术样题1-学生赛

2023年全国职业院校技能大赛 高职组“机器人系统集成应用技术”赛项 竞赛任务书(学生赛) 样题1 选手须知: 本任务书共 25页,如出现任务书缺页、字迹不清等问题,请及时向裁判示意,并进行任务书的更换。参赛队…...

计算机毕业设计 基于SpringBoot的日常办公用品直售推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…...

uniapp:使用fixed定位,iOS平台的安全区域问题解决

manifest.json > 添加节点 "safearea": { //iOS平台的安全区域"background": "#1C1E22","backgroundDark": "#1C1E22", // HX 3.1.19支持"bottom": {"offset": "auto"} },已解决&#xff…...

三层交换机原理与配置

文章目录 三层交换机原理与配置一、三层交换技术概述二、传统的 MLS三、基于CEF 的MLS1、转发信息库(FIB)2、邻接关系表3、工作原理: 四、三层交换机的配置1、三层交换机配置命令2、三层交换机配置步骤 三层交换机原理与配置 一、三层交换技…...

Linux-----5、文件系统

# 文件系统 # 终端的基本操作 ㈠ 打开多个终端 ㈡ 快速清屏 新建标签:command T 新建窗口:command N 关闭标签:command Q 关闭窗口:command W 放大:command 缩小:command - 清屏&#xff…...

电脑自动关机怎么设置?

电脑自动关机怎么设置?如果你是一名上班族,工作忙起来很多事情都会忘记做,有时候忙到很晚后紧急下班,就会忘记给电脑关机,电脑如果经常不关机,那么电脑就会超负荷的运转,大家都知道电脑的寿命是…...

MS5602视频 8 位数模转换器,可替代TLC5602

MS5602 是低功率、超高速视频数模转换器。 MS5602 以 DC 至 20MHz 的采样速率,将数字信号转换成模拟信号。由于高速工作 的特性, MS5602 适合于数字电视、电脑视频处理及雷达信号处 理等数字视频应用。 MS5602 工作在 -40C 至 85C 的温度范围内 …...

Logistic Regression——逻辑回归

1. 为什么需要逻辑回归 在前面学习的线性回归中,我们的预测值都是任意的连续值,例如预测房价。除此之外,还有一个常见的问题就是分类问题,而逻辑回归是一个解决分类问题的模型,其预测值是离散的。 分类问题又包括…...

跟随鼠标动态显示线上点的值(基于Qt的开源绘图控件QCustomPlot进行二次开发)

本文为转载 原文链接: 采用Qt快速绘制多条曲线(折线),跟随鼠标动态显示线上点的值(基于Qt的开源绘图控件QCustomPlot进行二次开发) 内容如下 QCustomPlot是一个开源的基于Qt的第三方绘图库,能…...

Todesk、向日葵等访问“无显示器”主机黑屏问题解决

我的环境是 ubuntu 22.04 安装 要安装 video dummy,请在终端中运行以下命令: sudo apt install xserver-xorg-video-dummy配置 video dummy 的配置文件请自行搜索 使用任何文本编辑器打开此文件。 我的是 /etc/X11/xorg.conf 默认配置文件包含以下内…...

maven打包插件maven-jar-plugin与spring-boot-maven-plugin

maven几种打包插件介绍 文章目录 &#x1f50a;1.spring-boot-maven-plugin打包后效果 &#x1f4d5;2.maven-jar-plugin打包后效果&#x1f58a;️最后总结 &#x1f50a;1.spring-boot-maven-plugin <plugins><plugin><groupId>org.springframework.boot&…...

uniapp微信小程序下载base64图片流或https图片

常规https的图片下载是这样的 const urlPath https://test/logo.png uni.downloadFile({url: urlPath,success(res){// 这时会产生一个临时路径&#xff0c;在应用本次启动期间可以正常使用。if (res.statusCode 200) {// 需要将图片保存到相册uni.saveImageToPhotosAlbum({…...

数据结构 | Log-Structured Merge Tree (LSM Tree)

今天介绍LSM Tree这个数据结构&#xff0c;严格意义上来说&#xff0c;他并不像他的名字一样是一棵树型的数据结构&#xff0c;而更多是一种设计思想。 LSM Tree最先在1996年被提出&#xff0c;后来被广泛运用于现代NoSQL&#xff08;非关系型数据库&#xff09;系统中&#xf…...

QEMU源码全解析 —— virtio(9)

接前一篇文章&#xff1a; 上两回讲解了virtio balloon相关类所涉及的realize函数以及大致流程&#xff0c;如下表所示&#xff1a; realize函数parent_dc_realize函数DeviceClassvirtio_pci_dc_realizePCIDeviceClassvirtio_pci_realizeVirtioPCIClassvirtio_balloon_pci_rea…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...