所有代码均为参考官方文档:官方文档
原文说明
Java 高级 REST 客户端在 Java 低级 REST 客户端之上工作。它的主要目标是公开 API 特定的方法,这些方法接受请求对象作为参数并返回响应对象,以便由客户端自己处理请求编组和响应解组。
每个 API都可以同步或异步调用。同步方法返回一个响应对象,而名称以async后缀结尾的异步方法需要一个侦听器参数,一旦收到响应或错误,就会通知该侦听器参数(在低级客户端管理的线程池上)。
Java High Level REST Client 依赖于 Elasticsearch 核心项目。它接受与相同的请求参数TransportClient并返回相同的响应对象。
java API 文档:JAVA doc 低版本的:Java REST Client 高版本的:Elasticsearch Java API Client
注意安装版本要与客户端引入依赖保持一致,否则会出现版本问题
高版本的初始化方式与低版本的不一样,建议参考对应版本的文档
高版本的依赖会出现一部分jakarta.json加载不到,可引入下面依赖来解决
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>jakarta.json</artifactId>
<version>1.0.0</version>
</dependency>
Elasticsearch Maven
# 所需的最低 Java 版本是1.8
# 所需依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.7.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.7.2</version>
</dependency>
初始化客户端
package com.wdz.es.config.es;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ElasticsearchConfig {
@Value("${elasticsearch.hosts}")
private String hosts;
@Value("${elasticsearch.username}")
private String username;
@Value("${elasticsearch.password}")
private String password;
/**
* 有密码初始化
*
* @return
*/
@Bean(destroyMethod = "close")
public RestHighLevelClient restHighLevelClient() {
// 设置密码
BasicCredentialsProvider provider = new BasicCredentialsProvider();
provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(
RestClient.builder(setHost()).setHttpClientConfigCallback(
new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
httpAsyncClientBuilder.disableAuthCaching();
return httpAsyncClientBuilder.setDefaultCredentialsProvider(provider);
}
}
));
return restHighLevelClient;
}
/**
* 无密码初始化
* @return
*/
@Bean(destroyMethod = "close")
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(setHost()));
return restHighLevelClient;
}
private HttpHost[] setHost(){
String[] split = hosts.split(",");
HttpHost[] hhs = new HttpHost[split.length];
for (int i = 0; i < split.length; i++) {
String host = split[i];
String[] ht = host.split(":");
hhs[i] = new HttpHost(ht[0], Integer.parseInt(ht[1]), "http");
}
return hhs;
}
}
参数hosts可以多个用户逗号分隔,在代码中进行解析,格式:ip:port
校验和创建索引
/**
* 校验索引是否存在,如果不存在进行创建
*/
private boolean checkCreate(String index) throws IOException {
GetIndexRequest request = new GetIndexRequest(index);
boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
if (!exists) {
CreateIndexRequest create = new CreateIndexRequest(index);
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(create, RequestOptions.DEFAULT);
System.out.println(JSONObject.toJSONString(createIndexResponse));
}
return exists;
}
// 该方法可以放在业务实现类中,在服务启动时校验一次
@PostConstruct
public void checkCreate(){
// 索引参数,相当于数据库中的一张表
String index = "edu-app-user";
GetIndexRequest request = new GetIndexRequest(index);
try {
boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
if (!exists) {
CreateIndexRequest create = new CreateIndexRequest(index);
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(create, RequestOptions.DEFAULT);
System.out.println(JSONObject.toJSONString(createIndexResponse));
}
} catch (IOException e) {
e.printStackTrace();
}
}
同步添加数据
为了方便调试,所有接口使用get方式
# 方式一:使用map方式进行添加数据,推荐使用
@GetMapping("add")
public IndexResponse add(String id, String name, String mobile, Integer age) {
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("id", id);
jsonMap.put("name", name);
jsonMap.put("mobile", mobile);
jsonMap.put("age", age);
// 参数1: 索引,同一个文档(或者说数据库中的表名)唯一,
// 参数2:文档类型,在高版本中已经优化,可不需要该参数,
// 参数3:id,内部id参数值,也可默认,该参数是String类型
IndexRequest request = new IndexRequest("edu-app-user", "doc", id).source(jsonMap);
// 选填数据
request.opType(DocWriteRequest.OpType.CREATE);
IndexResponse response = null;
try {
// 校验索引是否存在,否则
checkCreate("edu-app-user");
// 执行添加,默认的请求操作方式
response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
# 方式二 拼接json方式,该方式不推荐使用,容易出错
@GetMapping("add2")
public IndexResponse add2(String id, String name, String mobile, Integer age) {
IndexRequest request = new IndexRequest("edu-app-user", "doc", id);
String jsonString = "{" +
"\"id\":" + id + "," +
"\"name\":" + name + "," +
"\"mobile\":" + mobile + "," +
"\"age\":" + age +
"}";
request.source(jsonString, XContentType.JSON.mediaType());
IndexResponse response = null;
try {
response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
# XContentType 中定义多种类型,默认是XContentType.JSON = "application/json",会出现编码问题
# 方式三 推荐使用,更简洁易读
@GetMapping("add3")
public IndexResponse add3(String id, String name, String mobile, Integer age) throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("id", id);
builder.field("name", name);
builder.field("mobile", mobile);
builder.timeField("updateTime", new Date());
builder.field("age", age);
}
builder.endObject();
IndexRequest request = new IndexRequest("edu-app-user", "doc", id);
request.source(builder);
IndexResponse response = null;
try {
response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
# 方式四:直接在request.source()中进行参数操作
@GetMapping("add4")
public IndexResponse add4(String id, String name, String mobile, Integer age) {
IndexRequest request = new IndexRequest("edu-app-user", "doc", id)
.source("id", id,
"name", name,
"age", age,
"mobile", mobile);
IndexResponse response = null;
try {
response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
# 其他可选方法
# 过期时间指定,两种方式
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
# 刷新策略
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
request.setRefreshPolicy("wait_for");
异步添加数据
同步与异步区别是方法上:(springboot 中的es版本和显式引入的依赖会出现冲突问题,直接显式定义es版本即可解决)
<properties>
<elasticsearch.version>6.7.2</elasticsearch.version>
</properties>
@GetMapping("addAsync")
public void addAsync(String id, String name, String mobile, Integer age) {
IndexRequest request = new IndexRequest("edu-app-user", "doc", id)
.source("id", id,
"name", name,
"age", age,
"mobile", mobile);
restHighLevelClient.indexAsync(request, RequestOptions.DEFAULT, new EduAppUserListener());
}
# 监听类
package com.wdz.es.config.es;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.index.IndexResponse;
public class EduAppUserListener implements ActionListener<IndexResponse> {
@Override
public void onResponse(IndexResponse response) {
System.out.println("异步保存成功:"+ response);
}
@Override
public void onFailure(Exception e) {
System.out.println("异步保存失败:"+ e.getMessage());
}
}