使用Spring Boot集成中间件:Elasticsearch基础->提高篇

这篇具有很好参考价值的文章主要介绍了使用Spring Boot集成中间件:Elasticsearch基础->提高篇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用Spring Boot集成中间件:Elasticsearch基础->提高篇

导言

Elasticsearch是一个开源的分布式搜索和分析引擎,广泛用于构建实时的搜索和分析应用。在本篇博客中,我们将深入讲解如何使用Spring Boot集成Elasticsearch,实现数据的索引、搜索和分析。

一、 Elasticsearch一些基本操作和配置

1. 准备工作

在开始之前,确保已经完成以下准备工作:

  • 安装并启动Elasticsearch集群
  • 创建Elasticsearch索引和映射(Mapping)

2. 添加依赖

首先,需要在Spring Boot项目中添加Elasticsearch的依赖。在pom.xml文件中加入以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

3. 配置Elasticsearch连接

application.propertiesapplication.yml中配置Elasticsearch的连接信息:

spring.data.elasticsearch.cluster-nodes=localhost:9200

4. 创建实体类

创建一个Java实体类,用于映射Elasticsearch中的文档。

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;

@Document(indexName = "blog", type = "article")
public class Article {

    @Id
    private String id;

    private String title;

    private String content;

    // Getters and setters
}

在上述代码中,我们使用了@Document注解定义了Elasticsearch中的索引名和文档类型。

5. 创建Repository接口

使用Spring Data Elasticsearch提供的ElasticsearchRepository接口来定义对Elasticsearch的操作。

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface ArticleRepository extends ElasticsearchRepository<Article, String> {

    List<Article> findByTitle(String title);

    List<Article> findByContent(String content);
}

通过继承ElasticsearchRepository,我们可以直接使用Spring Data提供的方法进行数据的CRUD操作。

6. 编写Service

创建一个Service类,封装业务逻辑,调用Repository进行数据操作。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ArticleService {

    private final ArticleRepository articleRepository;

    @Autowired
    public ArticleService(ArticleRepository articleRepository) {
        this.articleRepository = articleRepository;
    }

    public List<Article> searchByTitle(String title) {
        return articleRepository.findByTitle(title);
    }

    public List<Article> searchByContent(String content) {
        return articleRepository.findByContent(content);
    }
}

7. 使用示例

在Controller层使用我们创建的Service进行数据的操作。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/articles")
public class ArticleController {

    private final ArticleService articleService;

    @Autowired
    public ArticleController(ArticleService articleService) {
        this.articleService = articleService;
    }

    @GetMapping("/searchByTitle")
    public List<Article> searchByTitle(@RequestParam String title) {
        return articleService.searchByTitle(title);
    }

    @GetMapping("/searchByContent")
    public List<Article> searchByContent(@RequestParam String content) {
        return articleService.searchByContent(content);
    }
}

8. 运行和测试

通过访问Controller提供的接口,我们可以进行数据的索引、搜索等操作:

curl -X GET http://localhost:8080/articles/searchByTitle?title=Elasticsearch

二、 Elasticsearch 保存实体类在表中的映射

Elasticsearch 与传统的关系型数据库不同,它采用的是文档型数据库的思想,数据以文档的形式存储。在 Elasticsearch 中,我们不再创建表,而是创建索引(Index),每个索引包含多个文档(Document),每个文档包含多个字段。

以下是 Elasticsearch 中建立索引和实体类的映射的基本步骤:

1. 创建索引

在 Elasticsearch 中,索引是存储相关文档的地方。我们可以通过 RESTful API 或者在 Spring Boot 项目中使用 Elasticsearch 的 Java 客户端创建索引。以下是通过 RESTful API 创建索引的示例:

PUT /my_index

上述命令创建了一个名为 my_index 的索引。在 Spring Boot 项目中,可以使用 IndexOperations 类来创建索引,示例如下:

@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;

public void createIndex() {
    elasticsearchRestTemplate.indexOps(MyEntity.class).create();
}

2. 定义实体类

实体类用于映射 Elasticsearch 中的文档结构。每个实体类的实例对应于一个文档。在实体类中,我们可以使用注解来定义字段的映射关系。以下是一个简单的实体类示例:

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Document(indexName = "my_index", type = "my_entity")
public class MyEntity {

    @Id
    private String id;

    @Field(type = FieldType.Text)
    private String name;

    @Field(type = FieldType.Keyword)
    private String category;

    // 其他字段和方法
}

上述示例中,通过 @Document 注解定义了索引名为 my_index,类型名为 my_entity。通过 @Field 注解定义了字段的映射关系,例如 name 字段映射为 Text 类型,category 字段映射为 Keyword 类型。

3. 保存文档

保存文档是将实体类的实例存储到 Elasticsearch 中的过程。在 Spring Boot 项目中,可以使用 ElasticsearchTemplate 或者 ElasticsearchRepository 进行文档的保存。以下是使用 ElasticsearchRepository 的示例:

public interface MyEntityRepository extends ElasticsearchRepository<MyEntity, String> {
}

在上述示例中,MyEntityRepository 继承了 ElasticsearchRepository 接口,泛型参数为实体类类型和 ID 类型。Spring Data Elasticsearch 将根据实体类的结构自动生成相应的 CRUD 方法。通过调用 save 方法,可以保存实体类的实例到 Elasticsearch 中。

@Autowired
private MyEntityRepository myEntityRepository;

public void saveDocument() {
    MyEntity entity = new MyEntity();
    entity.setName("Document Name");
    entity.setCategory("Document Category");

    myEntityRepository.save(entity);
}

上述代码示例中,我们创建了一个 MyEntity 类的实例,并使用 save 方法将其保存到 Elasticsearch 中。


提高篇

一 实际案例:使用Spring Boot集成Elasticsearch的深度提高篇

在这个实际案例中,我们将以一个图书搜索引擎为例,详细讲解如何使用Spring Boot集成Elasticsearch进行深度提高,包括性能调优、复杂查询、分页和聚合等方面。

1. 准备工作

首先,确保你已经搭建好Elasticsearch集群,并且在Spring Boot项目中添加了Elasticsearch的依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2. 配置文件

application.propertiesapplication.yml中配置Elasticsearch的连接信息:

spring.data.elasticsearch.cluster-nodes=localhost:9200

3. 实体类

创建一个图书实体类,用于映射Elasticsearch中的文档。

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;

@Document(indexName = "books", type = "book")
public class Book {

    @Id
    private String id;

    private String title;

    private String author;

    private String genre;

    // Getters and setters
}

4. Repository 接口

创建一个Elasticsearch Repository接口,继承自ElasticsearchRepository,用于对图书文档进行操作。

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface BookRepository extends ElasticsearchRepository<Book, String> {

    List<Book> findByTitleLike(String title);

    List<Book> findByAuthorAndGenre(String author, String genre);

    // 更多自定义查询方法
}

5. 服务类

创建一个服务类,用于处理业务逻辑,调用Repository进行图书文档的操作。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class BookService {

    private final BookRepository bookRepository;

    @Autowired
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    public List<Book> searchBooksByTitle(String title) {
        return bookRepository.findByTitleLike(title);
    }

    public List<Book> searchBooksByAuthorAndGenre(String author, String genre) {
        return bookRepository.findByAuthorAndGenre(author, genre);
    }

    // 更多业务逻辑和自定义查询方法
}

6. 性能调优

6.1 配置文件调优

application.properties中配置Elasticsearch的连接池大小和相关参数:

spring.data.elasticsearch.properties.http.max_content_length=100mb
spring.data.elasticsearch.properties.http.max_initial_line_length=100kb
spring.data.elasticsearch.properties.http.max_header_size=3kb
spring.data.elasticsearch.properties.transport.tcp.compress=true
spring.data.elasticsearch.properties.transport.tcp.connect_timeout=5s
spring.data.elasticsearch.properties.transport.tcp.keep_alive=true
spring.data.elasticsearch.properties.transport.tcp.no_delay=true
spring.data.elasticsearch.properties.transport.tcp.socket_timeout=5s
6.2 JVM调优

修改jvm.options文件,调整堆内存大小:

-Xms2g
-Xmx2g

7. 复杂查询

通过服务类提供的自定义查询方法实现复杂查询,例如按标题模糊查询和按作者、类别查询:

@RestController
@RequestMapping("/books")
public class BookController {

    private final BookService bookService;

    @Autowired
    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @GetMapping("/searchByTitle")
    public List<Book> searchByTitle(@RequestParam String title) {
        return bookService.searchBooksByTitle(title);
    }

    @GetMapping("/searchByAuthorAndGenre")
    public List<Book> searchByAuthorAndGenre(@RequestParam String author, @RequestParam String genre) {
        return bookService.searchBooksByAuthorAndGenre(author, genre);
    }
}

8. 分页和聚合

在Controller中添加分页和聚合的方法:

@GetMapping("/searchWithPagination")
public List<Book> searchWithPagination(@RequestParam String title, @RequestParam int page, @RequestParam int size) {
    PageRequest pageRequest = PageRequest.of(page, size);
    return bookService.searchBooksByTitleWithPagination(title, pageRequest);
}

@GetMapping("/aggregateByGenre")
public Map<String, Long> aggregateByGenre() {
    return bookService.aggregate

BooksByGenre();
}

在服务类中实现分页和聚合的方法:

public List<Book> searchBooksByTitleWithPagination(String title, Pageable pageable) {
    SearchHits<Book> searchHits = bookRepository.search(QueryBuilders.matchQuery("title", title), pageable);
    return searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList());
}

public Map<String, Long> aggregateBooksByGenre() {
    TermsAggregationBuilder aggregation = AggregationBuilders.terms("genres").field("genre").size(10);
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().aggregation(aggregation);
    SearchHits<Book> searchHits = bookRepository.search(sourceBuilder.build());
    
    return searchHits.getAggregations().asMap().entrySet().stream()
            .collect(Collectors.toMap(Map.Entry::getKey, e -> ((ParsedLongTerms) e.getValue()).getBuckets().size()));
}

9. 运行与测试


二 使用Spring Boot集成Elasticsearch的更多进阶特性

1. 文档数据处理

在实际应用中,对文档数据的处理常常需要更多的灵活性。我们将学习如何在实体类中使用注解进行更高级的字段映射和设置:

import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Document(indexName = "books", type = "book")
public class Book {

    @Id
    private String id;

    @Field(type = FieldType.Text, analyzer = "standard", fielddata = true)
    private String title;

    @Field(type = FieldType.Keyword)
    private String author;

    @Field(type = FieldType.Keyword)
    private String genre;

    // 其他字段和方法
}

在上述例子中,我们使用了@Field注解进行更精细的字段类型设置和分词配置。

2. 脚本查询

Elasticsearch允许使用脚本进行查询,这在某些复杂的业务逻辑下非常有用。我们将学习如何使用脚本进行查询:

@GetMapping("/searchWithScript")
public List<Book> searchWithScript(@RequestParam String script) {
    NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.scriptQuery(new Script(script)))
            .build();
    return elasticsearchRestTemplate.search(searchQuery, Book.class).stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());
}

在上述例子中,我们通过Script对象构建了一个脚本查询,并使用NativeSearchQuery进行执行。

3. 性能优化 - Bulk 操作

当需要批量操作大量文档时,使用Bulk操作可以显著提高性能。我们将学习如何使用Bulk操作:

public void bulkIndexBooks(List<Book> books) {
    List<IndexQuery> indexQueries = books.stream()
            .map(book -> new IndexQueryBuilder()
                    .withObject(book)
                    .build())
            .collect(Collectors.toList());

    elasticsearchRestTemplate.bulkIndex(indexQueries);
    elasticsearchRestTemplate.refresh(Book.class);
}

在上述例子中,我们通过bulkIndex方法批量索引图书,并使用refresh方法刷新索引。

4. 高级用法 - Highlight

在搜索结果中高亮显示关键字是提高用户体验的一种方式。我们将学习如何在查询中使用Highlight:

public List<Book> searchBooksWithHighlight(String keyword) {
    QueryStringQueryBuilder query = QueryBuilders.queryStringQuery(keyword);
    HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title")
            .preTags("<span style='background-color:yellow'>")
            .postTags("</span>");

    NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(query)
            .withHighlightFields(highlightTitle)
            .build();

    SearchHits<Book> searchHits = elasticsearchRestTemplate.search(searchQuery, Book.class);
    return searchHits.stream()
            .map(searchHit -> {
                Book book = searchHit.getContent();
                Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
                if (highlightFields.containsKey("title")) {
                    book.setTitle(String.join(" ", highlightFields.get("title")));
                }
                return book;
            })
            .collect(Collectors.toList());
}

在上述例子中,我们通过HighlightBuilder设置了对title字段的高亮显示,然后在查询中使用了withHighlightFields方法。

5. 进阶用法 - SearchTemplate

Elasticsearch提供了SearchTemplate功能,允许使用模板进行更灵活的查询。我们将学习如何使用SearchTemplate:

public List<Book> searchBooksWithTemplate(String genre) {
    Map<String, Object> params = Collections.singletonMap("genre", genre);
    String script = "{\"query\":{\"match\":{\"genre\":\"{{genre}}\"}}}";

    SearchResponse response = elasticsearchRestTemplate.query(searchRequest -> {
        searchRequest
                .setScript(new Script(ScriptType.INLINE, "mustache", script, params))
                .setIndices("books")
                .setTypes("book");
    }, SearchResponse.class);

    return Arrays.stream(response.getHits().getHits())
            .map(hit -> elasticsearchRestTemplate.getConverter().read(Book.class, hit))
            .collect(Collectors.toList());
}

在上述例子中,我们通过SearchTemplate使用了一个简单的Mustache模板进行查询。


高级使用篇

Elasticsearch常见的高级使用篇

在一部分中,我们将深入讨论Elasticsearch的一些常见的高级使用技巧,包括聚合、地理空间搜索、模糊查询、索引别名等。

1. 聚合(Aggregation)

聚合是Elasticsearch中一项强大的功能,它允许对数据集进行复杂的数据分析和汇总。以下是一些常见的聚合类型:

1.1 桶聚合(Bucket Aggregation)

桶聚合将文档分配到不同的桶中,然后对每个桶进行聚合计算。

GET /my_index/_search
{
  "size": 0,
  "aggs": {
    "categories": {
      "terms": {
        "field": "category.keyword"
      }
    }
  }
}

上述例子中,通过桶聚合统计了每个类别的文档数量。

1.2 指标聚合(Metric Aggregation)

指标聚合计算某个字段的统计指标,比如平均值、最大值、最小值等。

GET /my_index/_search
{
  "size": 0,
  "aggs": {
    "average_price": {
      "avg": {
        "field": "price"
      }
    }
  }
}

上述例子中,通过指标聚合计算了字段"price"的平均值。

2. 地理空间搜索

Elasticsearch提供了强大的地理空间搜索功能,支持地理点、地理形状等多种地理数据类型。

2.1 地理点搜索
GET /my_geo_index/_search
{
  "query": {
    "geo_distance": {
      "distance": "10km",
      "location": {
        "lat": 40,
        "lon": -70
      }
    }
  }
}

上述例子中,通过地理点搜索找到距离指定坐标(纬度40,经度-70)10公里范围内的文档。

2.2 地理形状搜索
GET /my_geo_shape_index/_search
{
  "query": {
    "geo_shape": {
      "location": {
        "shape": {
          "type": "envelope",
          "coordinates": [[-74.1,40.73], [-73.9,40.85]]
        },
        "relation": "within"
      }
    }
  }
}

上述例子中,通过地理形状搜索找到在指定矩形区域内的文档。

3. 模糊查询

Elasticsearch支持多种模糊查询,包括通配符查询、模糊查询、近似查询等。

3.1 通配符查询
GET /my_index/_search
{
  "query": {
    "wildcard": {
      "name": "el*"
    }
  }
}

上述例子中,通过通配符查询找到名字以"el"开头的文档。

3.2 模糊查询
GET /my_index/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "elastic",
        "fuzziness": "AUTO"
      }
    }
  }
}

上述例子中,通过模糊查询找到与"elastic"相似的文档。

4. 索引别名

索引别名是一个指向一个或多个索引的虚拟索引名称,它可以用于简化查询、切换索引版本、重命名索引等操作。

POST /_aliases
{
  "actions": [
    {
      "add": {
        "index": "new_index",
        "alias": "my_alias"
      }
    }
  ]
}

上述例子中,创建了一个别名"my_alias"指向索引"new_index"。

5. 深度分页

当需要深度分页时,常规的fromsize可能会导致性能问题。这时可以使用search_after进行优化。

GET /my_index/_search
{
  "size": 10,
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "date": {
        "order": "asc"
      }
    }
  ]
}

上述例子中,通过search_after分页查询,可以避免使用fromsize导致的性能问题。

结语

通过这篇高级使用篇博客,我们详细介绍了如何使用Spring Boot集成Elasticsearch,包括添加依赖、配置连接、创建实体类和Repository接口、编写Service以及使用示例。我们深入了解了Elasticsearch的一些高级功能,包括聚合、地理空间搜索、模糊查询、索引别名等。这些技巧将有助于你更灵活、高效地处理各种复杂的数据查询和分析任务。希望这些内容对你在实际项目中的应用有所帮助。感谢阅读!文章来源地址https://www.toymoban.com/news/detail-805008.html

到了这里,关于使用Spring Boot集成中间件:Elasticsearch基础->提高篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring boot 项目中搭建 ElasticSearch 中间件 一 spring data 操作 es

    作者: 逍遥Sean 简介:一个主修Java的Web网站游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言! 本文是进行ElasticSearch 的环境准备和基础操作(使用postman),并且已经能够使用java api操作

    2024年02月10日
    浏览(32)
  • spring boot 项目中搭建 ElasticSearch 中间件 一 postman 操作 es

    作者: 逍遥Sean 简介:一个主修Java的Web网站游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言! 本文是ElasticSearch 的入门文章,包含ElasticSearch 的环境准备和基础操作(使用postman) Elas

    2024年02月11日
    浏览(27)
  • 基于 Docker 的 Spring Boot 项目部署演示,其中使用了 Redis、MySQL 和 RabbitMQ 中间件

    这是一个基于 Docker 的 Spring Boot 项目部署演示,其中使用了 Redis、MySQL 和 RabbitMQ 中间件。 拉取 MySQL 镜像: 创建 MySQL 容器: 将 密码 、 数据库名 、 用户名 和 密码 替换为您自己的值。 拉取 Redis 镜像: 创建 Redis 容器: 拉取 RabbitMQ 镜像: 创建 RabbitMQ 容器: 构建和运行

    2024年02月06日
    浏览(46)
  • Spring Boot 接入 KMS 托管中间件密码&第三方接口密钥

    Nacos中关于中间件的密码,还有第三方API的密钥等信息,都是明文存储,不符合系统安全要求。现需对这些信息进行加密处理,Nacos只存储密文,并在服务启动时,调用云厂商的KMS接口进行解密,将解密后的明文存储在内存中供服务后续使用。 业界上已有 jasypt 组件可以很好地

    2024年01月22日
    浏览(44)
  • 实战:Spring Cloud Stream集成兼容多消息中间件kafka、rabbitmq

    前面的博文我们介绍并实战演示了Spring Cloud Stream整合rabbitmq,其中主要介绍了如何使用和配置完成消息中间件的集成。但是,在实际的生产环境中可能会用到多个消息中间件,又或者是由于业务改变需要更换消息中间件,在这些情况下我们的Spring Cloud Stream框架可以完全兼容多

    2024年02月08日
    浏览(39)
  • 【中间件】ElasticSearch:ES的基本概念与基本使用

    Index索引、Type类型,类似于数据库中的数据库和表,我们说,ES的数据存储在某个索引的某个类型中(某个数据库的某个表中),Document文档(JSON格式),相当于是数据库中内容的存储方式 MySQL:数据库、表、数据 ElasticSearch:索引、类型、文档 ElasticSearch的检索功能基于其倒

    2024年02月04日
    浏览(36)
  • 远程方法调用中间件Dubbo在spring项目中的使用

    作者: 逍遥Sean 简介:一个主修Java的Web网站游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言! Dubbo是一个高性能分布式服务的Java RPC框架,它可以可以帮助实现不同应用之间的远程调用

    2024年02月10日
    浏览(30)
  • 【开发】中间件——ElasticSearch

    ElasticSearch是一个基于Lucene的搜索服务器。提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口 ElasticSearch是一个基于Lucene的搜索服务器。提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口 ElasticSearch是用JAVA开发的。达到实时搜索,稳定可靠,快速,

    2024年02月17日
    浏览(44)
  • Java中间件-Elasticsearch

    Elasticsearch 是一个非常强大的搜索引擎。它目前被广泛地使用于各个 IT 公司。Elasticsearch 是由 Elastic 公司创建。它的代码位于 GitHub - elastic/elasticsearch: Free and Open, Distributed, RESTful Search Engine。目前,Elasticsearch 是一个免费及开放(free and open)的项目。同时,Elastic 公司也拥有

    2023年04月27日
    浏览(36)
  • ES(Elasticsearch)中间件

    文章目录 配置连接ES 全文搜索引擎 全文搜索引擎就是通过从互联网上提取的各个网站的信息(以网页文字为主)而建立的数据库中,检索与用户查询条件匹配的相关记录,然后按一定的排列顺序将结果返回给用户。 官网地址: 链接:

    2024年02月11日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包