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

ElasticSearch整合SpringBoot

ElasticSearch


整合SpringBoot

ES官方提供了各种不同语言的客户端。用来操作ES。这些客户端的本质就是组装DSL语句,通过HTTP请求发送给ES。

设计索引库

跟据数据库的表结构进行ES索引库的创建时。如果字段需要进行倒排索引的时候请为它指定分词器。如果该字段不是检索时所需要使用的字段时请将index设置为false。在同时检索多个字段的时候,往往会降低检索的效率,但是可以使用copy_to这个参数来指定相关字段将其放入到同一个字段里面,这样既保证了检索的效率问题又简化了多字段查询的语法,使语法更加简洁。我们称之为字段拷贝,但是在使用查询语句时我们是看不见这个给字段信息的,检索是可以进行使用的

初始化工程

  • 引入es的RestHighLevelClient依赖

<!-- 引入 RestHighLevelClient -->
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>${elasticsearch.version}</version>
</dependency>
  • 因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本

<!-- 覆盖 Spring Boot 默认的 ES 版本 -->
<properties><elasticsearch.version>7.17.3</elasticsearch.version> <!-- 改为你需要的版本 -->
</properties>
  • 初始化RestHighLevelClient

@Configuration
public class ElasticsearchConfig {
​@Beanpublic RestHighLevelClient restHighLevelClient() {// 配置 ES 地址(支持多个节点)return new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")  // 修改为你的 ES 地址// new HttpHost("another-host", 9200, "http") // 可添加多个节点));}
}

索引操纵

基本步骤:

  • 初始化RestHighLevelClient

  • 创建XxxIndexRequest。Xxx是CREATE、Get、Delete

  • 准备DSL语句

  • 发送请求。调用RestHighLevelClient.indices().xxx()方法。xxx是create、exist、delete

创建索引库

主要分成三个具体步骤

  1. 创建索引库的操作请求对象

  2. 给请求对象中放入指定的DSL执行语句

  3. 发起请求完成操作

代码示例

@Component
public class IndexCreator {
​@Autowiredprivate RestHighLevelClient restHighLevelClient;
​/*** 创建索引库* @param indexName 索引名称* @return 是否创建成功*/public boolean createIndex(String indexName) throws IOException {// 1. 创建索引请求CreateIndexRequest request = new CreateIndexRequest(indexName);
​// 2. 设置索引参数(可选)request.settings(Settings.builder().put("index.number_of_shards", 3)    // 分片数.put("index.number_of_replicas", 1)  // 副本数);
​// 3. 定义映射(Mapping,数据结构)String mapping = """{"mappings": {"properties": {"id":       { "type": "keyword" },"title":    { "type": "text", "analyzer": "ik_max_word" },"price":    { "type": "double" },"createTime": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||epoch_millis" }}}}""";request.mapping(mapping, XContentType.JSON);
​// 4. 执行创建操作CreateIndexResponse response = restHighLevelClient.indices()//拿到所有的索引操作.create(request, RequestOptions.DEFAULT);
​return response.isAcknowledged();}
}

注意:在示例代码里面我们使用的是request.mapping(...) 这个API,这是因为索引的setting参数已经在前面进行了设置。如果需要设置setting参数且之前没有设置的情况下,可以使用request.source(...) 这个API来进行声明。

方法作用参数格式要求
request.mapping(...)仅设置索引的映射(Mapping)接收 纯 Mapping 的 JSON 片段(仅包含 "mappings": { ... } 部分)
request.source(...)设置完整的索引定义(Settings + Mapping)接收 完整的索引 JSON 定义(需包含 "settings": { ... }, "mappings": { ... }
删除索引库、判断索引库是否存在
public class IndexOperator {
​@Autowiredprivate RestHighLevelClient restHighLevelClient;
​/*** 判断索引是否存在* @param indexName 索引名称* @return 是否存在*/public boolean indexExists(String indexName) throws IOException {DeleteIndexRequest request = new DeleteIndexRequest(indexName);return restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);}
}
public class IndexOperator {
​@Autowiredprivate RestHighLevelClient restHighLevelClient;
​/*** 判断索引是否存在* @param indexName 索引名称* @return 是否存在*/public boolean indexExists(String indexName) throws IOException {GetIndexRequest request = new GetIndexRequest(indexName);return restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);}
}

新增、查询、更新、删除文档

在必要的时候需要创建索引库对应的实体对象(一般来说索引库的字段类型结构要不同于数据库的字段类型结构)

基本步骤:

  • 初始化RestHighLevelClient

  • 创建XxxRequest请求。Xxx是Index、Get、Update、Delete

  • 准备参数(Index和Update时需要)

  • 发送请求。调用RestHighLevelClient.Xxx()方法;Xxx是index、get、update、delete

  • 解析结果(Get时需要使用)

新增文档

public class DocumentOperator {
​@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testpublic void DocAddOperator(){//1.创建Request对象IndexRequest request = new IndexRequest("index_name");//2.准备JSON数据(可以自己准备。或者从数据库里面查询再转换成JSON数据,切记要注意字段的数据类型变化)String jsonString = "{" +"\"user\":\"kimchy\"," +"\"postDate\":\"2025-05-19\"," +"\"message\":\"trying out Elasticsearch\"" +"}";
​//3.发送请求restHighLevelClient.index(request,RequestOptions.DEFAULT);}
​
}
查询文档

public class DocumentOperator {
​@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testpublic void DocGetOperator(){//1.创建Request对象GetRequest request = new GetRequest("index_name","1");//2.发送请求GetResponse response=restHighLevelClient.get(request, RequestOptions.DEFAULT);//3.解析响应的结果String json=response。getSourceAsString();System.out.println(json);}
​
}
修改文档

public class DocumentOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testpublic void DocUpdateOperator(){//1.创建Request对象UpdateRequest request = new UpdateRequest("index_name","1");//2.准备请求参数request.doc("price","952","starName","四钻");//3.发送请求 restHighLevelClient.Update(request,RequestOptions.DEFAULT);}}
删除文档
public class DocumentOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testpublic void DocDeleteOperator(){//1.创建Request对象UpdateRequest request = new DeleteRequest("index_name","1");//2.发送请求 restHighLevelClient.delete(request,RequestOptions.DEFAULT);}}
批量导入文档

public class DocumentOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testpublic void DocBulkOperator(){//1.创建Request对象UpdateRequest request = new BulkRequest("index_name","1");//2.添加需要批量提交的请求request.add(new IndexRequest("hotel").id("101").source("json source",XContentType.JSON));new IndexRequest("hotel").id("102").source("json source",XContentType.JSON));//3.发送请求 restHighLevelClient.bulk(request,RequestOptions.DEFAULT);}}

DSL复杂查询

基本步骤:

  • 创建SearchRequest对象

  • 准备Request.source()、也就是DSL

    • QueryBuilders来构建查询条件

    • 传入Request.source()的query()方法

  • 发送请求,得到结果

  • 解析结果(参考Json结果,从内到外,逐层进行解析)

快速入门

public class DocumentOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testvoid DSLOperator() throws IOException {// 1. 准备Request对象(指定目标索引)SearchRequest request = new SearchRequest("hotel"); // 指定查询的索引名为"hotel"// 2. 组织DSL参数(构建查询条件)request.source()                          // 获取SearchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 设置match_all查询(匹配所有文档)// 3. 发送请求,获取响应结果SearchResponse response = restHighLevelClient.search(   // 通过Elasticsearch客户端发送请求request,RequestOptions.DEFAULT                 // 使用默认请求配置(此处可能存在拼写错误,正确应为DEFAULT));// ...解析响应结果(参考前一个示例的解析逻辑)// 4 解析查询结果SearchHits searchHits = response.getHits();// 4.1 获取总匹配文档数long total = searchHits.getTotalHits().value; // 对应JSON中的 "total.value": 2// 4.2 获取命中的文档数组SearchHit[] hits = searchHits.getHits(); // 对应JSON中的 "hits"数组// 遍历所有命中文档for (SearchHit hit : hits) {// 4.3 获取文档原始JSON数据(_source字段)String json = hit.getSourceAsString(); // 对应JSON中的 "_source"对象// 4.4 打印文档内容System.out.println(json);}}
}
全文检索查询

全文检索的语法的结构与前面给的示例代码几乎一摸一样。只需要对其中的一些参数进行一些修改就可以进行使用,下面是代码与DSL语句的对比演示图。可以看到在使用Java代码操作ES时的细节,便于更好的理解代码逻辑,上手完成相关功能。

public class DocumentOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testvoid DSLOperator() throws IOException {// 1. 准备Request对象(指定目标索引)SearchRequest request = new SearchRequest("hotel"); // 指定查询的索引名为"hotel"// 2. 组织DSL参数(构建查询条件)request.source()                          // 获取SearchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 设置match_all查询(匹配所有文档)/*request.source().query(QueryBuilders.matchQuery("all","如家"));//全文检索match查询request.source().query(QueryBuilders.multiMatchQuery("如家","name","brand"));//全文检索muili_match查询request.source().query(QueryBuilders.termQuery("city","杭州"));//精确查询term查询request.source().query(QueryBuilders.rangeQuery("price").gt(100).lt(150);//精确查询range查询=========================================================================bool查询BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();//创建bool查询boolQuery.must(QueryBuilders.termQuery("city","杭州"));//添加term查询boolQuery.filter(QueryBuilders.rangeQuery("price").gt(100).lt(150));//添加range查询*/// 3. 发送请求,获取响应结果SearchResponse response = restHighLevelClient.search(   // 通过Elasticsearch客户端发送请求request,RequestOptions.DEFAULT                 // 使用默认请求配置(此处可能存在拼写错误,正确应为DEFAULT));// ...解析响应结果(参考前一个示例的解析逻辑)// 4 解析查询结果SearchHits searchHits = response.getHits();// 4.1 获取总匹配文档数long total = searchHits.getTotalHits().value; // 对应JSON中的 "total.value": 2// 4.2 获取命中的文档数组SearchHit[] hits = searchHits.getHits(); // 对应JSON中的 "hits"数组// 遍历所有命中文档for (SearchHit hit : hits) {// 4.3 获取文档原始JSON数据(_source字段)String json = hit.getSourceAsString(); // 对应JSON中的 "_source"对象// 4.4 打印文档内容System.out.println(json);}}
}
分页和排序

public class AdviceOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testvoid PageAndOrderOperator() throws IOException {// 1. 准备Request对象(指定目标索引)SearchRequest request = new SearchRequest("hotel"); // 指定查询的索引名为"hotel"// 2. 组织DSL参数(构建查询条件)request.source()                          // 获取SearchSourceBuilder.query(QueryBuilders.matchAllQuery()) // 设置match_all查询(匹配所有文档).sort("price",SortOrder.ASC)//设置排序的参数.from(0).size(5);//设置分页的参数//注意:可以使用链式编程的语法进行编写或者分开来对同一个请求进行参数设置。跟据个人喜好进行书写就可以。// 3. 发送请求restHighLevelClient.search(   // 通过Elasticsearch客户端发送请求request,RequestOptions.DEFAULT                 // 使用默认请求配置(此处可能存在拼写错误,正确应为DEFAULT));}
}
高亮展示

public class AdviceOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testvoid HighLighterOperator() throws IOException {// 1. 准备Request对象(指定目标索引)SearchRequest request = new SearchRequest("hotel"); // 指定查询的索引名为"hotel"// 2. 组织DSL参数(构建查询条件)request.source()                          // 获取SearchSourceBuilder.query(QueryBuilders.matchQuery("all","如家")) // 设置match_all查询(匹配所有文档).highlighter(new HighlightBuilders().field("name").requireFieldMatch(false))//注意:可以使用链式编程的语法进行编写或者分开来对同一个请求进行参数设置。跟据个人喜好进行书写就可以。还可以设置前缀标签与后置标签,增强其可扩展性,这里就直接使用默认的em标签就可以了。// 3. 发送请求restHighLevelClient.search(   // 通过Elasticsearch客户端发送请求request,RequestOptions.DEFAULT                 // 使用默认请求配置(此处可能存在拼写错误,正确应为DEFAULT));}
}

高亮的结果解析是比较复杂的,在这里你可以参考上述的图片中的代码进行理解,因为使用的比较少你可以自行参考,我就不再过多的赘述与编写了。你只需要记住在解析或者编写ES相关的查询语句时对照着原生的DSL语句进行一层一层的剖析,编写就行了。

聚合

public class AggregationsOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testvoid AggOperator() throws IOException {// 1. 准备Request对象(指定目标索引)SearchRequest request = new SearchRequest("hotel"); // 指定查询的索引名为"hotel"// 2. 组织DSL参数(构建查询条件)request.source()                          // 获取SearchSourceBuilder.size(0) //设置分页.aggregation(new AggregationBuilders().term("brandAgg").field("brand").size(10));//注意:可以使用链式编程的语法进行编写或者分开来对同一个请求进行参数设置。跟据个人喜好进行书写就可以。// 3. 发送请求,获取响应结果SearchResponse response = restHighLevelClient.search(   // 通过Elasticsearch客户端发送请求request,RequestOptions.DEFAULT                 // 使用默认请求配置(此处可能存在拼写错误,正确应为DEFAULT));// 4. 解析聚合结果Aggregations aggregations = response.getAggregations(); // 获取聚合结果根对象// 4.1 根据聚合名称获取指定类型的聚合结果(假设为Terms聚合)Terms brandTerms = aggregations.get("brandAgg");// 4.2 获取所有分桶(Bucket)List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();// 4.3 遍历每个分桶for (Terms.Bucket bucket : buckets) {// 4.4 获取当前分桶的键(即聚合的字段值)String key = bucket.getKeyAsString();System.out.println("品牌名称: " + key);}}
}

自动补全

在我们使用一些购物网站时,通常搜索栏都有这样的功能,在你输入一些关键词时就会自动有商品信息自动补全出来供你选择。我们称之为自动补全功能。相关例子如下所示:

拼音分词器

拼音分词器(Pinyin Tokenizer)是一种用于处理中文文本的工具,主要功能是将中文汉字转换为对应的拼音(汉语拼音),并在转换过程中对拼音进行分词处理。它在搜索引擎、自然语言处理(NLP)、语音识别和输入法等场景中广泛应用,尤其在需要处理拼音输入或拼音与汉字混合输入时非常有用。

核心功能

  1. 汉字转拼音 将中文文本逐字或逐词转换为拼音形式。例如:

    • 输入:我爱北京

    • 输出:wo ai bei jing(可配置是否带声调,如 wǒ ài běi jīng)。

  2. 拼音分词 将连续的拼音字符串按语义切分成有意义的词语。例如:

    • 输入拼音:xihuanbeijing

    • 分词结果:xi huan bei jing(喜欢北京)或 xi huan bei jing(需结合上下文优化)。

  3. 多音字处理 根据上下文自动选择正确的拼音。例如:

    • 输入:重庆

    • 可能输出:chong qing(默认)或 zhong qing(需根据语境判断)。

  4. 支持模糊匹配 允许拼音缩写或容错输入。例如:

    • 输入:zhrmbghg

    • 解析为:zhong hua ren min gong he guo(中华人民共和国)。

由于原生的拼音分析器不能满足我们现有的业务要求,面临分词单一、结果弱的现状。我们需要配合现有的手段对分析进行一定的加强来满足符合业务的功能需求

自定义分词器可以在创建索引的时候进行定义与设置,相关参数说明在GitHub的插件下载中有详细的说明与解析。下面是一些常用的分词器设置参数,供参考。需要注意的是自定义的分词器仅仅只在当前索引库生效,其它库是无法使用自定义的分析器的。

在构建完自定义的拼音分词器之后,使用搜索功能时你会发现会有同义信息(拼音相同的信息)被检索出来,不符合业务的规范。为了解决这样的问题,我们需要对搜索使用的分词器进行指定,使其区别于倒排索引时使用的分词器。避免这样的业务问题出现

elasticsearch提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回,为了提高补全查询的效率,对于文档中字段的类型还有一定的约束。

查询语法如下:这一块只需要会对相关代码进行修改与再次使用即可,不用完全熟练掌握。

RestAPI实现

public class CompletionOperator {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testvoid ComOperator() throws IOException {// 1.准备请求SearchRequest request = new SearchRequest("hotel");// 2.构建请求参数request.source().suggest(new SuggestBuilder().addSuggestion("mySuggestion", // 建议名称SuggestBuilders.completionSuggestion("title") // 补全字段.prefix("h")                  // 用户输入前缀.skipDuplicates(true)          // 去重.size(10)                      // 返回数量));// 3.发送请求restHighLevelClient.search(request,RequestOptions.DEFAULT);// 4.处理结果Suggest suggest = response.getSuggest();// 4.1.根据名称获取补全结果(注意名称需与请求一致)CompletionSuggestion suggestion = suggest.getSuggestion("hotelSuggestion"); // 名称可能与请求不一致// 4.2.遍历选项并提取文本for (CompletionSuggestion.Entry.Option option : suggestion.getOptions()) {// 4.3.获取补全词条文本String text = option.getText().string();System.out.println(text);}}
}

数据同步

数据同步问题在许多地方都有体现不单单是在ES这里,还有像redis与MYSQL数据同步等。在实际的业务里面,我们往往是需要对数据库的数据进行相关操作的,那么基于数据库所使用的中间件就需要完成对数据库数据的实时对接与更新,以满足数据的一致性原则。这里给出三种数据同步的解决思路,当然在企业级别的开发中肯定是要使用代码耦合度低,效率高的方法。这里给出的相关策略可以作为大家的知识扩充。

方案一:同步调用

业务代码耦合度高,数据同步一致性强但反应时间长(主业务逻辑耗时长)效率低下。了解

方案二:异步调用

业务代码耦合度低,数据同步一致性好反应时间短(主业务逻辑数据返回耗时短)效率高。比较推荐

方案三:监听binlog

这种方式业务代码的耦合度最低。需要开启MYSQL的binlog功能,会增加数据库的性能开销加之新的中间件的引入,难度不言而喻。

相关文章:

ElasticSearch整合SpringBoot

ElasticSearch 整合SpringBoot ES官方提供了各种不同语言的客户端。用来操作ES。这些客户端的本质就是组装DSL语句&#xff0c;通过HTTP请求发送给ES。 设计索引库 跟据数据库的表结构进行ES索引库的创建时。如果字段需要进行倒排索引的时候请为它指定分词器。如果该字段不是…...

ArcGIS Pro 3.4 二次开发 - 知识图谱

环境:ArcGIS Pro SDK 3.4 + .NET 8 文章目录 知识图谱1 知识图谱数据存储1.1 打开与知识图谱的连接1.2 从KnowledgeGraphLayer获取连接1.3 检索GDB要素类和定义1.4 检索GDB表和定义1.5 从知识图谱数据存储中获取服务 Uri1.6 将一组对象ID转换为实体的ID1.7 将一组ID转换为实体…...

2025上半年软考高级系统架构设计师经验分享

笔者背景 笔者在成都工作近7年&#xff0c; 一直担任研发大头兵&#xff0c;平日工作主要涵盖应用开发&#xff08;Java&#xff09;与数仓开发&#xff0c;对主流数据库、框架等均有涉猎&#xff0c;但谈不上精通。 最近有一些职业上的想法&#xff0c;了解到软考有那么一丁点…...

uni-app学习笔记十二-vue3中创建组件

通过组件&#xff0c;可以很方便地实现页面复用&#xff0c;减少重复页面的创建&#xff0c;减少重复代码。一个页面可以引入多个组件。下面介绍在HBuilder X中创建组件的方法&#xff1a; 一.组件的创建 1.选中项目&#xff0c;右键-->新建目录(文件夹)&#xff0c;并将文…...

React 虚拟dom

虚拟dom react核心机制 内存中轻量级JS对象树模拟真实DOM&#xff0c;主要目的是减少操作真实dom的开销 具体是通过diff算法计算最小的变更&#xff0c;批处理更新真实dom元素 diff算法 特点 同级去进行比较&#xff0c;不涉及跨层的一个比较 使用key值优化列表遍历过程 …...

互联网大厂Java求职面试:AI与大模型应用集成中的架构难题与解决方案-1

互联网大厂Java求职面试&#xff1a;AI与大模型应用集成中的架构难题与解决方案-1 场景描述 郑薪苦&#xff0c;一个看似不靠谱但技术潜力巨大的程序员&#xff0c;在一次针对AI与大模型应用集成的面试中&#xff0c;被一位技术总监级别的人物提问。面试官以严肃专业的态度&a…...

《算法笔记》13.2小节——专题扩展->树状数组(BIT) 问题 D: 数列-训练套题T10T3

数列(sequence.pas/c/cpp) - 问题描述 一个简单的数列问题&#xff1a;给定一个长度为n的数列&#xff0c;求这样的三个元素ai, aj, ak的个数&#xff0c;满足ai < aj > ak&#xff0c;且i < j < k。 - 输入数据 第一行是一个整数n(n < 50000)。 第二行n个整…...

一键启动多个 Chrome 实例并自动清理的 Bash 脚本分享!

目录 一、&#x1f4e6; 脚本功能概览 二、&#x1f4dc; 脚本代码一览 三、&#x1f50d; 脚本功能说明 &#xff08;一&#xff09;✅ 支持批量启动多个 Chrome 实例 &#xff08;二&#xff09;✅ 每个实例使用独立用户数据目录 &#xff08;三&#xff09;✅ 启动后自…...

4 月 62100 款 App 被谷歌下架!环比增长 28%

大家好&#xff0c;我是牢鹅&#xff01;上周刚刚结束的 2025 年 Google I/O 开发者大会&#xff0c; Google Play 带来了一系列的更新&#xff0c;主要围绕提升优质 App 的"发现"、"互动"和"收入"三大核心内容。 这或许正是谷歌生态的一个侧影…...

图像分割全路线学习(结合论文)

本篇文章参考自开源大佬的文章并结合自己的思考而来&#xff0c;欢迎大家提出意见&#xff0c;论文代码同样来自开源&#xff0c;文中已注明 文章目录 图像分割图像分割算法分类&#xff1f;传统的基于CNN的分割方法缺点&#xff1f;FCN详解FCN改变了什么?FCN网络结构&#x…...

Go语言之定义结构体(Struct)-《Go语言实战指南》

结构体&#xff08;struct&#xff09;是 Go 中的一种复合数据类型&#xff0c;它允许你将多个不同类型的字段组合成一个类型&#xff0c;类似于 C 语言的结构体或面向对象语言中的类。 一、结构体的基本定义 type 结构体名 struct {字段名 字段类型... } 示例&#xff1a; …...

mediapipe标注视频姿态关键点(基础版加进阶版)

前言 手语视频流的识别有两种大的分类&#xff0c;一种是直接将视频输入进网络&#xff0c;一种是识别了关键点之后再进入网络。所以这篇文章我就要来讲讲如何用mediapipe对手语视频进行关键点标注。 代码 需要直接使用代码的&#xff0c;我就放这里了。环境自己配置一下吧&…...

PCtoLCD2002如何制作6*8字符

如何不把“等比缩放”前的打勾取消&#xff0c;则无法修改为对应英文字符为6*8。 取消之后就可以更改了&#xff01;...

SmartPlayer与VLC播放RTMP:深度对比分析延迟、稳定性与功能

随着音视频直播技术的发展&#xff0c;RTMP&#xff08;实时消息传输协议&#xff09;成为了广泛应用于实时直播、在线教育、视频会议等领域的重要协议。为了确保优质的观看体验&#xff0c;RTMP播放器的选择至关重要。大牛直播SDK的SmartPlayer和VLC都是在行业中广受欢迎的播放…...

Qt QPaintEvent绘图事件painter使用指南

绘制需在paintEvent函数中实现 用图片形象理解 如果加了刷子再用笔就相当于用笔画过的区域用刷子走 防雷达&#xff1a; 源文件 #include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QPainter> Widget::Widget(QWidget…...

伪创新-《软件方法》全流程引领AI-第1章 04

《软件方法》全流程引领AI-第1章 ABCD工作流-01 对PlantUML们的评价-《软件方法》全流程引领AI-第1章 02 AI辅助的建模步骤-《软件方法》全流程引领AI-第1章 03 第1章 ABCD工作流 1.5 警惕和揭秘伪创新 初中数学里要学习全等三角形、相似三角形、SSS、SAS……&#xff0c;到…...

win11如何重启

在 Windows 11 中重启电脑有多种方法&#xff0c;以下是其中几种常见方法&#xff1a; 开始菜单重启&#xff1a; 点击屏幕左下角的“开始”按钮&#xff08;Windows 图标&#xff09;。 在开始菜单中&#xff0c;点击“电源”图标。 选择“重启”选项。 使用快捷键&#xf…...

【iOS】 锁

iOS 锁 文章目录 iOS 锁前言线程安全锁互斥锁pthread_mutexsynchronized (互斥递归锁)synchronized问题:小结 NSLockNSRecursiveLockNSConditionNSConditionLock 自旋锁OSSpinLock(已弃用)atomicatomic修饰的属性绝对安全吗?os_unfair_lock 读写锁互斥锁和自旋锁的对比 小结使…...

uni-app学习笔记十五-vue3页面生命周期(一)

页面生命周期概览 vue3页面生命周期如下图所示&#xff1a; onLoad 此时页面还未显示&#xff0c;没有开始进入的转场动画&#xff0c;页面dom还不存在。 所以这里不能直接操作dom&#xff08;可以修改data&#xff0c;因为vue框架会等待dom准备后再更新界面&#xff09;&am…...

Flink核心概念小结

文章目录 前言引言数据流API基于POJO的数据流基本源流配置示例基本流接收器数据管道与ETL(提取、转换、加载)一对一映射构建面向流映射的构建键控流进行分组运算RichFlatMapFunction对于流的状态管理连接流的使用流式分析水位的基本概念和示例侧道输入的基本概念和示例Process …...

《软件工程》第 14 章 - 持续集成

在软件工程的开发流程中&#xff0c;持续集成是保障代码质量与开发效率的关键环节。本章将围绕持续集成的各个方面展开详细讲解&#xff0c;结合 Java 代码示例与可视化图表&#xff0c;帮助读者深入理解并实践相关知识。 14.1 持续集成概述 14.1.1 持续集成的相关概念 持续集…...

大模型 Agent 中的通用 MCP 机制详解

1. 引言 大模型(Large Language Model,LLM)技术的迅猛发展催生了一类全新的应用范式:LLM Agent(大模型 Agent)。简单来说,Agent 是基于大模型的自治智能体,它不仅能理解和生成自然语言,还能通过调用工具与环境交互,从而自主地完成复杂任务。ChatGPT 的出现让人们看到…...

Navicat 17 SQL 预览时表名异常右键表名,点击设计表->SQL预览->另存为的SQL预览时,表名都是 Untitled。

&#x1f9d1;‍&#x1f4bb; 用户 Navicat 17 SQL 预览时表名异常右键表名&#xff0c;点击设计表->SQL预览->另存为的SQL预览时&#xff0c;表名都是 Untitled。 &#x1f9d1;‍&#x1f527; 官方技术中心 了解到您的问题&#xff0c;这个显示是正常的&#xff0c…...

Orpheus-TTS:AI文本转语音,免费好用的TTS系统

名人说&#xff1a;博观而约取&#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、Orpheus-TTS&#xff1a;重新定义语音合成的标准1. 什么是Orpheus-TTS&#xff…...

Python爬虫实战:研究Goose框架相关技术

一、引言 随着互联网的迅速发展,网络上的信息量呈爆炸式增长。从海量的网页中提取有价值的信息成为一项重要的技术。网络爬虫作为一种自动获取网页内容的程序,在信息收集、数据挖掘、搜索引擎等领域有着广泛的应用。本文将详细介绍如何使用 Python 的 Goose 框架构建一个完整…...

webpack优化方法

以下是Webpack优化的系统性策略&#xff0c;涵盖构建速度、输出体积、缓存优化等多个维度&#xff0c;配置示例和原理分析&#xff1a; 一、构建速度优化 1. 缩小文件搜索范围 module.exports {resolve: {// 明确第三方模块的路径modules: [path.resolve(node_modules)],// …...

STM32 Keil工程搭建 (手动搭建)流程 2025年5月27日07:42:09

STM32 Keil工程搭建 (手动搭建)流程 觉得麻烦跳转到最底部看总配置图 1.获取官方标准外设函数库 内部结构如下: 文件夹功能分别为 图标(用不上)库函数(重点) Libraries/ ├── CMSIS/ # ARM Cortex-M Microcontroller Software Interface Standard…...

MyBatis 框架使用与 Spring 集成时的使用

MyBatis 创建项目mybatis项目&#xff0c;首先需要使用maven导入mybatis库 poml.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema…...

OpenGL Chan视频学习-7 Writing a Shader inOpenGL

bilibili视频链接&#xff1a; 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函数网站&#xff1a; docs.gl 说明&#xff1a; 1.之后就不再整理具体函数了&#xff0c;网站直接翻译会更直观也会…...

顶会新方向:卡尔曼滤波+目标检测

卡尔曼虑波&#xff0b;目标检测创新结合&#xff0c;新作准确率突破100%! 一个有前景且好发论文的方向:卡尔曼滤波&#xff0b;目标检测! 这种创新结合&#xff0c;得到学术界的广泛认可&#xff0c;多篇成果陆续登上顶会顶刊。例如无人机竞速系统 Swift&#xff0c;登上nat…...