【ElasticSearch】基于 Java 客户端 RestClient 实现对 ElasticSearch 索引库、文档的增删改查操作,以及文档的批量导入

news2024/11/28 2:50:28

文章目录

  • 前言
  • 一、对 Java RestClient 的认识
    • 1.1 什么是 RestClient
    • 1.2 RestClient 核心类:RestHighLevelClient
  • 二、使用 Java RestClient 操作索引库
    • 2.1 根据数据库表编写创建 ES 索引的 DSL 语句
    • 2.2 初始化 Java RestClient
      • 2.2.1 在 Spring Boot 项目中引入 `RestHighLevelClient` 的依赖
      • 2.2.2 编写 HotelIndexTests 单元测试类,完成 RestHighLevelClient 的初始化
    • 2.3 创建索引库
    • 2.4 删除索引库
    • 2.5 判断索引库是否存在
  • 三、使用 Java RestClient 实现对文档的增删改查
    • 3.1 新增文档
    • 3.2 获取文档
    • 3.3 更新文档
    • 3.4 删除文档
    • 3.5 批量导入文档


前言

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

官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html。

在本文中,我们将着重介绍 ElasticSearch Java 客户端中的 RestClient,并演示如何使用它实现对索引库和文档的各种操作。

一、对 Java RestClient 的认识

1.1 什么是 RestClient

RestClient 是 ElasticSearch 提供的用于与 ElasticSearch 集群进行通信的 Java 客户端。它提供了一种简单而灵活的方式来执行 REST 请求,并处理响应。通过 RestClient,我们可以轻松地在 Java 中操作 ElasticSearch。

在 ES 官方文档中看到 Java 的 RestClient 分为 High level REST clientLow level REST client

它们之间的区别:

  1. High Level REST Client:

    • 面向对象:提供了更加面向对象的API,简化了复杂的操作,使用起来更加方便。
    • 使用场景:适用于绝大多数的操作,特别是对于复杂的操作,比如查询、索引、更新等。
  2. Low Level REST Client:

    • 更接近 HTTP 层:提供的是与 Elasticsearch REST API 一一对应的方法,更加灵活,适用于特定场景的定制化需求。
    • 使用场景:适用于对于 Elasticsearch 提供的 REST API 进行细粒度控制的情况,比如处理特殊的请求和响应。

1.2 RestClient 核心类:RestHighLevelClient

RestHighLevelClient 是 Elasticsearch Java 客户端中的高级客户端,提供了更加方便和抽象的操作方式,适用于大多数的 Elasticsearch 操作。在使用 RestHighLevelClient 之前,需要创建一个 RestClient 实例,并将其包装在 RestHighLevelClient 中。

主要功能和特点:

  1. 面向对象的操作:RestHighLevelClient 提供了更加面向对象的 API,使得 Elasticsearch 操作更加符合 Java 开发的习惯,易于理解和使用。

  2. 内置序列化和反序列化:RestHighLevelClient 内置了 Jackson 库,可以自动序列化和反序列化 Elasticsearch 的请求和响应,无需手动处理 JSON 数据。

  3. 复杂查询支持:支持复杂的 Elasticsearch 查询操作,如布尔查询、范围查询、聚合查询等。

  4. 错误处理:提供了异常处理机制,能够更好地捕获和处理 Elasticsearch 操作中的错误。

  5. 并发性:RestHighLevelClient 可以处理多个并发请求,是多线程安全的。

常用操作和方法:

以下是 RestHighLevelClient 类的一些常用操作和方法,通过这些方法可以实现对 Elasticsearch 的索引库和文档的各种操作:

操作方法描述
索引文档IndexResponse index(IndexRequest request, RequestOptions options)向指定索引插入文档
获取文档GetResponse get(GetRequest request, RequestOptions options)根据文档 ID 获取文档
删除文档DeleteResponse delete(DeleteRequest request, RequestOptions options)根据文档 ID 删除文档
更新文档UpdateResponse update(UpdateRequest request, RequestOptions options)根据文档 ID 更新文档
批量操作BulkResponse bulk(BulkRequest request, RequestOptions options)批量执行操作
查询SearchResponse search(SearchRequest request, RequestOptions options)执行搜索查询
聚合查询SearchResponse search(SearchRequest request, RequestOptions options)执行聚合查询
清理滚动ClearScrollResponse clearScroll(ClearScrollRequest request, RequestOptions options)清理滚动上下文

以上只是 RestHighLevelClient 类的一部分方法,更多详细的操作和方法请参考 官方文档。这些方法提供了丰富的功能,可以满足各种 Elasticsearch 操作的需求。

二、使用 Java RestClient 操作索引库

2.1 根据数据库表编写创建 ES 索引的 DSL 语句

当需要将已有的数据库数据导入到 Elasticsearch 索引中时,首先需要定义好 Elasticsearch 索引的 mapping 结构,这样 Elasticsearch 才能正确解析和存储数据。

在这个例子中,我们有一个名为 hotel 的数据库表,它有各种不同类型的字段,包括文本、数字、地理坐标等。让我们逐步解释如何根据数据库表的结构编写创建 Elasticsearch 索引的 DSL(Domain Specific Language)语句。

  1. 数据库表结构分析

首先,让我们来看一下 hotel 表的结构:

+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id        | bigint       | NO   | PRI | NULL    |       |
| name      | varchar(255) | NO   |     | NULL    |       |
| address   | varchar(255) | NO   |     | NULL    |       |
| price     | int          | NO   |     | NULL    |       |
| score     | int          | NO   |     | NULL    |       |
| brand     | varchar(32)  | NO   |     | NULL    |       |
| city      | varchar(32)  | NO   |     | NULL    |       |
| star_name | varchar(16)  | YES  |     | NULL    |       |
| business  | varchar(255) | YES  |     | NULL    |       |
| latitude  | varchar(32)  | NO   |     | NULL    |       |
| longitude | varchar(32)  | NO   |     | NULL    |       |
| pic       | varchar(255) | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+

这个表包含了以下字段:

  • id:长整型(bigint
  • name:文本字符串(varchar),用于存储酒店名称
  • address:文本字符串,用于存储酒店地址
  • price:整数(int),表示酒店价格
  • score:整数,表示酒店评分
  • brand:文本字符串,用于存储酒店品牌
  • city:文本字符串,用于存储城市名称
  • star_name:文本字符串,用于存储星级名称(可为空)
  • business:文本字符串,用于存储营业信息(可为空)
  • latitude:文本字符串,用于存储纬度坐标
  • longitude:文本字符串,用于存储经度坐标
  • pic:文本字符串,用于存储图片路径(可为空)
  1. 创建 Elasticsearch 索引的 DSL

现在,让我们将上述数据库表的结构映射到 Elasticsearch 索引的 DSL 中:

PUT /hotel
{
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "name": {
        "type": "text",
        "analyzer": "ik_max_word",
        "copy_to": "all"
      },
      "address": {
        "type": "keyword",
        "index": false
      },
      "price": {
        "type": "integer"
      },
      "score": {
        "type": "integer"
      },
      "brand": {
        "type": "keyword",
        "copy_to": "all"
      },
      "city": {
        "type": "keyword"
      },
      "starName": {
        "type": "keyword"
      },
      "business": {
        "type": "keyword",
        "copy_to": "all"
      },
      "location": {
        "type": "geo_point"
      },
      "pic": {
        "type": "keyword",
        "index": false
      },
      "all": {
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}

重要说明:

  1. 地理坐标 (location) 字段:

在 MySQL 数据库表中,地理坐标是使用 latitudelongitude 两个字段表示的。但在 Elasticsearch 中,我们使用 geo_point 类型来表示地理坐标。

  • geo_point:由纬度(latitude)和经度(longitude)确定的一个点。例如:“32.8752345, 120.2981576”。

补充:ES 中支持两种地理坐标数据类型

  • geo_point:由纬度(latitude)和经度(longitude)确定的一个点。例如:"32.8752345, 120.2981576"
  • geo_shape:有多个geo_point组成的复杂几何图形。例如一条直线:"LINESTRING (-77.03653 38.897676, -77.009051 38.889939)"
  1. 字段拷贝:

字段拷贝的目的是在搜索时,同时匹配多个字段。我们使用 copy_to 属性将当前字段拷贝到指定字段。这样,在搜索时,可以同时匹配 namebrandbusiness 字段。

示例:

"all": {
  "type": "text",
  "analyzer": "ik_max_word"
},
"brand": {
  "type": "keyword",
  "copy_to": "all"
}
  1. 映射规则总结

Elasticsearch 对不同类型的字段有不同的映射规则,以下是常见类型的映射规则:

  • 字符串 (textkeyword): text 用于全文搜索,支持分词;keyword 用于精确匹配,不分词。
  • 整数 (integer): 用于存储整数。
  • 长整型 (long): 用于存储长整数。
  • 浮点数 (float): 用于存储浮点数。
  • 地理坐标 (geo_point): 用于存储地理坐标。
  • 日期 (date): 用于存储日期时间。

通过正确定义索引的映射规则,我们可以更有效地利用 Elasticsearch 的搜索和分析功能。

2.2 初始化 Java RestClient

2.2.1 在 Spring Boot 项目中引入 RestHighLevelClient 的依赖

首先在 pom.xml 中引入依赖

<!--ElasticSearch 客户端依赖-->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.12.1</version>
</dependency>

此次引入的版本是 7.12.1 版本的,目的是与ElasticSearch 服务器的版本相同。刷新 Maven 之后,发现 elasticsearch-rest-high-level-client依赖中某些组件的版本并不是7.12.1的:

其原因是 Spring Boot 已经自动为我们管理了一些依赖,其中就包括了elasticsearch,其版本就是 7.6.2的。


因此我们需要做的就是在 pom.xml 覆盖这个配置,即在 properties 中指定版本为 7.12.1

再次刷新 Maven,就能够发现所有组件的版本都是 7.12.1 了:

2.2.2 编写 HotelIndexTests 单元测试类,完成 RestHighLevelClient 的初始化

@SpringBootTest
class HotelIndexTests {
    private RestHighLevelClient client;

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.248.128:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
    /**
     * 测试初始化客户端
     */
    @Test
    void testInit() {
        System.out.println(client);
    }
}

对上述代码的说明:

  • 在上述代码中,通过 RestClient.builder 构建了 RestHighLevelClient 实例,并指定了 ElasticSearch 服务器的地址为 http://192.168.248.128:9200。这是一个简单的单元测试,用于验证客户端的初始化是否成功。
  • @BeforeEach 注解的方法中,我们创建了 RestHighLevelClient 的实例,而在 @AfterEach 注解的方法中,我们关闭了客户端。这是为了保证测试用例执行前后,客户端都能够正确地被初始化和关闭。
  • 在测试方法 testInit 中,我们简单地打印了客户端对象,以验证其初始化是否成功。

在接下来的内容中,我们将继续使用编写单元测试方法,执行一系列对 ElasticSearch 索引库和文档的操作。

2.3 创建索引库

创建 hotel 索引库会使用到前文根据 hotle 表结构编写的 DSL mapping 映射,在Java代码中,我们需要将其封装成一个全局常量,例如,将其保存到名为 MAPPING_TEMPLATE 的常量字符串中:

public class HotelConstants {
    public static final String MAPPING_TEMPLATE = "{\n" +
            "  \"mappings\": {\n" +
            "    \"properties\": {\n" +
            "      \"id\": {\n" +
            "        \"type\": \"long\"\n" +
            "      },\n" +
            "      \"name\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_max_word\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"address\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"price\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"score\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"brand\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"city\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"starName\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"business\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"location\": {\n" +
            "        \"type\": \"geo_point\"\n" +
            "      },\n" +
            "      \"pic\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"all\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_max_word\"\n" +
            "      }\n" +
            "    }\n" +
            "  }\n" +
            "}";
}

下面是创建索引库的单元测试方:

    /**
     * 创建索引库
     *
     * @throws IOException 抛出异常
     */
    @Test
    void testCreateHotelIndex() throws IOException {
        // 1. 创建 Request 对象
        CreateIndexRequest request = new CreateIndexRequest("hotel");

        // 2. 准备请求参数:DSL 语句
        request.source(MAPPING_TEMPLATE, XContentType.JSON);

        // 3. 发起请求
        client.indices().create(request, RequestOptions.DEFAULT);
    }

对上述代码的说明:

  1. 创建 CreateIndexRequest 对象,指定索引库的名称为 "hotel"
  2. 准备请求参数,即 DSL 语句,使用 MAPPING_TEMPLATE 常量。
  3. 发起创建索引库的请求,通过 client.indices().create(request, RequestOptions.DEFAULT) 执行。

这样,我们就完成了通过 Java RestClient 创建 ElasticSearch 索引库的操作。在实际应用中,创建索引库是一个初始化工作,通常在应用启动时执行一次即可。

2.4 删除索引库

以下是使用 Java RestClient 删除名为 “hotel” 的索引库的单元测试方法:

/**
 * 删除索引库
 * @throws IOException 抛出异常
 */
@Test
void testDeleteHotelIndex() throws IOException {
    // 1. 创建 Request 对象
    DeleteIndexRequest request = new DeleteIndexRequest("hotel");

    // 2. 发起请求
    client.indices().delete(request, RequestOptions.DEFAULT);
}

对上述代码的说明:

  1. 创建 DeleteIndexRequest 对象,指定要删除的索引库名称为 “hotel”。
  2. 发起删除索引库的请求,通过 client.indices().delete(request, RequestOptions.DEFAULT) 执行。

这个方法主要用于清理测试环境或者在应用退出时执行,以确保数据的整洁和安全。

删除索引库的操作需要谨慎执行,因为它会将整个索引库以及其中的所有文档都删除,且无法恢复。在实际应用中,通常会设置一些安全机制来避免误操作。

2.5 判断索引库是否存在

在 Elasticsearch 中,我们可以通过 Java RestClient 来判断指定的索引库是否存在。以下是一个示例代码:

@Test
void testExistsHotelIndex() throws IOException {
    // 1. 创建 GetIndexRequest 对象,指定要判断是否存在的索引库名称为 "hotel"
    GetIndexRequest request = new GetIndexRequest("hotel");
    
    // 2. 发起请求,执行判断索引库是否存在的操作
    boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    
    // 3. 打印判断结果
    System.out.println(exists ? "索引库存在" : "索引库不存在");
}

在这个方法中,首先创建了一个 GetIndexRequest 对象,指定了要判断是否存在的索引库名称为 “hotel”。然后,通过 client.indices().exists(request, RequestOptions.DEFAULT) 发起请求,执行判断索引库是否存在的操作。最后,根据返回的布尔值,输出相应的提示信息。

这个方法通常用于在进行其他操作之前,先判断索引库是否存在,以确保我们不会对不存在的索引库执行其他操作。

三、使用 Java RestClient 实现对文档的增删改查

3.1 新增文档

在新增文档之前,首先需要从数据库中去查询一条记录,然后再将查询到的记录保存到 ES 文档中。例如,现在有一条 id=61083的酒店数据,我们需要把它查询出来,然后添加到文档中:

首先同样需要创建一个测试类HotelDocumentTests,并完成 RestHighLevelClient 的初始化。然后新增文档的测试代码如下:

@Test
void testAddDocument() throws IOException {
    // 根据id查询酒店
    Hotel hotel = hotelService.getById(61083L);
    // 转换为文档类型
    HotelDoc hotelDoc = new HotelDoc(hotel);

    // 1. 准备 Request 对象
    IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());

    // 2. 准备 JSON 文档
    request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);

    // 3. 发送请求
    client.index(request, RequestOptions.DEFAULT);
}

对上述代码的说明:

  1. 根据 ID 查询酒店数据: 使用 hotelService.getById(61083L) 方法从数据库中根据酒店 ID(这里是 61083L)查询酒店数据并封装到 Hotel 对象中。

  2. 转换为文档类型: 将查询到的 Hotel 类型转换为HotelDoc文档类型,因为数据库和文档中表示经纬度的方式不同。

  3. 准备 IndexRequest 对象: 创建 IndexRequest 对象,指定索引库名称为 “hotel”,并设置文档 ID 为酒店的 ID(使用 hotel.getId().toString() 获取 ID 的字符串表示)。

  4. 准备 JSON 文档:HotelDoc 对象转换为 JSON 格式的字符串,使用 JSON.toJSONString(hotelDoc) 实现转换。

  5. 发送请求: 使用 client.index(request, RequestOptions.DEFAULT) 发送请求,将准备好的文档添加到索引库中。

这个测试方法演示了如何通过 Java RestClient 向 Elasticsearch 索引库中新增文档。

3.2 获取文档

获取指定文档的测试方法的代码如下:

@Test
void testGetDocument() throws IOException {
    // 1. 创建 Request 对象
    GetRequest request = new GetRequest("hotel", "61083");

    // 2. 发送请求,获取结果
    GetResponse response = client.get(request, RequestOptions.DEFAULT);

    // 3. 解析结果
    String json = response.getSourceAsString();

    // 4. 将字符串解析为 HotelDoc 对象
    HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);

    System.out.println(hotelDoc);
}

对该方法的详细说明:

  1. 创建 GetRequest 对象: 使用 GetRequest 对象指定索引库名称为 “hotel”,文档 ID 为 “61083”。

  2. 发送请求,获取结果: 使用 client.get(request, RequestOptions.DEFAULT) 发送请求,获取包含文档信息的 GetResponse 对象。

  3. 解析结果: 通过 response.getSourceAsString() 获取文档内容的 JSON 字符串表示。

  4. 将字符串解析为 HotelDoc 对象: 使用 JSON.parseObject(json, HotelDoc.class) 将获取的 JSON 字符串解析为 HotelDoc 对象。

这个测试方法演示了如何通过 Java RestClient 获取 Elasticsearch 索引库中指定文档的信息。

3.3 更新文档

更新文档的测试方法的代码如下:

@Test
void testUpdateDocument() throws IOException {
    // 1. 获取 Request 对象
    UpdateRequest request = new UpdateRequest("hotel", "61083");

    // 2. 准备参数
    request.doc(
            "price", 1000,
            "score", 50
    );

    // 3. 发起请求
    client.update(request, RequestOptions.DEFAULT);
}

对该方法的详细说明:

  1. 获取 UpdateRequest 对象: 使用 UpdateRequest 对象指定索引库名称为 “hotel”,文档 ID 为 “61083”。

  2. 准备参数: 使用 request.doc(...) 方法准备需要更新的字段及其对应的新值。在这个例子中,更新了 “price” 字段为 1000,“score” 字段为 50。

  3. 发起请求: 使用 client.update(request, RequestOptions.DEFAULT) 发送更新请求。

这个测试方法演示了如何通过 Java RestClient 更新 Elasticsearch 索引库中的指定文档。

3.4 删除文档

删除指定文档的单元测试方法的代码如下:

@Test
 void testDeleteDocument() throws IOException {
     // 1. 获取 Request 对象
     DeleteRequest request = new DeleteRequest("hotel", "61083");

     // 2. 发起请求
     client.delete(request, RequestOptions.DEFAULT);
 }

对该方法的详细说明:

  1. 获取 DeleteRequest 对象: 使用 DeleteRequest 对象指定索引库名称为 “hotel”,文档 ID 为 “61083”。

  2. 发起请求: 使用 client.delete(request, RequestOptions.DEFAULT) 发送删除请求。

这个测试方法演示了如何通过 Java RestClient 删除 Elasticsearch 索引库中的指定文档。

3.5 批量导入文档

在实际开发中,我们不可能像上面那样一条数据一条数据的导入到文档中,而是需要批量的查询数据库,然后将结果集批量的导入到文档中,导入批量数据到文档的测试方法如下:

@Test
void testBulkRequest() throws IOException {
    // 批量查询酒店数据
    List<Hotel> hotels = hotelService.list();

    // 1. 创建 BulkRequest
    BulkRequest request = new BulkRequest();

    // 转换为文档类型 HotelDoc
    for (Hotel hotel : hotels) {
        HotelDoc hotelDoc = new HotelDoc(hotel);
        // 2. 准备参数,添加多个新增的 Request
        request.add(new IndexRequest("hotel")
                .id(hotel.getId().toString())
                .source(JSON.toJSONString(hotelDoc), XContentType.JSON));
    }

    // 3. 发起请求
    client.bulk(request, RequestOptions.DEFAULT);
}

对上述代码的说明:

  1. 批量查询酒店数据: 使用 hotelService.list() 批量获取酒店数据。

  2. 创建 BulkRequest 对象: 使用 BulkRequest 对象准备批量请求。

  3. 循环添加请求: 遍历酒店数据列表,将每个酒店数据转换为 HotelDoc 类型,并添加到 BulkRequest 中。

  4. 发起请求: 使用 client.bulk(request, RequestOptions.DEFAULT) 发送批量请求。

这个测试方法演示了如何通过 Java RestClient 批量导入 Elasticsearch 索引库中的文档。批量导入通常能够提高效率,特别是在处理大量数据时。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1070099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关系的性质(自反,反自反,对称,反对称,传递)

自反 若∀a∈A&#xff0c;必有<a,a>∈R&#xff0c;则称R是自反的&#xff0c;&#xff08;关系矩阵对角线都为1&#xff09;。 例&#xff1a;A{1,2,3}&#xff0c;R{<1,1,>,<2,2>,<3,3> 反自反 若∀a∈A&#xff0c;必有<a,a>R&#xff0c;…

微服务架构的未来:跨边界的云原生整合

文章目录 微服务架构的基础微服务的挑战云原生的崛起跨边界的云原生整合实现跨边界的云原生整合跨边界的云原生整合案例结论 &#x1f389;欢迎来到架构设计专栏~微服务架构的未来&#xff1a;跨边界的云原生整合 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&…

Android Studio修改虚拟机AVD Manger目录

Android Studio修改虚拟机AVD Manger目录 1、在AS的设备管理器Device Manager中删除原来创建的所有虚拟机&#xff08;Android Virtual Device&#xff09;&#xff1b; 2、新建一个自定义的AVD目录&#xff0c;例如&#xff1a;D:\Android\AndroidAVD 3、在高级系统设置中增加…

flutter出现entrypoint isn‘t within the current project

更新了android studio版本&#xff0c;打开一个老的flutter项目时&#xff0c;无法运行&#xff0c;打开configuration配置&#xff0c;提示错误entrypoint isn’t within the current project. 解决办法 1、删掉目录.idea, .gradle, .dart_tool退出重新打开项目 2、选中根目…

【Linux】Git使用

一、Git简介 Git 是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理很小或非常大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 Git 与常用的版本控制工具 CVS, Subversion 等不同&#xff0c;它采用了分布…

人脸动作迁移——基于DaGAN深度感知的生成对抗网络操作对口型数字人

前言 口播视频生成旨在合成具有源图像和驱动视频的身份和姿势信息的协同人脸视频。现有方法主要依赖于从输入图像中学到的二维表示&#xff08;如外观和运动&#xff09;&#xff0c;但密集的三维面部几何信息&#xff08;如像素深度&#xff09;对任务至关重要。这有助于生成…

raft算法的自我理解

1、raft算法是什么&#xff1f; 答&#xff1a;共识算法 2、raft算法有什么用&#xff1f; 答&#xff1a;维持不同机器的强一致性 3、raft算法通过什么方式来维持不同机器的强一致性&#xff1f; 答&#xff1a;传递log日志 &#xff0c;按照官方的说法日志里面包含命令&…

泛型的小结

文章目录 什么是泛型泛型的相关概念泛型的作用 泛型的使用泛型类语法泛型接口语法泛型方法语法泛型类的简单示例泛型接口的简单示例基于泛型的简单工厂方法泛型的上界与下界 泛型的一些使用建议 什么是泛型 从JDK1.5开始引入泛型&#xff08;generic&#xff09;语法。对类型实…

北邮22级信通院数电:Verilog-FPGA(4)第四第五周实验 密码保险箱的设计

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 一.密码箱的功能和安全性 显示&#xff1a;…

Python—Scrapy实践项目

爬取豆瓣电影2022年Top250部经典电影 1.项目概述 从https://movie.douban/top250爬取电影的标题、评分、主题。我在之前使用普通的爬虫实现了类似的功能&#xff0c;可以对比来进行学习&#xff08;Python爬虫——爬虫基础模块和类库&#xff08;附实践项目&#xff09;&#…

Spring框架(中)

1、基于注解管理Bean&#xff1a; 1、开启组件扫描&#xff1a; Spring 默认不使用注解装配 Bean&#xff0c;因此我们需要在 Spring 的 XML 配置中&#xff0c;通过 context:component-scan 元素开启 Spring Beans的自动扫描功能。开启此功能后&#xff0c;Spring 会自动从扫…

JVM CMS和G1执行过程比较

CMS CMS&#xff08;Concurrent Mark Sweep&#xff09;收集器是一种以获取最短回收停顿时间为目标的收集器。由于大部分 Java 应用主要集中在互联网网站以及基于浏览器的 B/S 系统的服务端&#xff0c;这类应用通常会较为关注服务的响应速度&#xff0c;希望系统的停顿时间尽…

公司软文怎么写?如何写好软文?

软文&#xff0c;即柔性广告&#xff0c;是通过文字、图片等形式&#xff0c;以一种隐性的方式&#xff0c;将广告信息融入到文章中&#xff0c;以达到宣传、推广的目的。它相较于硬广告&#xff0c;更能深入人心&#xff0c;更易被接受。 首先&#xff0c;软文能够提升品牌的…

xlsx使用table_to_book报错Uncaught Unsupported origin when DIV is not a TABLE

背景&#xff1a;const workbook XLSX.utils.table_to_book(document.querySelector(‘#table-export’),{ raw: true//保留原始字符串 })报错Uncaught Unsupported origin when DIV is not a TABLE 原因&#xff1a;el-table是div格式 过程1&#xff1a;获取深层次的table…

使用Docker安装JupyterHub

安装JupyterHub 拉取Jupyter镜像并运行容器 docker run -d -p 8000:8000 --name jupyterhub jupyterhub/jupyterhub jupyterhub # -d&#xff1a;后台运行 # -p 8000:8000&#xff1a;宿主机的8000端口映射容器中的8000端口 # --name jupyterhub&#xff1a;给运行的容器起名…

H3C 防火墙策略

H3C防火墙有安全策略和域间策略&#xff0c;安全策略的优先级大于域间策略&#xff0c;会优先匹配安全策略&#xff0c;匹配不到才会匹配域间策略 域间策略&#xff1a;any to any的域间策略优先级低于具体的区域到具体的区域的域间策略 安全策略匹配顺序&#xff1a;从上到下…

剑指offer——JZ34 二叉树中和为某一值的路径(二) 解题思路与具体代码【C++】

一、题目描述与要求 二叉树中和为某一值的路径(二)_牛客题霸_牛客网 (nowcoder.com) 题目描述 输入一颗二叉树的根节点root和一个整数expectNumber&#xff0c;找出二叉树中结点值的和为expectNumber的所有路径。 1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过…

第 366 场周赛 LeetCode 周赛题解

A 分类求和并作差 模拟 class Solution { public:int differenceOfSums(int n, int m) {int res 0;for (int i 1; i < n; i)res i % m ! 0 ? i : -i;return res;} };B 最小处理时间 排序&#xff1a;设四个 p r o c e s s o r T i m e processorTime processorTime 的元…

【LeetCode 算法专题突破】二分查找(⭐)

文章目录 前言1. 二分经典模板题目题目描述代码&#xff1a; 2. 在排序数组中查找元素的第一个和最后一个位置题目描述代码 3. 有效的完全平方数题目描述代码 4. 寻找峰值题目描述代码 5. 寻找旋转排序数组中的最小值题目描述代码 6. 点名题目描述代码 总结 前言 我刷过不少算…

java: 警告: 源发行版 17 需要目标发行版 17

一、遇到问题&#xff1a; java: 警告: 源发行版 17 需要目标发行版 17 二、分析原因&#xff1a;JDK版本不一致 在idea中编辑器中修改JDK配置 三、解决问题 找到settings -- Build,Execution,Deployment -- compiler -- JavaCompiler 进行更改版本 另外还要找到两个地方的J…