ElasticSearch 学习笔记总结(二)

一、ES JavaAPI 环境准备

第一步:创建maven项目,引入相关依赖。

<!-- elasticsearch的核心依赖 -->
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.8.0</version>
</dependency>
<!-- elasticsearch的客户端 high-level另外一种组件。 -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.8.0</version>
</dependency>
<!-- elasticsearch依赖2.x的log4j -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.8.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.8.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.9</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

第二步:构建相关API客户端。

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

public class ESTest_Client {

    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );
        // 关闭ES客户端
        restHighLevelClient.close();
    }

}

二、ES JavaAPI 索引

1. 索引 创建

http://127.0.0.1:9200/_cat/indices?v 测试使用

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

public class ESTest_Client {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1",9200,"http"))
        );
        // 创建索引
        CreateIndexRequest request = new CreateIndexRequest("user1");
        CreateIndexResponse createIndexResponse = esClient.indices().create(request, RequestOptions.DEFAULT);
        // 响应状态
        boolean acknowledged = createIndexResponse.isAcknowledged();
        System.out.println("索引操作:" + acknowledged);
        // 关闭ES客户端
        esClient.close();
    }
}

2. 索引 查找

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;

public class ESTest_Client_Search {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1",9200,"http"))
        );
        // 查询索引
        GetIndexRequest request = new GetIndexRequest("user1");
        GetIndexResponse getIndexResponse = esClient.indices().get(request, RequestOptions.DEFAULT);
        // 响应状态
        System.out.println(getIndexResponse.getAliases());
        System.out.println(getIndexResponse.getMappings());
        System.out.println(getIndexResponse.getSettings());
        // 关闭ES客户端
        esClient.close();
    }
}

3. 索引 删除

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;

public class ESTest_Client_Delete {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1",9200,"http"))
        );
        // 删除索引
        DeleteIndexRequest request = new DeleteIndexRequest("user");
        AcknowledgedResponse delete = esClient.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println("响应是否成功" + delete.isAcknowledged());
        // 关闭ES客户端
        esClient.close();
    }
}

三、ES JavaAPI 文档

1. 文档 创建

http://127.0.0.1:9200/user/_doc/1001 测试使用。

package com.itholmes.es.test;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

public class ESTest_Client_Insert {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1",9200,"http"))
        );
        // 插入数据
        IndexRequest request = new IndexRequest();
        request.index("user").id("1001");
        User user = new User();
        user.setName("zhangsan");
        user.setAge(30);
        user.setSex("男");

        // 向ES插入数据,必须讲数据转换为JSON格式
        ObjectMapper mapper = new ObjectMapper();
        String userJson = mapper.writeValueAsString(user);

        // 放入数据,并且告诉请求的类型
        request.source(userJson, XContentType.JSON);
        // 查询
        IndexResponse response = esClient.index(request, RequestOptions.DEFAULT);
        // 查看结果 (Shard分片)
        System.out.println(response.getResult());
        // 关闭ES客户端
        esClient.close();
    }
}

2. 文档 修改

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

public class ESTest_Dos_Update {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"))
        );
        // 修改数据
        UpdateRequest request = new UpdateRequest();
        // 哪个索引,哪个id主键
        request.index("user").id("1001");
        request.doc(XContentType.JSON,"sex","女");
        UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);
        System.out.println(response.getResult());
        // 关闭ES客户端
        esClient.close();
    }
}

3. 文档 查询

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

public class ESTest_Dos_Get {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"))
        );
        // 查询文档
        GetRequest request = new GetRequest();
        request.index("user").id("1001");
        GetResponse response = esClient.get(request, RequestOptions.DEFAULT);
        System.out.println(response.getSourceAsString());
        // 关闭ES客户端
        esClient.close();
    }
}

4. 文档 删除

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

public class ESTest_Dos_Delete {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"))
        );
        DeleteRequest request = new DeleteRequest();
        request.index("user").id("1001");
        // 删除文档
        DeleteResponse delete = esClient.delete(request, RequestOptions.DEFAULT);
        System.out.println(delete.toString());
        // 关闭ES客户端
        esClient.close();
    }
}

4. 文档 批量新增 和 批量删除

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;

public class ESTest_Client_Insert_Batch {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1",9200,"http"))
        );
        // 文档 批量新增
        BulkRequest request = new BulkRequest();
        request.add(new IndexRequest().index("user").id("1001").source(XContentType.JSON,"name","zhangsan"));
        request.add(new IndexRequest().index("user").id("1002").source(XContentType.JSON,"name","lisi"));
        request.add(new IndexRequest().index("user").id("1003").source(XContentType.JSON,"name","wangwu"));
        BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);
        System.out.println(response.getTook()); // 执行时长
        System.out.println(response.getItems());
        // 关闭ES客户端
        esClient.close();
    }
}
package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

public class ESTest_Dos_Delete_Batch {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"))
        );
        // 文档 批量删除
        BulkRequest request = new BulkRequest();
        request.add(new DeleteRequest().index("user").id("1001"));
        request.add(new DeleteRequest().index("user").id("1002"));
        request.add(new DeleteRequest().index("user").id("1003"));
        BulkResponse bulk = esClient.bulk(request, RequestOptions.DEFAULT);
        System.out.println(bulk.getTook());
        System.out.println(bulk.getItems());
        // 关闭ES客户端
        esClient.close();
    }
}

5. 高级查询 索引全量查询

查询某索引下的全部内容:

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;

public class ESTest_Dos_Query {
    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"))
        );
        // 高级查询 全量查询
        SearchRequest request = new SearchRequest();
        request.indices("user");
        // 查询索引中全部的数据
        SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        request.source(query);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        // 最终的结果
        SearchHits hits = response.getHits();
        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        // 关闭ES客户端
        esClient.close();
    }
}

6. 高级查询

总共有:分页查询、条件查询、字段查询、组合查询、范围查询、 聚合查询、分组查询。

package com.itholmes.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.metrics.MaxAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;

public class ESTest_Dos_Query {

    public static void main(String[] args) throws Exception {
        // 创建ES客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"))
        );
        // 1. 条件查询
        // SearchResponse response = condition(esClient);
        // 2. 分页查询
        // SearchResponse response = page(esClient);
        // 3. 排序查询
        // SearchResponse response = sort(esClient);
        // 4. 过滤查询
        // SearchResponse response = filter(esClient);
        // 5. 组合查询
        // SearchResponse response = associate(esClient);
        // 6. 范围查询
        // SearchResponse response = range(esClient);
        // 7. 模糊查询
        // SearchResponse response = like(esClient);
        // 8. 高亮查询
        // SearchResponse response = highlight(esClient);
        // 9. 聚合查询
        // SearchResponse response = aggregate(esClient);
        // 10. 分组查询
        SearchResponse response = group(esClient);
        // 最终的结果
        SearchHits hits = response.getHits();
        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
        // 关闭ES客户端
        esClient.close();
    }

    // 条件查询
    public static SearchResponse condition(RestHighLevelClient esClient) throws Exception {
        // 高级查询
        SearchRequest request = new SearchRequest();
        request.indices("user");
        // termQuery 进行条件查询
        SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.termQuery("age", 30));
        request.source(query);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        return response;
    }

    // 分页查询
    public static SearchResponse page(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        // builder设置分页
        SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.termQuery("age", 30));
        // 分页算法: 起始位置 = (当前页码 - 1) * 每页显示数据条数
        builder.from(2); // 起始位置
        builder.size(2); // 每页多少条
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        return response;
    }

    // 查询排序
    public static SearchResponse sort(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        // builder设置分页
        SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        builder.sort("age", SortOrder.DESC);
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        return response;
    }

    // 查询过滤
    public static SearchResponse filter(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        // builder设置分页
        SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        // 包含,不包含
        String[] excludes = {};
        String[] includes = {"name"};
        builder.fetchSource(excludes, includes);
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        return response;
    }

    // 组合查询
    public static SearchResponse associate(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        // builder 组合查询
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 满足的条件 must就是必须
        // boolQueryBuilder.must(QueryBuilders.matchQuery("age",30));
        // boolQueryBuilder.mustNot(QueryBuilders.matchQuery("sex","男"));
        // should 可以理解为or的效果
        boolQueryBuilder.should(QueryBuilders.matchQuery("age", 30));
        boolQueryBuilder.should(QueryBuilders.matchQuery("age", 100));
        builder.query(boolQueryBuilder);
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        return response;
    }

    // 范围查询
    public static SearchResponse range(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");
        rangeQuery.gte(30); // gte 大于等于
        rangeQuery.lte(90); // lte 小于等于
        builder.query(rangeQuery);
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        return response;
    }

    // 模糊查询
    public static SearchResponse like(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 模糊查询 fuzziness 英文直译:模糊度,Fuzziness.ONE代表差异1个字符也可以查询出来。
        FuzzyQueryBuilder fuzziness = QueryBuilders.fuzzyQuery("name", "wangwu").fuzziness(Fuzziness.ONE);
        builder.query(fuzziness);
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        return response;
    }

    // 高亮查询
    public static SearchResponse highlight(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "zhangsan");
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        // 添加标签
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        // 指定name属性高亮效果。
        highlightBuilder.field("name");
        builder.highlighter(highlightBuilder);
        builder.query(termQueryBuilder);
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        // 高亮显示是对应的highlight的属性。
        return response;
    }

    // 聚合查询
    public static SearchResponse aggregate(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 聚合查询 取age的最大值
        MaxAggregationBuilder field = AggregationBuilders.max("maxAge").field("age");
        builder.aggregation(field);
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        // 同样聚合查询也要特定的属性才获取到。
        return response;
    }

    // 分组查询
    public static SearchResponse group(RestHighLevelClient esClient) throws Exception {
        SearchRequest request = new SearchRequest();
        request.indices("user");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 分组查询 根据age年龄进行分组
        AggregationBuilder field = AggregationBuilders.terms("ageGroup").field("age");
        builder.aggregation(field);
        request.source(builder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        // 同样分组查询也要特定的属性才获取到。
        return response;
    }

}

四、ES 集群

1. ES集群 概念

概念:
在这里插入图片描述

ES目录介绍:

  • data目录:存放相关的数据,如果删除了数据就没了。
  • logs目录:存放日志,如果删除了日志就没了。

2. window 集群搭建

第一步:配置第一个节点。

配置elasticsearch.yml文件:

  • 集群的名称一定保持一致。
  • 节点名字在集群当中,必须保持唯一。
# 集群名称 保持一致。
cluster.name: my-application
# 节点名字
node.name: node-1002
node.master: true
node.data: true
# 网络外网配置
network.host: localhost
# http协议端口
http.port: 1002
# 传输协议
transport.tcp.port: 9301

# 配置开宇
http.cors.enabled: true
http.cors.allow-origin: "*"

在这里插入图片描述
在这里插入图片描述

集群状态查询:

# get方法
http://localhost:1001/_cluster/health 

第二步:配置第二个节点。

  • 需要在elasticsearch.yml文件中,添加配置,配置到第一个节点上。(其实是发现服务的效果)。
# 其他配置node.name http.port transport.tcp.port 端口 都不能相同!
# 配置注册发现效果
discovery.seed_hosts: ["localhost:9301"] # 相当于取找9301这个节点。
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5

第三步:配置第三个节点。

discovery.seed_hosts: ["localhost:9301","localhost:9302"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5

3. linux 单点安装ES

官方下载,linux包解压。

因为安全问题,ES不允许root用户直接运行,所以要创建新用户。

useradd es
passwd es
chown -R es:es /opt/elasticsearch/elasticsearch-7.8.0

添加配置如下:

cluster.name: my-application
node.name: node-1
network.host: 0.0.0.0
http.port: 9200
# 配置node-1为主节点
cluster.initial_master_nodes: ["node-1"]

因为linux系统有文件限制之类的,所以为了防止这种类似错误的发生配置如下操作:

配置limits.conf:

# 配置limits.conf
vi /etc/security/limits.conf

配置如下:

# 在limits.conf文件末尾添加
# 针对es用户 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536

配置20-nproc.conf:

# 配置20-nproc.conf
vi /etc/security/limits.d/20-nproc.conf
# 针对es用户 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536
* hard nproc 4096

修改sysctl.conf 文件:

# 修改sysctl.conf 文件
vi /etc/sysctl.conf 
vm.max_map_count=655360

最后,切换到创建的用户es,并且在bin目录下启动即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xupengboo

你的鼓励将是我创作最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值