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

ElasticSeach--springboot中使用

目录

一.引入依赖

 二.配置链接信息

 三.索引库测试

1.创建索引库

2.查询索引库

3.删除索引库

四.文档测试

1.添加文档

2.修改文档

3.删除文档

4.查询具体文档

5.批量添加文档

五.查询测试

 1.查询所有

2.根据属性term匹配查询

3.分页查询

4.排序

5.过滤属性

6.bool查询

7.范围查询

8.模糊查询

9.高亮查询

 10.聚合查询

 10.1最大年龄

10.2分组查询


一.引入依赖

    <dependencies><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.8.0</version></dependency><!--es的客户端--><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.8.0</version></dependency></dependencies>

 二.配置链接信息

#自定义elasticsearch连接配置
elasticsearch:host: 192.168.81.128port: 9200
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticSearchConfig {private String host;private int port;@Beanpublic RestHighLevelClient client(){return new RestHighLevelClient(RestClient.builder(new HttpHost(host, port, "http")));}
}

 三.索引库测试

1.创建索引库

    /***  添加索引库*/@Testpublic void AddIndex() throws IOException {//创建索引库CreateIndexRequest request = new CreateIndexRequest("user");//获取响应CreateIndexResponse response =restHighLevelClient.indices().create(request,RequestOptions.DEFAULT);boolean acknowledged = response.isAcknowledged();System.out.println("响应状态:"+acknowledged);}

2.查询索引库

//查询索引库@Testpublic void testGetIndex() throws IOException {GetIndexRequest request = new GetIndexRequest("user");GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);//System.out.println(response.getAliases());//获取默认配置System.out.println(response.getDefaultSettings());//获取索引名称System.out.println(Arrays.toString(response.getIndices()));//获取映射System.out.println(response.getMappings());}

3.删除索引库

/*** 删除索引库*/@Testpublic void testDeleteIndex() throws IOException {//删除索引请求DeleteIndexRequest request = new DeleteIndexRequest("user");AcknowledgedResponse response = restHighLevelClient.indices().delete(request,RequestOptions.DEFAULT);System.out.println(response.isAcknowledged());restHighLevelClient.close();}

四.文档测试

1.添加文档

/***  添加文档*/@Testpublic void testAddDoucument() throws IOException {/*** 第一次不存在时是创建,*  第二次存在时就是修改,将修改version版本号*/IndexRequest indexRequest = new IndexRequest("user");indexRequest.id("122");User user = new User();user.setId(122);user.setName("张三");user.setAge(12);user.setScore(123);//添加数据indexRequest.source(JSON.toJSONString(user), XContentType.JSON);IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);//获取索引库idSystem.out.println(response.getIndex());//获取文档idSystem.out.println(response.getId());//获取版本System.out.println(response.getVersion());//获取结果System.out.println(response.getResult());}

2.修改文档

/*** 修改文档*/@Testpublic void testUpadteDoc() throws IOException {UpdateRequest updateRequest = new UpdateRequest("user","122");User user = new User();user.setId(122);user.setName("张三");user.setAge(13);user.setScore(123);updateRequest.doc(JSON.toJSONString(user), XContentType.JSON);UpdateResponse res = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);System.out.println(res.getId());System.out.println(res.getIndex());System.out.println(res.getResult());System.out.println(res.getVersion());restHighLevelClient.close();}

3.删除文档

/***  删除文档*/@Testpublic void testDelteDoc() throws IOException {DeleteRequest deleteRequest = new DeleteRequest("user","122");DeleteResponse res = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);System.out.println(res.getId());System.out.println(res.getIndex());System.out.println(res.getResult());}

4.查询具体文档

    /*** 查询文档*/@Testpublic void testGetDoc() throws IOException {GetRequest getRequest =new GetRequest("user","122");GetResponse res = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);System.out.println(res.getIndex());System.out.println(res.getId());System.out.println(res.getSource());System.out.println(res.getFields());System.out.println(res.getSourceAsString()); //返回json串
//        user
//        122
//        {score=123, name=张三, id=122, age=12}
//        {}
//        {"age":12,"id":122,"name":"张三","score":123}}

5.批量添加文档

 /*** 批量添加文档*/@Testpublic void testBulkAdd() throws IOException {User user1 = new User(1,"王五",12,213);User user2 = new User(2,"李四",321,213);User user3 = new User(3,"赵六",24,213);User user4 = new User(4,"zhangsan",41,213);User user5 = new User(5,"蔡徐坤",21,213);BulkRequest request = new BulkRequest("user");IndexRequest request1 = new IndexRequest("user").id(user1.getId().toString());request1.source(JSON.toJSONString(user1),XContentType.JSON);IndexRequest request2 = new IndexRequest("user").id(user2.getId().toString());request2.source(JSON.toJSONString(user2),XContentType.JSON);IndexRequest request3 = new IndexRequest("user").id(user3.getId().toString());request3.source(JSON.toJSONString(user3),XContentType.JSON);IndexRequest request4 = new IndexRequest("user").id(user4.getId().toString());;request4.source(JSON.toJSONString(user4),XContentType.JSON);IndexRequest request5 = new IndexRequest("user").id(user5.getId().toString());request5.source(JSON.toJSONString(user5),XContentType.JSON);request.add(request1);request.add(request2);request.add(request3);request.add(request4);request.add(request5);BulkResponse res = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);System.out.println(res.getIngestTook());System.out.println(res.getTook());System.out.println(res.getIngestTookInMillis());}

五.查询测试

 1.查询所有

 /*** 查询所有*/@Testpublic void testqueryAll() throws IOException {SearchRequest searchRequest = new SearchRequest();//指定索引库searchRequest.indices("user");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//查询所有sourceBuilder.query(QueryBuilders.matchAllQuery());searchRequest.source(sourceBuilder);SearchResponse res = client.search(searchRequest, RequestOptions.DEFAULT);//查询匹配SearchHits hits = res.getHits();System.out.println("took:" + res.getTook());System.out.println("是否超时:" + res.isTimedOut());System.out.println("TotalHits:" + hits.getTotalHits());System.out.println("MaxScore:" + hits.getMaxScore());for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}

2.根据属性term匹配查询

/*** 根据term条件查询* @throws IOException*/@Testpublic void testTermQuery() throws IOException {SearchRequest request = new SearchRequest();request.indices("user");//构建查询的请求体SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//查询所有对象sourceBuilder.query(QueryBuilders.termQuery("name","zhangsan"));request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);//查询匹配SearchHits hits = response.getHits();System.out.println("took:" + response.getTook());System.out.println("是否超时:" + response.isTimedOut());System.out.println("TotalHits:" + hits.getTotalHits());System.out.println("MaxScore:" + hits.getMaxScore());for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}

3.分页查询

 /*** 分页查询*/@Testpublic void testPageQuery() throws IOException {SearchRequest request = new SearchRequest();request.indices("user");//构建查询的请求体SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//查询所有对象sourceBuilder.query(QueryBuilders.matchAllQuery());//第一页sourceBuilder.from(0);//三条记录sourceBuilder.size(11);request.source(sourceBuilder);//添加分页信息SearchResponse response = client.search(request, RequestOptions.DEFAULT);//查询匹配SearchHits hits = response.getHits();System.out.println("took:" + response.getTook());System.out.println("是否超时:" + response.isTimedOut());System.out.println("TotalHits:" + hits.getTotalHits());System.out.println("MaxScore:" + hits.getMaxScore());for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}

4.排序

 //年龄排序 倒序,从大到小sourceBuilder.sort("age", SortOrder.DESC);

5.过滤属性

//查询过滤字段String[] excludes = {"age"};//过滤掉age属性String[] includes = {};sourceBuilder.fetchSource(includes,excludes);

6.bool查询

 //创建搜索对象SearchRequest request = new SearchRequest();request.indices("user");//构建查询的请求体SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();//必须包含boolQuery.must(QueryBuilders.matchQuery("age",18));//一定不包含boolQuery.mustNot(QueryBuilders.matchQuery("name","lisi"));//可能包含boolQuery.should(QueryBuilders.matchQuery("name","zhangsan"));//查询所有对象sourceBuilder.query(boolQuery);request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);

7.范围查询

 //创建搜索对象SearchRequest request = new SearchRequest();request.indices("user");//构建查询的请求体SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//范围查询RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");//大于等于rangeQuery.gte("19");//小于等于rangeQuery.lte("40");//查询所有对象sourceBuilder.query(rangeQuery);request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);

8.模糊查询

//创建搜索对象SearchRequest request = new SearchRequest();request.indices("user");//构建查询的请求体SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//模糊查询FuzzyQueryBuilder fuzzyQuery = QueryBuilders.fuzzyQuery("name", "zhangsan");fuzzyQuery.fuzziness(Fuzziness.ONE);sourceBuilder.query(fuzzyQuery);request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);

9.高亮查询

//高亮查询SearchRequest request = new SearchRequest("user");//创建查询请求体构建器SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//构建查询方式,高亮查询TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "zhangsan");//设置查询方式sourceBuilder.query(termQueryBuilder);//构建高亮字段HighlightBuilder highlightBuilder = new HighlightBuilder();//设置标签前缀highlightBuilder.preTags("<font color='red'");//设置标签后缀highlightBuilder.postTags("</font>");//设置高亮字段highlightBuilder.field("name");//设置高亮构建对象sourceBuilder.highlighter(highlightBuilder);//设置请求体request.source(sourceBuilder);//客户端发送请求,获取响应对象SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 打印响应结果SearchHits hits = response.getHits();System.out.println("took::"+response.getTook());System.out.println("time_out::"+response.isTimedOut());System.out.println("total::"+hits.getTotalHits());System.out.println("max_s core::"+hits.getMaxScore());System.out.println("hits::::>>");for (SearchHit hit : hits) {String sourceAsString = hit.getSourceAsString();System.out.println(sourceAsString);//打印高亮结果Map<String, HighlightField> highlightFields = hit.getHighlightFields();System.out.println(highlightFields);System.out.println("<<::::");}

 10.聚合查询

 10.1最大年龄

 SearchRequest request = new SearchRequest().indices("user");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.aggregation(AggregationBuilders.max("maxAge").field("age"));//设置请求体request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);//打印响应结果SearchHits hits = response.getHits();System.out.println("hits = " + hits);System.out.println(response);

10.2分组查询

//创建搜索对象SearchRequest request = new SearchRequest().indices("user");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.aggregation(AggregationBuilders.terms("age_groupby").field("age"));//设置请求体request.source(searchSourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);System.out.println(response.getHits());System.out.println(response);

相关文章:

ElasticSeach--springboot中使用

目录 一.引入依赖 二.配置链接信息 三.索引库测试 1.创建索引库 2.查询索引库 3.删除索引库 四.文档测试 1.添加文档 2.修改文档 3.删除文档 4.查询具体文档 5.批量添加文档 五.查询测试 1.查询所有 2.根据属性term匹配查询 3.分页查询 4.排序 5.过滤属性 6.boo…...

(1)(1.9) MSP (version 4.2)

文章目录 前言 1 协议概述 2 配置 3 参数说明 前言 ArduPilot 支持 MSP 协议&#xff0c;可通过任何串行端口进行遥测、OSD 和传感器。这样&#xff0c;ArduPilot 就能将遥测数据发送到 MSP 兼容设备&#xff08;如大疆护目镜&#xff09;&#xff0c;用于屏幕显示&#x…...

mysql 表锁 行锁

目录 表锁&#xff08;Table Lock&#xff09; 行锁&#xff08;Row Lock&#xff09; 进一步通过举例解释 update操作走的是什么锁 表锁示例&#xff1a; 行锁示例&#xff1a; MySQL 中常见的锁类型包括&#xff1a; 表锁&#xff08;Table Lock&#xff09; 是针对整个…...

Google 提示:切忌滥用 DORA 指标

谷歌的 DevOps 研究与评估团队从事指标交易&#xff0c;即 DevOps 指标。但其最新的相关报告也警告不要过度使用这些指标。 DevOps 研究与评估小组&#xff08;DORA&#xff09;建议 IT 专业人员根据四个关键指标来评估团队绩效&#xff1a;部署频率&#xff0c;变更准备时间&a…...

2023年全球架构师峰会(ArchSummit北京站2023)-核心PPT资料下载

一、峰会简介 ArchSummit聚焦业界强大的技术成果&#xff0c;秉承“实践第一、案例为主”的原则&#xff0c;展示先进技术在行业中的典型实践&#xff0c;以及技术在企业转型、发展中的推动作用。旨在帮助技术管理者、CTO、架构师做好技术选型、技术团队组建与管理&#xff0c…...

安全、高效的MySQL DDL解决方案

MySQL作为目前应用最广泛的开源关系型数据库&#xff0c;是许多网站、应用和商业产品的主要数据存储。在生产环境&#xff0c;线上数据库常常面临着持续的、不断变化的表结构修改&#xff08;DDL&#xff09;&#xff0c;如增加、更改、删除字段和索引等等。其中一些DDL操作在M…...

100GPTS计划-AI学术AcademicRefiner

地址 https://chat.openai.com/g/g-LcMl7q6rk-academic-refiner https://poe.com/AcademicRefiner 测试 减少相似性 增加独特性 修改http://t.csdnimg.cn/jyHwo这篇文章微调 专注于人工智能、科技、金融和医学领域的学术论文改写&#xff0c;秉承严格的专业和学术标准。 …...

k8s 中部署Jenkins

创建namespace apiVersion: v1 kind: Namespace metadata:name: jenkins创建pv以及pvc kind: PersistentVolume apiVersion: v1 metadata:name: jenkins-pv-volumenamespace: jenkinslabels:type: localapp: jenkins spec:#storageClassName: manualcapacity:storage: 5Giacc…...

Spring Cloud和Zookeeper的集成,构建高可扩展的分布式系统

引言 构建高可扩展的分布式系统是现代应用程序开发中的重要挑战之一。在分布式系统中&#xff0c;负载均衡和分布式锁是两个关键问题。本文将介绍如何使用Spring Cloud和Zookeeper集成来实现高可扩展的分布式系统&#xff0c;并分析其负载均衡原理和分布式锁的应用。 1. 分布…...

【唐山海德教育】安全员c证怎么考

1、注册地在本市的施工单位在职“三类人员”可申请参加安全生产考核&#xff1b; 2、职业道德良好&#xff0c;身体健康&#xff0c;年龄不超过60周岁&#xff08;法定代表人除外&#xff09;&#xff1b; 3、筑施工企业专职安全生产管理人员需有中专&#xff08;含高中、中技…...

MySQL是如何保证数据不丢失的?

文章目录 前言Buffer Pool 和 DML 的关系DML操作流程加载数据页更新记录 数据持久化方案合适的时机刷盘双写机制日志先行机制日志刷盘机制Redo Log 恢复数据 总结 前言 上篇文章《InnoDB在SQL查询中的关键功能和优化策略》对InnoDB的查询操作和优化事项进行了说明。但是&#…...

CUMT--Java复习--泛型与集合

目录 一、泛型 1、概述 2、通配符 3、有界类型 二、集合 1、概述 2、迭代器接口 三、集合类 1、Collection接口 2、List接口 3、Set接口 4、Queue接口 5、Map接口 四、集合转换 五、集合工具类 一、泛型 1、概述 从JDK5.0开始&#xff0c;Java引入泛型类型&…...

Android 权限申请

在Android中&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用在运行时需要动态申请权限。以下是一些步骤来动态申请权限&#xff1a; 在应用的清单文件&#xff08;AndroidManifest.xml&#xff09;中声明需要的权限。例如&#xff0c;如果应…...

R语言【base】——invisible将控制台的输出模式调整为隐藏,只允许赋值后输出,返回对象的(临时)不可见副本

Package base version 4.3.2 invisible(x NULL) 参数【x】&#xff1a;一个任意的 R 对象&#xff0c;默认为 NULL。 如果希望函数返回的值可以赋值&#xff0c;但在未赋值时不打印&#xff0c;则可以使用该函数。 f <- function(x){if (x){return (x)} else {return (in…...

LA@线性代数学习总结@主要对象和问题@思想方法

文章目录 线性代数研究对象主要问题联系核心概念核心定理 核心操作和运算基础高级小结 性质和推导方法问题转换为线性方程组求解问题验证和推导性质定理 线性代数研究对象 线性代数的研究对象主要是行列式和矩阵(向量)矩阵这种对象可以做的操作和运算很多,特别是方阵,它们的计…...

VMware克隆虚拟机

要求&#xff1a;利用模板虚拟机hadoop100&#xff0c;克隆出hadoop101虚拟机。 1、鼠标右键点击已存在的模板虚拟机hadoop100 --> 管理 --> 克隆 2、选择克隆自虚拟机中的当前状态 3、创建完整克隆 4、修改虚拟机名称、位置 5、等待克隆完成后&#xff0c;则成功克隆出…...

C语言中常见的关键字

一、数据类型关键字&#xff08;20个&#xff09; 基本数据类型&#xff08;5个&#xff09; void&#xff1a;声明函数无返回值或无参数&#xff0c;声明无类型指针&#xff0c;显式丢弃运算结果 char&#xff1a;字符型类型数据&#xff0c;属于整型数据的一种 int&#xff…...

新型智慧视频监控系统:基于TSINGSEE青犀边缘计算AI视频识别技术的应用

边缘计算AI智能识别技术在视频监控领域的应用有很多。这项技术结合了边缘计算和人工智能技术&#xff0c;通过在摄像头或网关设备上运行AI算法&#xff0c;可以在现场实时处理和分析视频数据&#xff0c;从而实现智能识别和分析。目前来说&#xff0c;边缘计算AI视频智能技术可…...

智能优化算法应用:基于梯度算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于梯度算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于梯度算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.梯度算法4.实验参数设定5.算法结果6.参考文献7.MA…...

如何使用Docker搭建青龙面板并结合内网穿透工具发布至公网可访问

文章目录 一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用。本教程使用Docker部署青龙&#xff0c;如何安装Docker详见&#xff1a; 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 正文…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...