[Spring] OpenFeign的使用
🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (93平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
🐰RabbitMQ(97平均质量分) https://blog.csdn.net/2301_80050796/category_12792900.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
目录
- 1. RestTemplate存在的问题
- 2. OpenFeign介绍
- 2.1 引入依赖
- 2.2 添加注解
- 2.3 编写OpenFeign客户端
- 2.4 远程调用
- 2.5 测试
- 3. OpenFeign参数传递
- 3.1 传递单个参数
- 3.2 传递多个参数
- 4.3 传递对象
- 3.4 传递Json
- 4. 最佳实践
- 4.1 Feign继承方式
- 4.2 Feign抽取方式
1. RestTemplate存在的问题
观察我们之前远程调用的代码
public OrderInfo selectOrder(Integer id){OrderInfo orderInfo = orderMapper.selectOrderById(id);//把获取到的服务URL拼接到远程调用的URL中String url = "http://product-service/product/select?id=" + orderInfo.getProductId();ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;
}
虽然说RestTemplate对HTTP封装之后,已经比直接使用HTTP Client方便很多,但是还是存在一些问题的.
- 需要拼接URL,灵活性高,但是封装臃肿,URL复杂的时候,容易出错.
- 代码可读性差,风格不统一.
微服务之间的通行主要有两种方式,一种是RPC,一种是HTTP.在SpringCloud中,默认是使用HTTP进行通信的,最常用的实现形式有两种:
- RestTemplate
- OpenFeign
接下来我们就来详细介绍一下OpenFeign.
2. OpenFeign介绍
OpenFeign是一个声明式的Web Service客户端.它让微服务之间的调用变得更加简单,类似与Controller调用Service,只需要创建一个接口,然后再添加注解就可以使用OpenFeign.
2.1 引入依赖
首先我们需要在服务调用方(order-service)中引入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.2 添加注解
在order-service的启动类添加注解,@EnableFeignClients
,开启OpenFeign的功能.
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class,args);}
}
2.3 编写OpenFeign客户端
在调用其他服务的客户端之下,编写API调用接口,基于SpringMVC的注解来声明远程调用的信息.
@FeignClient(name = "product-service")
public interface ProductApi {@RequestMapping("/product/select")ProductInfo getProductInfo(@RequestParam("id")Integer id);
}
[注意]:在接口的参数前面必须使用@RequestParam加上所调用服务接口的对应参数,否则参数无法传入,就相当于在请求的后面加上了?参数=xxx
.
也可以把该服务的接口的统一前缀(放在类上的@RequestMapping
)统一放到FeignClient注解的Path参数中.
@FeignClient(name = "product-service",path = "/product")
public interface ProductApi {@RequestMapping("/select")ProductInfo getProductInfo(@RequestParam("id")Integer id);
}
@FeignClient
注解作用在接口上,参数说明:
- name/value: 指定OpenFeign的名称,也就是被调用的微服务的名称,用于服务发现,Feign底层会使用SpringLoadBalance进行负载均衡.
当然也可以使用URL属性指定一个具体的URL. - Path: 定义当前FeignClient的统一前缀,一般是被调用方Controller层的类注解.
2.4 远程调用
修改远程调用方法
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate ProductApi api;//设置原子类public OrderInfo selectOrder(Integer id){OrderInfo orderInfo = orderMapper.selectOrderById(id);//把获取到的服务URL拼接到远程调用的URL中Integer productId = orderInfo.getProductId();ProductInfo productInfo = api.getProductInfo(productId);orderInfo.setProductInfo(productInfo);return orderInfo;}
}
2.5 测试
启动服务.访问接口,测试远程调用.
3. OpenFeign参数传递
3.1 传递单个参数
我们上面2.4的例子就是单个参数的调用.下面我们再来举一个例子
- 服务提供方product-service
@RestController
@RequestMapping("/product")
public class ProductController {@RequestMapping("/p1")public String p1(Integer id){return "接收到参数"+id;}
}
- FeginClient
@FeignClient(value = "product-service")
public interface ProductApi {@RequestMapping("/product/p1")String p1(@RequestParam("id") Integer id);
}
和我们上面提到的一样,@RequestParam是用来做参数绑定的,不能省略.
3. order-service
@RequestMapping("/order")
@RestController
public class OrderController {@Autowiredprivate ProductApi api;@RequestMapping("/p1")public String p1(Integer id){return api.p1(id);}
}
远程测试调用:GET http://127.0.0.1:8080/order/p1?id=1
3.2 传递多个参数
使用多个@RequestParam
进行参数绑定即可
- 服务提供方product-service
@RestController
@RequestMapping("/product")
public class ProductController {@RequestMapping("/p2")public String p2(Integer id1,Integer id2){return "接收到参数1:" + id1 + ",接收到参数2:" + id2;}
}
- FeignClient
@FeignClient(value = "product-service")
public interface ProductApi {@RequestMapping("/product/p2")String p2(@RequestParam("id1") Integer p1,@RequestParam("id2") Integer p2);
}
- 服务消费方order-service
@RequestMapping("/order")
@RestController
public class OrderController {@Autowiredprivate ProductApi api;@RequestMapping("/p2")public String p2(Integer p1,Integer p2){return api.p2(p1,p2);}
}
调用接口进行测试:GET http://127.0.0.1:8080/order/p2?p1=1&p2=2
4.3 传递对象
- 服务提供方product-service
@RequestMapping("/p3")
public String p3(ProductInfo productInfo){return "接收到对象:" + productInfo;
}
- Feign
@RequestMapping("/product/p3")
String p3(@SpringQueryMap ProductInfo productInfo);
其中@SpringQueryMap
注解表示的是:可以方便地将一个对象的属性作为请求的查询参数添加到请求的 URL中,避免了手动构建查询参数字符串(如json)的繁琐过程.
3. order-service
@RequestMapping("/p3")
public String p3(ProductInfo productInfo){return api.p3(productInfo);
}
测试远程调用:GET http://127.0.0.1:8080/order/p3?id=5&productName=zhangsan
3.4 传递Json
和我们之前学习SpringBoot的时候一样,同样是使用@RequestBody
注解进行绑定.
注意由于数据在服务之间一直是按照Json格式传递的,所以服务方,服务调用方,FeignClient的参数上都需要加上注解.
- 服务提供方product-service
@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo){return "接收到对象:" + productInfo;
}
- FeignClient
@RequestMapping("/product/p4")
String p4(@RequestBody ProductInfo productInfo);
- 服务消费方order-service
@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo){return api.p4(productInfo);
}
测试远程调用:http://127.0.0.1:8080/order/p4
4. 最佳实践
通过观察,我们也能看出来,Feign的客户端与服务提供者的controller代码非常相似.
Feign客户端:
@FeignClient(value = "product-service")
public interface ProductApi {@RequestMapping("/product/p1")String p1(@RequestParam("id") Integer id);
}
服务提供方Controller
@RestController
@RequestMapping("/product")
public class ProductController {@RequestMapping("/p1")public String p1(Integer id){return "接收到参数"+id;}
}
有没有一种方法可以简化这种写法呢?
4.1 Feign继承方式
Feign支持继承的方式,我们可以把一些常见的操作封装到接口里.
我可以定义好一个接口,服务提供方实现这个接口,服务消费方编写Feign接口的时候,直接继承这个接口.
接口可以放在一个公共的jar包中,供服务提供方和服务消费方使用.
- 新建一个模块
- 引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
</dependencies>
- 编写接口
复制ProductInfo类和ProductApi到product-api模块中.把ProductApi改名为ProductInterface
- 打jar包,并安装到本地Maven仓库
点击install.该模块就会被安装到本地的Maven仓库.
由于jar包中已经有了ProductInfo类,所以我们就可以把product-service和order-service的ProductInfo类注掉了. - 服务提供方
需要先在服务方中引入对应模块的依赖.
<dependency><groupId>org.example</groupId><artifactId>product-api</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope>
</dependency>
服务方product-service
直接实现接口ProductInterface
.
@RestController
@RequestMapping("/product")
public class ProductController implements ProductInterface {@Autowiredprivate ProductService productService;@RequestMapping("/select")public ProductInfo getProductInfo(Integer id){return productService.selectById(id);}@RequestMapping("/p1")public String p1(Integer id){return "接收到参数"+id;}@RequestMapping("/p2")public String p2(Integer id1,Integer id2){return "接收到参数1:" + id1 + ",接收到参数2:" + id2;}@RequestMapping("/p3")public String p3(ProductInfo productInfo){return "接收到对象:" + productInfo;}@RequestMapping("/p4")public String p4(@RequestBody ProductInfo productInfo){return "接收到对象:" + productInfo;}
}
- 服务消费方
同样,首先先添加依赖.
之后让FeignClient继承ProductInterface
@FeignClient(value = "product-service")
public interface ProductApi extends ProductInterface {}
注意在上述步骤中,把ProductInfo类引入包的路径全部改为之前打包的product-api模块下ProductInfo类的路径.
- 测试接口
http://127.0.0.1:8080/order/select?id=1
4.2 Feign抽取方式
官方推荐Feign的使用方式为继承的方式,但是企业开发中,更多是把Feign接口抽取为⼀个独立的模块(做法和继承相似,但理念不同).
操作方法:
将Feign的Client抽取为⼀个独立的模块,并把涉及到的实体类等都放在这个模块中,打成⼀个Jar.服务消费方只需要依赖该Jar包即可.这种方式在企业中比较常见,Jar包通常由服务提供方来实现.
前4步和前面继承的方式一样.只不过接口ProductApi在复制到新模块的时候不用修改名字
- 服务消费方使用product-api
首先引入依赖,之后把该模块中原有的ProductApi接口注掉.
<dependency><groupId>org.example</groupId><artifactId>product-api</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
之后指定扫描类
在启动类中添加需要加载的Feign客户端.
@SpringBootApplication
@EnableFeignClients(clients = ProductApi.class)
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class,args);}
}
- 测试
远程调用接口http://127.0.0.1:8080/order/select?id=1
相关文章:
[Spring] OpenFeign的使用
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
java文件按行写入数据后并创建行索引及查询
背景 当有很多数据需要存储,这些数据只是想要简单的按行存储和查询,不需要进行其他条件搜索,此时就可以考虑不需把这些数据存储在数据库,而是直接写入文件,然后从文件中查询 但是正常情况下,如果仅仅只是按…...
在视频汇聚平台EasyNVR平台中使用RTSP拉流的具体步骤
之前有用户反馈,在EasyNVR平台中添加Pull时使用海康设备的RTSP流地址无法播放。经过研发的优化及一系列严谨的验证流程,我们已确认优化后的EasyNVR平台,通过Pull方式添加海康设备的RTSP流已经能够正常播放。以下是具体的操作步骤:…...
OS2.【Linux】基本命令入门(1)
目录 1.操作系统是什么? 2.好操作系统的衡量标准 3.操作系统的核心工作 4.在计算机上所有行为都会被转换为硬件行为 5.文件 6.简单介绍一些基本命令 1.clear 2.pwd 3.ls 1.ls -l 2.隐藏文件的创建 3.ls -al 4.ls -ld 5.ls -F(注意是大写) 4.cd 1.cd .. "…...
WPF 复杂页面布局及漂亮 UI 界面设计全解析
在 WPF 开发领域,打造一个既具备复杂功能又拥有美观 UI 界面的应用程序是众多开发者追求的目标。复杂页面布局与漂亮的 UI 设计不仅能提升用户体验,还能展现应用的专业性和独特性。本文将深入探讨如何在 WPF 中实现复杂页面布局以及设计出令人眼前一亮的…...
002-SpringBoot整合AI(Alibaba)
SpringBoot整合AI 一、引入依赖二、配置application.yml三、获取 api-key四、编写 controller五、起服务调用 一、引入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><vers…...
c++模板进阶
前言 一、非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数…...
99.8 金融难点通俗解释:净资产收益率(ROE)
目录 0. 承前1. 简述2. 比喻:养母鸡赚钱2.1 第一步:投资母鸡2.2 第二步:母鸡下蛋2.3 第三步:计算赚钱2.4 第四步:计算ROE 3. 生活中的例子3.1 好的ROE3.2 一般的ROE3.3 差的ROE 4. 小朋友要注意4.1 ROE高不一定好4.2 R…...
原生HTML集合
一、表格 1、固定表格 <div class"tablebox"><div class"table-container"><table id"myTable" border"0" cellspacing"0" cellpadding"0"><thead><tr></tr></thead>…...
【计算机网络】- 应用层HTTP协议
目录 初识HTTP 什么是HTTP 版本 HTTPS 模型 HTTP抓包工具 为什么使用 抓包工具的下载 下载后的重要操作 Fiddler的使用 HTTP请求与响应的基本格式 HTTP请求基本格式编辑 HTTP响应基本格式 协议格式总结❗️❗️❗️编辑 HTTP 详解 认识 URL URL基本格式 …...
python学opencv|读取图像(四十)掩模:三通道图像的局部覆盖
【1】引言 前序学习了使用numpy创建单通道的灰色图像,并对灰色图像的局部进行了颜色更改,相关链接为: python学opencv|读取图像(九)用numpy创建黑白相间灰度图_numpy生成全黑图片-CSDN博客 之后又学习了使用numpy创…...
数据库:MongoDB命令行帮助解释
MongoDB命令: mongodmongosmongoperrormongoexportmongofilesmongoimportmongorestoreMongostat MongoDB包中的核心组件包括: mongod 是 MongoDB 的核心服务器进程,负责数据存储和管理。mongos 是分片集群的路由进程,负责将请求路由到正确…...
python 统计相同像素值个数
目录 python 统计相同像素值个数 最大值附近的值 python 统计相同像素值个数 import cv2 import numpy as np import time from collections import Counter# 读取图像 image cv2.imread(mask16.jpg)# 将图像转换为灰度图像 gray_image cv2.cvtColor(image, cv2.COLOR_BGR2…...
工作流引擎Camunda与LiteFlow核心组件对比
以下为 Camunda 7 和 LiteFlow 详细的介绍,包括它们的核心组件和用途。 1. Camunda 7 详细介绍 Camunda 7 是一个基于 BPMN 2.0 标准的企业级工作流和决策自动化平台。它被广泛应用于复杂业务流程的管理和执行,其核心目标是通过流程自动化来提升企业效…...
记一个Timestamp时区问题的坑
resultSet.getTimestamp(“kpi_collect_time”)查出来的Timestamp居然是带时区的, 如果该Timestamp不是UTC时区的,Timestamp.toInstant().atZone(ZoneId.of(“UTC”))会把Timestamp转成UTC时区 使用Timestamp.toLocalDateTime()可以直接把时区信息抹除 …...
R语言学习笔记之开发环境配置
一、概要 整个安装过程及遇到的问题记录 操作步骤备注(包含遇到的问题)1下载安装R语言2下载安装RStudio3离线安装pacman提示需要安装Rtools4安装Rtoolspacman、tidyfst均离线安装完成5加载tidyfst报错 提示需要安装依赖,试错逐步下载并安装…...
Hive部署
1. 最小化安装Hive 本次安装的版本是Hive的3.1.3版本 解压缩Hive压缩包 # 解压缩 tar -zxvf apache-hive-3.1.3-bin.tar.gz、 # 修改文件夹名称(看个人习惯,可以不执行) mv apache-hive-3.1.3-bin apache-hive-3.1.3在conf目录下,新增hive-env.sh&…...
Windows第一次上手鸿蒙周边
端云一体所需装备 很重要:C/D/E/F盘要有二三十G的可用空间! 硬件:华为鸿蒙实验箱(基础版)》飞机板核心板环境监测板 软件:Visual Studio Code写代码 终端编译 Hiburn烧录到开发板 MobaXterm (…...
【java数据结构】二叉搜索树
【java数据结构】二叉搜索树 一、二叉搜索树的概念二、二叉搜索树的操作2.1 插入2.2 查找2.3 删除(重点以及难点)2.3.1 删除节点的左边为null2.3.2 删除节点的右边为null2.3.3 删除的左右节点都不为空 三、二叉搜索树的性能分析3.1 最优情况3.2 最差情况…...
3D Vision--计算点到平面的距离
写在前面 本文内容 计算点到平面的距离 平台/环境 python open3d 转载请注明出处: https://blog.csdn.net/qq_41102371/article/details/121482246 目录 写在前面准备Open3D代码完 准备Open3D pip install open3d代码 import open3d as o3ddef compute_points2…...
相机内参的作用原理
由三角形角度关系,得到X_image / focal_length X_real / Z_distance 用双目测距得到Z_distance之后 然后联合X_image / focal_length可以计算得到真实世界的X_real...
计算机网络介质访问控制全攻略:从信道划分到协议详解!!!
一、信道划分介质访问控制 介质访问控制:多个节点共享同一个“总线型”广播信道时,可能发生“信号冲突” 应该怎么控制各节点对传输介质的访问,才能减少冲突,甚至避免冲突? 时分复用(TDM) 时分复用:将时间分为等长的“…...
代码随想录day1
704.二分查找: 1.左闭右闭 int search(vector<int>& nums, int target) {int right nums.size() - 1;int left 0;while(left < right){int middle left ((right - left) >> 1);if(nums.at(middle) target){return middle;}else if(nums[m…...
IJK播放器问题集
IJK播放器问题集 在使用ijkplayer进行播放时候,时常会遇到一些问题,故记录下: 1 ijkplayer出现小窗切换到大窗画面卡住问题 检查是否大小窗口切换时候,频繁设置了surface。某些底层api频繁设置会导致画面不动。 //holder判断是…...
macOS使用LLVM官方发布的tar.xz来安装Clang编译器
之前笔者写过一篇博文ubuntu使用LLVM官方发布的tar.xz来安装Clang编译器介绍了Ubuntu下使用官方发布的tar.xz包来安装Clang编译。官方发布的版本中也有MacOS版本的tar.xz,那MacOS应该也是可以安装的。 笔者2015款MBP笔记本,CPU是intel的,出厂…...
【设计模式-行为型】观察者模式
一、什么是观察者模式 说起观察者模式,不得不说一位观察者模式的高级应用者,朱元璋。不知道大家有没有看过胡军演的电视剧《朱元璋》。这部剧背景是元朝末年,天下大乱,朱元璋自幼父母双亡,沦为乞丐,后遁入空…...
HTML5 新表单属性详解
HTML5 为 <form> 和 <input> 标签引入了一系列新属性,极大地增强了表单的功能和用户体验。这些新属性不仅简化了开发者的工作,还为用户提供了更友好、更高效的交互方式。本文将详细介绍这些新属性,并结合代码示例帮助大家更好地理…...
Android程序中使用FFmpeg库
目录 前言 一、环境 二、创建APP 三. 添加FFmpeg库文件到app中 1. 复制ffmpeg头文件和so库到app中 2. 修改CMakeLists.txt文件内容. 3. 修改ffmpeglib.cpp 文件内容 4. 修改NativeLib.kt 文件添加方法和加载库 5. 调用 四. 增加解析视频文件信息功能 总结 前言 前面…...
到华为考场考HCIE的注意事项和考试流程
大家好,我是张同学,来自成都职业技术学院2021级计算机网络专业。最近成功通过了 Datacom HCIE 考试,在这里和大家分享一下我的经验。 考证契机 在母校的培养下,我接触到ICT这个行业,打好了基础,开始了成…...
基于STM32的智能书架管理系统设计
目录 引言系统设计 硬件设计软件设计 系统功能模块 图书分类与存储模块环境监测与保护模块数据显示与用户交互模块远程管理与书籍推荐模块 控制算法 图书分类与存储管理算法环境监测与保护算法数据记录与推荐算法 代码实现 图书分类与存储代码环境监测与保护代码数据显示与远程…...
STL--list(双向链表)
目录 一、list 对象创建 1、默认构造函数 2、初始化列表 3、迭代器 4、全0初始化 5、全值初始化 6、拷贝构造函数 二、list 赋值操作 1、赋值 2、assign(迭代器1,迭代器2) 3、assign(初始化列表) 4、assig…...
构建高效稳定的网络环境
概述 网络技术是当今IT行业的重要组成部分,构建高效稳定的网络环境对于企业、个人和互联网发展至关重要。本文将探讨网络技术中的关键要素,包括网络协议、网络架构、网络安全和网络优化,并提供实用的技巧和最佳实践,以帮助您构建…...
2025美赛倒计时,数学建模五类模型40+常用算法及算法手册汇总
数学建模美赛倒计时,对于第一次参加竞赛且没有相关基础知识的同学来讲,掌握数学建模常用经典的模型算法知识,并熟练使用相关软件进行建模是关键。本文将介绍一些常用的模型算法,以及软件操作教程。 数学建模常用模型包括…...
ElasticSearch DSL查询之排序和分页
一、排序功能 1. 默认排序 在 Elasticsearch 中,默认情况下,查询结果是根据 相关度 评分(score)进行排序的。我们之前已经了解过,相关度评分是通过 Elasticsearch 根据查询条件与文档内容的匹配程度自动计算得出的。…...
C语言--数据在内存中的存储
数据在内存中的存储 主要研究整型和浮点型在内存中的存储。 1. 整数在内存中的存储 在学习操作符的时候,就了解过了下面的内容: 整数的2进制表示方法有三种,即原码、反码和补码。 有符号的整数,三种表示方法均有符号位和数值…...
qml ScrollView详解
1、概述 QML中的ScrollView是一个容器组件,它允许用户滚动查看其内容,当内容超出视口大小时特别有用。ScrollView提供了垂直和水平滚动条(或触摸滚动),使用户能够访问被视口裁剪的内容部分。它常用于显示大量数据或复…...
通过frm和ibd文件恢复mysql数据
1.提取所有的文件名并查找出以frm结尾的 dir /t /b >1.txt 2.要准备的软件 1.mysql-utilities-1.6.5-winx64.msi 2.vcredist_x64.exe(c 2013) 3.利用frm生成sql文件 mysqlfrm --serverroot:123456localhost:3306 --port3308 D:\phpstudy_pro\Extensions\MySQL5.7.26\da…...
观察者模式 - 观察者模式的应用场景
引言 观察者模式(Observer Pattern)是设计模式中行为型模式的一种,它定义了对象之间的一对多依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。观察者模式广泛应用于事件处理系统…...
【Mac】Python相关知识经验
一、给Python3安装第三方库 mac下给Python3安装第三方库pillow,处理图片 【安装方式】: 终端中输入命令:python3 -m pip install pillow 按回车,等待pillow下载安装 NOTE: 其他模块同理,如pytesseract 二、Python版…...
使用 JMeter 的 Autostop Listener 插件:自动化性能测试的守护者
在性能测试中,监控测试执行的状态并及时做出响应是至关重要的。如果测试过程中出现性能瓶颈或系统崩溃,继续运行测试可能会导致资源浪费或测试结果不准确。JMeter 的 Autostop Listener 插件正是为了解决这一问题而设计的。它允许你设置自动化停止条件&a…...
C# lock使用的逻辑和情景
情景:扣库存,会出现超扣的情况,因为同一个单子会有不同的工作人员使用,要保证数据的一致性。那么就用锁。 优化锁对象管理 使用 Lazy 初始化锁对象: 使用 ConcurrentDictionary 的 GetOrAdd 方法结合 Lazy 确保锁对象只…...
React 中hooks之 React useCallback使用方法总结
1. useCallback 基础概念 useCallback 是 React 的一个 Hook,用于记忆函数定义,避免在每次渲染时创建新的函数实例。它在需要将回调函数传递给经过优化的子组件时特别有用。 当state变化的时候引起组件重新渲染执行会导致某个方法被反复创建增加内存负担…...
期刊论文左下角添加通讯作者和横线的方法
一、添加脚注 二、写脚注内容 三、修改脚注分隔符(添加横线) 大概插入十个此符号,长度可微调。...
Docker使用 使用Dockerfile来创建镜像
本篇文章主要介绍了Docker使用Dockerfile来创建镜像, 本文学习Dcokerfile的基本命令,并且创建一个支持ssh服务的镜像. 1.Dockerfile 1.1基本案例 基本案例 dockerfile可以说是docker的描述符,该文件定义了docker镜像的所能拥有哪些东西.基本格式如下: 第一行指定…...
手写SOCKET进行HTTP通信
网络基础 我们电脑主板上都内置了多种网卡,一般主要有以下几类: 虚拟网卡(loopback) 注意,它是虚拟的,并不是物理网卡,也被称为是本地环回地址(或接口),一般将127.0.0.1作为本地环回…...
深入理解 Java 的并发容器
目录 一、为何需要并发容器 二、Java 中的主要并发容器 1. ConcurrentHashMap 2. CopyOnWriteArrayList 3. ConcurrentLinkedQueue 4. BlockingQueue及其实现类 三、并发容器的应用场景 1. 缓存系统 2. 任务队列 3. 数据共享与传递 四、使用并发容器的注意事项 1. …...
四、CSS效果
一、box-shadow box-shadow:在元素的框架上添加阴影效果 /* x 偏移量 | y 偏移量 | 阴影颜色 */ box-shadow: 60px -16px teal; /* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影颜色 */ box-shadow: 10px 5px 5px black; /* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半…...
每日OJ_牛客_DP44兑换零钱_C++_Java
目录 牛客_DP44兑换零钱 题目解析 C代码 Java代码 牛客_DP44兑换零钱 兑换零钱_牛客题霸_牛客网 描述: 给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个a…...
Linux——入门基本指令汇总
目录 1. ls指令2. pwd3. whoami指令4. cd指令5. clear指令6. touch指令7. mkdir指令8. rm指令9. man指令10. cp指令11. mv指令12. cat指令13. tac指令14. more指令15. less指令16. head指令17. tail指令18. date指令19. cal指令20. find指令21. which指令22. alias指令23. grep…...
VOSK实现【离线中文语音】识别
Vosk是一款开源的离线语音识别工具包,具有以下功能: 多语言支持:能够对20多种语言和方言进行语音识别,如中文、英语、德语、法语、西班牙语等,可满足不同用户的语言需求。 模型轻量化:每种语言的模型大小仅…...