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

spring boot——自定义依赖实现自动配置

需求

要实现的功能是:实现一个可以支持minio+oss两种方式,上传下载文件的自定义依赖。其中还包括一些创建桶、删除桶、删除文件等功能,但是最主要的是实现自动配置。

如果对spring理解很深的话,自动配置这些东西很容易理解,但是对于技术小白来讲只能按葫芦画瓢。

首先,StorageManager是我的自定义依赖对外提供的要注入spring的对象,其中的方法是对外提供的方法,方法返回的是StorageService接口。

package cn.chinatelecom.dxsc.park.oss;import cn.chinatelecom.dxsc.park.oss.entity.FileDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;public class StorageManager {private static final Logger log = LoggerFactory.getLogger(StorageManager.class);private final StorageService storageService;public StorageManager(StorageService storageService) {this.storageService = storageService;}/*** 创建存储桶** @param bucketName 桶名称*/public void createBucket(String bucketName) {storageService.createBucket(bucketName);}/*** 删除桶* @param bucketName 桶名称* @return*/public Boolean removeBucket(String bucketName) {Boolean removeBucket = storageService.removeBucket(bucketName);return removeBucket;}/*** 删除文件* @param fileName* @return*/public Boolean remove(String fileName){return storageService.remove(fileName);}/*** 下载文件** @param filePath 文件路径* @return 文件流*/public InputStream getObject(String filePath) {return storageService.getObject(filePath);}/*** 上传文件* @param file* @return*/public FileDomain saveFile(MultipartFile file) {FileDomain result = new FileDomain();try {InputStream in = file.getInputStream();long size = file.getSize();String contentType = file.getContentType();String fileName = generateName(file.getOriginalFilename());String filePath = generateKey(fileName);String url = storageService.saveFile(in, size, contentType, filePath);result.setSize(size);result.setUrl(url);result.setKey(filePath);result.setType(contentType);} catch (IOException e) {log.error("保存文件失败", e);throw new RuntimeException(e);}return result;}private String generateName(String originalFilename) {return UUID.randomUUID().toString().replace("-", "")  + originalFilename.substring(originalFilename.lastIndexOf("."));}private String generateKey(String fileName) {// 2022-10/24/b4c9106e3f574a61841ce4624494f0cc.jpg  在删除和下载文件时需要传入路径才可以删除和下载return LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM/dd")) + "/" + fileName;}}

StorageService接口定义:

package cn.chinatelecom.dxsc.park.oss;import io.minio.errors.*;import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;public interface StorageService {/*** 创建存储桶* @param bucketName 桶名称*/void createBucket(String bucketName);/*** 存储文件* @param inputStream 文件流* @param fileSize 文件大小* @param contentType 文件类型* @param keyName 文件名及路径*/String saveFile(InputStream inputStream, long fileSize, String contentType, String keyName);/*** 下载文件* @param filePath 文件路径* @return*/InputStream getObject(String filePath);/*** 删除文件* @param fileName* @return*/Boolean remove(String fileName);/*** 删除桶* @param bucketName 桶名称* @return*/Boolean removeBucket(String bucketName);
}

FileDomain是上传文件时返回的对象,其中包括文件url,文件在服务器的存储路径,文件类型、大小等等可以自己定义,这里没有使用@Data注解而是手写get和set方法,没有引入Lombok依赖是因为在实现自定义依赖的时候,尽量能不引入依赖就不引入依赖。如果你在自定义依赖里面引入版本2.0的Lombok,但是当别人引用你的依赖的时候,同时也引用的1.0的Lombok,这样就会出现最让人头疼的版本冲突问题,为了避免这种问题出现,尽量不要在底层引用过多依赖。

package cn.chinatelecom.dxsc.park.oss.entity;public class FileDomain {/*** 路径名称*/private String key;/*** 文件url*/private String url;/*** 文件类型(contentType)*/private String type;/*** 文件大小*/private Long size;public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getType() {return type;}public void setType(String type) {this.type = type;}public Long getSize() {return size;}public void setSize(Long size) {this.size = size;}
}

接下来是自动配置的相关代码
DxscStorageProperties是需要配置的一些属性,比如accessKey以及accessSecret等等。
@ConfigurationProperties注解,在 SpringBoot 中,当想需要获取到配置文件数据时,除了可以用 Spring 自带的 @Value 注解外,SpringBoot 还提供了一种更加方便的方式:@ConfigurationProperties。只要在 Bean 上添加上了这个注解,指定好配置文件的前缀,那么对应的配置文件数据就会自动填充到 Bean 中。

package cn.chinatelecom.dxsc.park.oss.config;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "dxsc.storage")
public class DxscStorageProperties {/*** 激活哪种存储*/private String active;/*** oss地址*/private String endpoint;/*** 桶名称*/private String bucketName;private String accessKey;private String accessSecret;public String getActive() {return active;}public void setActive(String active) {this.active = active;}public String getEndpoint() {return endpoint;}public void setEndpoint(String endpoint) {this.endpoint = endpoint;}public String getBucketName() {return bucketName;}public void setBucketName(String bucketName) {this.bucketName = bucketName;}public String getAccessKey() {return accessKey;}public void setAccessKey(String accessKey) {this.accessKey = accessKey;}public String getAccessSecret() {return accessSecret;}public void setAccessSecret(String accessSecret) {this.accessSecret = accessSecret;}}

接下来的代码才是重中之重DxscStorageAutoConfiguration,此类将DxscStorageProperties注入到spring中,Spring Boot 会扫描到类路径下的META-INF/spring.factories配置文件,把DxscStorageAutoConfiguration对应的的Bean值添加到容器中。

package cn.chinatelecom.dxsc.park.oss.autoconfigure;import cn.chinatelecom.dxsc.park.oss.StorageManager;
import cn.chinatelecom.dxsc.park.oss.StorageService;
import cn.chinatelecom.dxsc.park.oss.config.DxscStorageProperties;
import cn.chinatelecom.dxsc.park.oss.impl.MinioStorageServiceImpl;
import cn.chinatelecom.dxsc.park.oss.impl.OssStorageServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@EnableConfigurationProperties(DxscStorageProperties.class)
@Configuration
public class DxscStorageAutoConfiguration {@Autowiredprivate DxscStorageProperties dxscStorageProperties;@Beanpublic StorageManager storageManager(StorageService storageService) {return new StorageManager(storageService);}@Bean@ConditionalOnProperty(prefix = "dxsc.storage", value = "active", havingValue = "minio")public StorageService minioService() {return new MinioStorageServiceImpl(dxscStorageProperties);}
//prefix为前缀,value为选择哪个属性,havingValue就是启用哪种方式,当active属性为minio时就调用上面的,oss就调用下面的,
//大概就是这个意思@Bean@ConditionalOnProperty(prefix = "dxsc.storage", value = "active", havingValue = "oss")public StorageService OssService() {return new OssStorageServiceImpl(dxscStorageProperties);}}

spring.factories文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.chinatelecom.dxsc.park.oss.autoconfigure.DxscStorageAutoConfiguration

目录结构
其中MinioStorageServiceImpl和OssStorageServiceImpl就是实现的文件上传下载的接口,再此展示minion的接口:
oss接口可以查看官方文档,其中写得很清楚。

package cn.chinatelecom.dxsc.park.oss.impl;import cn.chinatelecom.dxsc.park.oss.StorageService;
import cn.chinatelecom.dxsc.park.oss.config.DxscStorageProperties;
import io.minio.*;
import io.minio.http.Method;import java.io.InputStream;public class MinioStorageServiceImpl implements StorageService {private final DxscStorageProperties dxscStorageProperties;private final MinioClient minioClient;public MinioStorageServiceImpl(DxscStorageProperties dxscStorageProperties) {this.dxscStorageProperties =dxscStorageProperties;this.minioClient = MinioClient.builder().endpoint(dxscStorageProperties.getEndpoint()).credentials(dxscStorageProperties.getAccessKey(), dxscStorageProperties.getAccessSecret()).build();}@Overridepublic void createBucket(String bucketName){boolean isExist = false;// 检查存储桶是否已经存在try{isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());if (!isExist) {//创建桶minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config("{\"Version\":\"2023-2-20\",\"Statement\":[]}").build());}}catch (Exception e){throw new RuntimeException(e);}}@Overridepublic String saveFile(InputStream inputStream, long fileSize, String contentType, String keyName) {try {PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(dxscStorageProperties.getBucketName()).object(keyName).stream(inputStream, fileSize, -1).contentType(contentType).build();//文件名称相同会覆盖minioClient.putObject(objectArgs);// 查看文件地址GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(dxscStorageProperties.getBucketName()).object(keyName).method(Method.GET).build();try {return minioClient.getPresignedObjectUrl(build);} catch (Exception e) {throw new RuntimeException(e);}} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic InputStream getObject(String filePath) {try{GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(dxscStorageProperties.getBucketName()).object(filePath).build();return minioClient.getObject(objectArgs);}catch (Exception e){System.out.println("下载失败");throw new RuntimeException(e);}}@Overridepublic Boolean remove(String fileName) {try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(dxscStorageProperties.getBucketName()).object(fileName).build());} catch (Exception e) {return false;}return true;}@Overridepublic Boolean removeBucket(String bucketName) {try {//在删除桶时,需要注意一下不能删除自身,当你的配置文件里的bucketName的test时还要删除test,是不能删除成功的//bucketName为test1时,删除test,是可以的minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {return false;}return true;}
}

至此,自定义依赖完成,接下来是引用,引用方法为先将自定义依赖上传至本地maven库,然后才可以导入依赖,

		<dependency><artifactId>dxsc-park-frame-oss</artifactId><groupId>cn.chinatelecom</groupId><version>1.0.0-SNAPSHOT</version></dependency>

然后,配置minio或者oss的accessKey和accessSecret等属性:
(active为minio就是通过minion方式实现文件上传下载)

dxsc:storage:active: minioendpoint: http://***.168.30.27:9000bucketName: dxsc-parkaccessKey: minioadminaccessSecret: minioadmin
#  storage:
#    active: oss
#    endpoint: https://oss-cn-beijing.aliyuncs.com
#    bucketName: dxsc-park
#    accessKey: ***
#    accessSecret: ***
server:port: 1101

最后注入StorageManager,在一开始的时候就说过StorageManager是对外提供的:

package cn.chinatelecom.dxsc.park.test.controller;import cn.chinatelecom.dxsc.park.oss.StorageManager;
import cn.chinatelecom.dxsc.park.oss.entity.FileDomain;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;@RestController
@RequestMapping("/minio")
public class TestController {@Autowiredprivate StorageManager storageManager;@PostMapping("/createBucket")public void createBucket(@RequestParam("bucketName") String bucketName){storageManager.createBucket(bucketName);}@PostMapping("/removeBucket")public void removeBucket(@RequestParam("bucketName") String bucketName){storageManager.removeBucket(bucketName);}@PostMapping("/upload")public String upload(@RequestParam("file") MultipartFile file){FileDomain fileDomain = storageManager.saveFile(file);System.out.println(fileDomain.getUrl());return fileDomain.getKey();}@PostMapping("/remove")public Boolean remove(@RequestParam("fileName") String fileName){Boolean remove = storageManager.remove(fileName);return remove;}@PostMapping("/getObject")public void getObject(@RequestParam("filePath") String filePath, HttpServletResponse response) throws IOException {InputStream object = storageManager.getObject(filePath);response.setContentType("application/octet-stream");response.addHeader("Content-Disposition", "attachment;filename=" + "fileName");IOUtils.copy(object, response.getOutputStream());IOUtils.closeQuietly(object);}}

以上就是我在实现自动配置的全部内容

一个集坚强与自信于一身的菇凉。

相关文章:

spring boot——自定义依赖实现自动配置

需求 要实现的功能是&#xff1a;实现一个可以支持miniooss两种方式&#xff0c;上传下载文件的自定义依赖。其中还包括一些创建桶、删除桶、删除文件等功能&#xff0c;但是最主要的是实现自动配置。 如果对spring理解很深的话&#xff0c;自动配置这些东西很容易理解&#…...

QMap 判断是否value是否已经存在,结合Sleep函数测试

网上查了资料&#xff0c;基本说的都是通过.value判断是否已经之前的key值&#xff0c;但是尝试.了一下发现有.key的函数&#xff0c;对比着来就感觉这个函数是用来判断是否已经存在value值&#xff0c;于是开始百度也几乎没有找到相关资料&#xff0c;只好自己看官方文档&…...

vue后台管理系统项目-table选择多行数据分页列表、一键全选重置功能

table选择多行数据 功能介绍&#xff1a; 1.列表分页功能&#xff1b; 2.一键全选&#xff0c;选中列表所有数据&#xff1b; 3.全选&#xff0c;选中当前页数据&#xff1b; 4.重置&#xff0c;清除选中状态&#xff1b; 5.列表搜索查询&#xff1b; 效果&#xff1a; 1.列表分…...

论文解读 | [CVPR2019] 基于自适应文本区域表示的任意形状场景文本检测

目录 1 研究背景及意义 2 总体设计 3 方法论 3.1 自适应文本区域表示 3.2 文本建议 3.3 建议改进 4 损失函数 5 实验及结果 1 研究背景及意义 现有的场景文本检测方法使用固定点数的多边形来 表示文本区域。例如&#xff0c;水平文本使用2个点(左上/右下)表示文本区域&…...

2月编程语言排行榜谁还没有看?

近日&#xff0c;TIOBE公布了2023年2月编程语言排行榜&#xff0c;本月各个语言表现如何&#xff1f;谁又摘得桂冠&#xff1f;一起来看看吧&#xff01; TIOBE 2月Top15编程语言&#xff1a; 详细榜单查看TIOBE官网 https://www.tiobe.com/tiobe-index/ 关注IT行业的小伙伴们…...

nginx.conf配置方法详细介绍

从前面的内容学习中&#xff0c;我们知道Nginx的核心配置文件默认是放在/usr/local/nginx/conf/nginx.conf&#xff0c;这一节&#xff0c;我们就来学习下nginx.conf的内容和基本配置方法。读取Nginx自带的Nginx配置文件&#xff0c;我们将其中的注释部分【学习一个技术点就是在…...

【微信小程序】一文带你吃透开发中的常用组件

写在前面 小程序中的组件也是由宿主环境提供的&#xff0c;开发者可以基于组件快速搭建出漂亮的页面结构。 官方把小程序的组件分为了9大类&#xff0c;分别是: 1.视图容器 2.基础内容 3.表单组件 4.导航组件 5.媒体组件 6.地图组件 7.画布组件 …...

Nginx 部署 Vue 项目以及 Vue 项目刷新出现 404 的问题(完整步骤)(亲测有效)

Nginx 部署 Vue 项目以及 Vue 项目刷新出现 404 的问题&#xff08;完整步骤&#xff09;&#xff08;亲测有效&#xff09; 1.流程步骤&#xff08;本教程下载的是1.20.2版本&#xff0c;放在D盘&#xff09; 1-1. 首先去官方下载 nginx &#xff0c;然后在当前目录下创建ht…...

leaflet 加载geojson数据,随机显示不同颜色的circleMarker

第086个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet项目中加载geojson数据,随机显示不同颜色的circleMarker. 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共89行)相关API专栏目标示例效果 配置方式…...

UL grant的分配(LCP)

欢迎关注同名微信公众号“modem协议笔记”。 UE有UL data时&#xff0c;会发送BSR的告知网络侧自己详细的请求&#xff0c;期望网络能够如期下发UL grant&#xff0c;正常情况下网络侧会给UE足够的UL grant去发送UL data&#xff0c;整个过程都会比较顺利。UE收到UL grant后&a…...

真我air笔记本电脑怎么重装Win10系统?

真我air笔记本电脑怎么重装Win10系统&#xff1f;最近真我air笔记本电脑挺多用户购买的&#xff0c;因为这款电脑性价比比较高&#xff0c;适合学生和一些办公人员来使用。但是系统预制了Win11系统&#xff0c;有用户想要将系统重装到Win10来使用。那么如何去进行系统的重装呢&…...

【闲聊杂谈】深入剖析SpringCloud Alibaba之Nacos源码

Nacos核心功能点 服务注册 Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务&#xff0c;提供自身的元数据&#xff0c;比如ip地址、端口等信息。Nacos Server接收到注册请求后&#xff0c;就会把这些元数据信息存储在一个双层的内存Map中&#xff1b; 服…...

MySQL删除或清空表内数据的方法

MySQL删除或清空表内数据的方法 一、使用MySQL清空表数据命令&#xff1a;truncate SQL语法为&#xff1a; truncate table 表名注意&#xff1a; truncate该命令会直接将数据表内数据清空&#xff1b;truncate该命令删除数据后会重置Identity&#xff08;标识列、自增字段…...

Android 权限(二): 动态权限讲解

1. 前言 继上一篇文章说到Android权限汇总, 请移步笔者的文章Android 权限(一)&#xff1a;权限大全_broadview_java的博客-CSDN博客_android 仅使用中允许权限 先要理清楚权限分类和定义,本篇文章继续说一下动态权限的申请和框架层的实现流程, 以及如何实现赋予系统应用默认的…...

【C++】2.类和对象(上)

1.面向过程和面向对象 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完成。 2.类的引入…...

扬帆优配|3300点半日游!上证指数冲高回落;再迎重磅利好!

今天早盘&#xff0c;A股冲高回落&#xff0c;上证指数3300点得而复失&#xff0c;深证成指也于12000点无功而返。 盘面上&#xff0c;煤炭、钢铁、房地产、才智政务等板块涨幅居前&#xff0c;酿酒、酒店餐饮、日用化工、IT设备等板块跌幅居前。北上资金净流入7.77亿元。 房地…...

如何编写性能测试计划?一篇文章教你设计符合项目的性能测试计划

上篇文章&#xff0c;我们讲过性能测试计划&#xff0c;接下来我们就来讲讲如何设计符合项目的性能测试计划。到上篇为止&#xff0c;我们了解了性能测试计划中包含的内容&#xff0c;但是&#xff0c;这个颗粒度&#xff0c;我觉得作为一名测试经验不够丰富的性能工程师来说&a…...

第3章 Windows 下安装 Memcached教程

官网上并未提供 Memcached 的 Windows 平台install 包&#xff0c;咱们可以使用以下链接来download &#xff0c;需要根据自己的去下载&#xff1a; 点击下载 在 1.4.5 版本以前 memcached 可以作为一个服务install &#xff0c;而在 1.4.5 及之后的版本删除了该功能。因此咱…...

RXjava中的操作符

要使用Rxjava首先要导入两个包&#xff0c;其中rxandroid是rxjava在android中的扩展 implementation io.reactivex:rxandroid:1.2.1implementation io.reactivex:rxjava:1.2.0Rxjava中的操作符 创建型操作符 interval 创建一个按固定时间间隔发射整数序列的Observable&#xf…...

前端页面jquery规范写法

使用最新版本的 jQuery 最新版本的 jQuery 会改进性能和增加新功能,若不是为了兼容旧浏览器,建议使用最新版本的 jQuery。以下是三条常见的 jQuery 语句,版本越新,性能越好: $(.elem) $(.elem, context) context.find(.elem) 结果 1.6.2 版执行次数远超两个老版本。 jQ…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...