irpas技术客

Elasticsearch-Java API_ZHOU_VIP

网络 3780

Java API操作

Elasticsearch软件是由Java语言开发的,所以也可以通过Java API的方式对Elasticsearch

服务进行访问

创建Maven项目

我们在IDEA开发工具中创建Maven项目或者Maven模块

我在service下创建Maven模块

?

pom.xml中增加依赖?

<dependencies> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.8.0</version> </dependency> <!-- elasticsearch的客户端 --> <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> <!-- junit单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>

?


客户端对象

创建com.nanjing.esservice.ESTest_Client类,代码中创建Elasticsearch客户端对象

因为早期版本的客户端对象已经不再推荐使用,且在未来版本中会被删除,所以这里我们采

用高级REST客户端对象

package com.nanjing.esservice; 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 esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 关闭ES客户端 esClient.close(); } }

索引操作

ES服务器正常启动后,可以通过Java API客户端对象对ES索引进行操作

1) ?创建索引

package com.nanjing.esservice; 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.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; public class ESTest_Index_Create { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 创建索引 CreateIndexRequest request = new CreateIndexRequest("user"); CreateIndexResponse createIndexResponse = esClient.indices().create(request, RequestOptions.DEFAULT); // 响应状态 boolean acknowledged = createIndexResponse.isAcknowledged(); System.out.println("索引操作 :" + acknowledged); esClient.close(); } }

2) ?查看索引

package com.nanjing.esservice; 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_Index_Search { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 查询索引 GetIndexRequest request = new GetIndexRequest("user"); GetIndexResponse getIndexResponse = esClient.indices().get(request, RequestOptions.DEFAULT); // 响应状态 System.out.println(getIndexResponse.getAliases()); System.out.println(getIndexResponse.getMappings()); System.out.println(getIndexResponse.getSettings()); esClient.close(); } }

3) ?删除索引

package com.nanjing.esservice; import org.apache.http.HttpHost; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; public class ESTest_Index_Delete { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 查询索引 DeleteIndexRequest request = new DeleteIndexRequest("user"); AcknowledgedResponse response = esClient.indices().delete(request, RequestOptions.DEFAULT); // 响应状态 System.out.println(response.isAcknowledged()); esClient.close(); } }

文档操作

1) ?新增文档

创建数据模型

package com.nanjing.esservice; public class User { private String name; private String sex; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }

创建数据,添加到文档中

package com.nanjing.esservice; 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_Doc_Insert { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 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); System.out.println(response.getResult()); esClient.close(); } }

2) ?修改文档?

package com.nanjing.esservice; 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_Doc_Update { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 修改数据 UpdateRequest request = new UpdateRequest(); request.index("user").id("1001"); request.doc(XContentType.JSON, "sex", "女"); UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT); System.out.println(response.getResult()); esClient.close(); } }

3) ?查询文档

package com.nanjing.esservice; 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_Doc_Get { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 查询数据 GetRequest request = new GetRequest(); request.index("user").id("1001"); GetResponse response = esClient.get(request, RequestOptions.DEFAULT); System.out.println(response.getSourceAsString()); esClient.close(); } }

4) ?删除文档

package com.nanjing.esservice; 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_Doc_Delete { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); DeleteRequest request = new DeleteRequest(); request.index("user").id("1001"); DeleteResponse response = esClient.delete(request, RequestOptions.DEFAULT); System.out.println(response.toString()); esClient.close(); } }

5) ?批量操作

package com.nanjing.esservice; 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_Doc_Insert_Batch { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 批量插入数据 BulkRequest request = new BulkRequest(); request.add(new IndexRequest().index("user").id("1001").source(XContentType.JSON, "name", "zhangsan", "age",30,"sex","男")); request.add(new IndexRequest().index("user").id("1002").source(XContentType.JSON, "name", "lisi", "age",30,"sex","女")); request.add(new IndexRequest().index("user").id("1003").source(XContentType.JSON, "name", "wangwu", "age",40,"sex","男")); request.add(new IndexRequest().index("user").id("1004").source(XContentType.JSON, "name", "wangwu1", "age",40,"sex","女")); request.add(new IndexRequest().index("user").id("1005").source(XContentType.JSON, "name", "wangwu2", "age",50,"sex","男")); request.add(new IndexRequest().index("user").id("1006").source(XContentType.JSON, "name", "wangwu3", "age",50,"sex","男")); request.add(new IndexRequest().index("user").id("1007").source(XContentType.JSON, "name", "wangwu44", "age",60,"sex","男")); request.add(new IndexRequest().index("user").id("1008").source(XContentType.JSON, "name", "wangwu555", "age",60,"sex","男")); request.add(new IndexRequest().index("user").id("1009").source(XContentType.JSON, "name", "wangwu66666", "age",60,"sex","男")); BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT); System.out.println(response.getTook()); System.out.println(response.getItems()); esClient.close(); } }

批量删除:

package com.nanjing.esservice; 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.client.RequestOptions; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; public class ESTest_Doc_Delete_Batch { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 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 response = esClient.bulk(request, RequestOptions.DEFAULT); System.out.println(response.getTook()); System.out.println(response.getItems()); esClient.close(); } }


高级查询

1) ?请求体查询

查询所有索引数据

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 1. 查询索引中全部的数据 // 创建搜索请求对象 SearchRequest request = new SearchRequest(); request.indices("zhou"); // 构建查询的请求体 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 查询所有数据 sourceBuilder.query(QueryBuilders.matchAllQuery()); request.source(sourceBuilder); //request.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery())); 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()); } esClient.close();

term查询,查询条件为关键字

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 2. 条件查询 : termQuery SearchRequest request = new SearchRequest(); request.indices("user"); request.source(new SearchSourceBuilder().query(QueryBuilders.termQuery("age", 30))); 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()); } esClient.close();

分页查询

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 3. 分页查询 SearchRequest request = new SearchRequest(); request.indices("zhou"); SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()); // (当前页码-1)*每页显示数据条数 builder.from(2); builder.size(2); request.source(builder); 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()); } esClient.close();

数据排序

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 4. 查询排序 SearchRequest request = new SearchRequest(); request.indices("zhou"); SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()); builder.sort("age", SortOrder.DESC); request.source(builder); 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()); } esClient.close();

过滤字段

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 5. 过滤字段 SearchRequest request = new SearchRequest(); request.indices("user"); SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()); String[] excludes = {"age"}; String[] includes = {}; builder.fetchSource(includes, excludes); request.source(builder); 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()); } esClient.close();

Bool组合查询

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 6. 组合查询 SearchRequest request = new SearchRequest(); request.indices("zhou"); SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); // 必须包含 boolQueryBuilder.must(QueryBuilders.matchQuery("age", 30)); boolQueryBuilder.must(QueryBuilders.matchQuery("sex", "男")); // 一定不含 //boolQueryBuilder.mustNot(QueryBuilders.matchQuery("sex", "男")); // 可能包含 boolQueryBuilder.should(QueryBuilders.matchQuery("age", 30)); boolQueryBuilder.should(QueryBuilders.matchQuery("age", 40)); builder.query(boolQueryBuilder); request.source(builder); 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()); } esClient.close();

范围查询

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 7. 范围查询 SearchRequest request = new SearchRequest(); request.indices("zhou"); SearchSourceBuilder builder = new SearchSourceBuilder(); RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age"); // 大于等于 rangeQuery.gte(30); // 小于等于 rangeQuery.lt(50); builder.query(rangeQuery); request.source(builder); 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()); } esClient.close();

模糊查询

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 8. 模糊查询 SearchRequest request = new SearchRequest(); request.indices("zhou"); SearchSourceBuilder builder = new SearchSourceBuilder(); builder.query(QueryBuilders.fuzzyQuery("name", "zhangsan").fuzziness(Fuzziness.TWO)); request.source(builder); 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()); } esClient.close();

高亮查询

RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 9. 高亮查询 SearchRequest request = new SearchRequest(); request.indices("zhou"); //创建查询请求体构建器 SearchSourceBuilder builder = new SearchSourceBuilder(); //构建查询方式:高亮查询 TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("name", "zhangsan"); //构建高亮字段 HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.preTags("<font color='red'>");//设置标签前缀 highlightBuilder.postTags("</font>");//设置标签后缀 highlightBuilder.field("name");//设置高亮字段 //设置高亮构建对象 builder.highlighter(highlightBuilder); builder.query(termsQueryBuilder); //设置请求体 request.source(builder); //客户端发送请求,获取响应对象 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()); } esClient.close();


聚合查询

最大年龄

package com.nanjing.esservice; 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.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.metrics.Max; import org.elasticsearch.search.builder.SearchSourceBuilder; public class ESTest_Doc_Query { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); SearchRequest request = new SearchRequest(); request.indices("zhou"); SearchSourceBuilder builder = new SearchSourceBuilder(); AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age"); builder.aggregation(aggregationBuilder); request.source(builder); SearchResponse response = esClient.search(request, RequestOptions.DEFAULT); Max max = response.getAggregations().get("maxAge"); System.out.println(max.getValue());//打印50 /*并不能查出最大值50,遂注掉 SearchHits hits = response.getHits(); System.out.println(hits.getTotalHits()); System.out.println(response.getTook()); for ( SearchHit hit : hits ) { System.out.println(hit.getSourceAsString()); }*/ esClient.close(); } }

ElasticSearch:Aggregation聚合查询的入门与进阶_风萧萧1999的博客-CSDN博客_aggregation聚合查询

ElasticSearch在Java中的高级应用1_奔腾游子的博客-CSDN博客

ElasticSearch:Aggregation聚合查询的入门与进阶_风萧萧1999的博客-CSDN博客_aggregation聚合查询

es 7.x JavaAPI 文档 最大值查询 分组查询_java持续实践的博客-CSDN博客_es java分组查询

package com.nanjing.esservice; 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.search.SearchHits; import org.elasticsearch.search.aggregations.Aggregation; import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.Aggregations; import org.elasticsearch.search.aggregations.metrics.ParsedMax; import org.elasticsearch.search.builder.SearchSourceBuilder; public class ESTest_Doc_Query { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); SearchRequest request = new SearchRequest(); request.indices("zhou"); SearchSourceBuilder builder = new SearchSourceBuilder(); AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age"); builder.aggregation(aggregationBuilder); request.source(builder); SearchResponse response = esClient.search(request, RequestOptions.DEFAULT); // 查询命中的信息 SearchHits hits = response.getHits(); System.out.println(hits.getTotalHits()); System.out.println(response.getTook()); Aggregations aggregations = response.getAggregations(); for (Aggregation aggregation : aggregations) { System.out.println("aggregationName: " + aggregation.getName() + " value: " + ((ParsedMax) aggregation).value()); } esClient.close(); } }


分组统计

AggregationBuilders.terms("name").field("id");

其中name值自定义,id为需要分组的key

package com.nanjing.esservice; 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.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.builder.SearchSourceBuilder; public class ESTest_Doc_Query { public static void main(String[] args) throws Exception { RestHighLevelClient esClient = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 11. 分组查询 SearchRequest request = new SearchRequest(); request.indices("zhou"); SearchSourceBuilder builder = new SearchSourceBuilder(); AggregationBuilder aggregationBuilder = AggregationBuilders.terms("ageGroup").field("age"); builder.aggregation(aggregationBuilder); request.source(builder); SearchResponse response = esClient.search(request, RequestOptions.DEFAULT); Terms aggregation = response.getAggregations().get("ageGroup"); for (Terms.Bucket bucket : aggregation.getBuckets()) { System.out.println("key=" + bucket.getKey() + ";数量=" + bucket.getDocCount()); } /*SearchHits hits = response.getHits(); System.out.println(hits.getTotalHits()); System.out.println(response.getTook()); for ( SearchHit hit : hits ) { System.out.println(hit.getSourceAsString()); }*/ esClient.close(); } }

?ElasticSearch查询之Aggregation - 南极山 - 博客园


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #API #JAVA