使用Java客户端操作elasticsearch

时间:2022-12-18 15:50:37

Java REST客户端有两种风格:

Java低级别REST客户端(Java Low Level REST Client,以后都简称低级客户端算了,难得码字):Elasticsearch的官方low-level客户端。 它允许通过http与Elasticsearch集群进行通信。 不会对请求进行编码和响应解码。 它与所有Elasticsearch版本兼容。
Java高级REST客户端(Java High Level REST Client,以后都简称高级客户端):Elasticsearch的官方high-level客户端。 基于low-level客户端,它公开了API特定的方法,并负责处理。

低级客户端 的功能包括:

  • 依赖最小
  • 所有可用节点,会负载平衡
  • 在节点故障和响应特定状态码的情况下会进行故障转移
  • 连接失败会进行处罚(失败的节点是否重试,取决于连续失败的次数,失败次数越多,客户端等待的时间越长)
  • 持久连接
  • 跟踪记录请求和响应的日志
  • 可选的自动发现群集节点

低级客户端 快速入门

Java API文档在这里可以找到。低级客户端托管在Maven Central上。所需的最低Java版本是1.7。低级客户端与Elasticsearch的发布周期相同。发布的第一个版本为5.0.0-alpha4。客户端版本和与之通信的Elasticsearch版本没有任何关系,可以替换客户端版本为你想要的任何版本。低级客户端与所有Elasticsearch版本兼容。

Maven Repository

Maven 配置

下面是使用maven作为依赖管理器配置依赖项。 将以下内容添加到您的pom.xml文件中:

<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.2.3</version>
</dependency>

Gradle 配置

下面是使用gradle作为依赖项管理器来配置依赖项。在您的build.gradle中添加以下内容:

dependencies {
compile 'org.elasticsearch.client:elasticsearch-rest-client:6.2.3'
}

Dependencies

低级客户端在内部使用Apache Http Async Client发送http请求。 它依赖于以下部件,即the async http client及其自身的传递依赖:

  • org.apache.httpcomponents:httpasyncclient
  • org.apache.httpcomponents:httpcore-nio
  • org.apache.httpcomponents:httpclient
  • org.apache.httpcomponents:httpcore
  • commons-codec:commons-codec
  • commons-logging:commons-logging

Shading

为了避免版本冲突,依赖需要shaded(翻译为被隐藏不知合不合理)和打包到一个单独的jar文件中。(该操作也被称作"uber JAR"或"fat JAR",是一种可执行的Jar包。FatJar和普通的jar不同在于它包含了依赖的jar包。)
对依赖进行隐藏需要取其内容(资源文件和java类文件),然后在放到jar文件之前会对一些包进行重命名。该操作可以使用第三方的插件,比如Gradle 和 Maven来完成。感兴趣的参照这儿。

请注意,隐藏一个JAR也是有缺点的。 例如,隐藏 Commons Logging 层,意味着也需要对依赖的第三方日志进行隐藏。

Maven 配置

下面是使用Maven Shade插件的配置。将以下内容添加到您的pom中。

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<relocations>
<relocation>
<pattern>org.apache.http</pattern>
<shadedPattern>hidden.org.apache.http</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.logging</pattern>
<shadedPattern>hidden.org.apache.logging</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.commons.codec</pattern>
<shadedPattern>hidden.org.apache.commons.codec</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.commons.logging</pattern>
<shadedPattern>hidden.org.apache.commons.logging</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Gradle 配置

下面是使用Gradle ShadowJar插件的配置。在您的 build.gradle 中添加以下内容。

shadowJar {
relocate 'org.apache.http', 'hidden.org.apache.http'
relocate 'org.apache.logging', 'hidden.org.apache.logging'
relocate 'org.apache.commons.codec', 'hidden.org.apache.commons.codec'
relocate 'org.apache.commons.logging', 'hidden.org.apache.commons.logging'
}

初始化

RestClient实例可以通过RestClientBuilder类创建,通过RestClient 的 builder(HttpHost ...)静态方法创建。 唯一需要的参数是客户端将与之通信的一个或多个主机,如下所示:

RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")).build();

RestClient类是线程安全的,理想情况下与使用它的应用程序具有相同的生命周期。当不再需要时关闭它是非常重要的,这样它所使用的所有资源以及底层http客户端实例及其线程都可以得到释放。

restClient.close();

RestClientBuilder还允许在构建RestClient实例时可选地设置以下配置参数:

       //配置可选参数
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "http"));
Header[] defaultHeaders = new Header[]{new BasicHeader("header", "value")};
//设置每个请求需要发送的默认headers,这样就不用在每个请求中指定它们。
builder.setDefaultHeaders(defaultHeaders);
// 设置应该授予的超时时间,以防对相同的请求进行多次尝试。默认值是30秒,与默认socket超时时间相同。
// 如果自定义socket超时时间,则应相应地调整最大重试超时时间。
builder.setMaxRetryTimeoutMillis(10000);
builder.setFailureListener(new RestClient.FailureListener() {
@Override
public void onFailure(HttpHost host) {
//设置一个监听程序,每次节点发生故障时都会收到通知,这样就可以采取相应的措施。
//Used internally when sniffing on failure is enabled.(这句话没搞懂啥意思)
}
});
builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
//设置允许修改默认请求配置的回调
// (例如,请求超时,身份验证或org.apache.http.client.config.RequestConfig.Builder允许设置的任何内容)
return requestConfigBuilder.setSocketTimeout(10000);
}
});
builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
//设置允许修改http客户端配置的回调
// (例如,通过SSL的加密通信,或者org.apache.http.impl.nio.client.HttpAsyncClientBuilder允许设置的任何内容)
return httpClientBuilder.setProxy(new HttpHost("proxy", 9000, "http"));
}
});

执行请求

一旦创建了RestClient,就可以调用performRequest或performRequestAsync方法来发送请求。

performRequest方法是同步的,直接返回响应,这意味着客户端将被阻塞并等待响应返回。

performRequestAsync方法返回void,并接受一个ResponseListener作为参数,这意味着它们是异步执行的。当请求完成或失败时,监听器将被通知。

发送同步请求

    //方式1:只提供谓词和终节点,这两个参数是必需要的参数
Response response = restClient.performRequest("GET", "/"); //方式2:提供谓词和终节点以及一些查询字符串参数来发送请求
Map<String, String> params = Collections.singletonMap("pretty", "true");
response = restClient.performRequest("GET", "/", params); //方式3:提供谓词和终节点以及可选查询字符串参数和org.apache.http.HttpEntity对象中包含的请求主体来发送请求
params = Collections.emptyMap();
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
//为HttpEntity指定ContentType非常重要,因为它将用于设置Content-Type请求头,以便Elasticsearch可以正确解析内容。
HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
response = restClient.performRequest("PUT", "/posts/doc/1", params, entity); //方式4:提供谓词,终节点,可选查询字符串参数,可选请求主体
// 以及用于为每个请求尝试创建org.apache.http.nio.protocol.HttpAsyncResponseConsumer回调实例的可选工厂来发送请求。
// 控制响应正文如何从客户端的非阻塞HTTP连接进行流式传输。
// 如果未提供,则使用默认实现,将整个响应主体缓存在堆内存中,最大为100 MB。
params = Collections.emptyMap();
HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory consumerFactory =
new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024);
response = restClient.performRequest("GET", "/posts/_search", params, null, consumerFactory);

发送异步请求

    //方式1: 提供谓词,终节点和响应监听器来发送异步请求,一旦请求完成,就会通知响应监听器,这三个参数是必需要的参数
ResponseListener responseListener = new ResponseListener() {
@Override
public void onSuccess(Response response) {
// 定义请求成功执行时需要做的事情
}
@Override
public void onFailure(Exception exception) {
// 定义请求失败时需要做的事情,即每当发生连接错误或返回错误状态码时做的操作。
}
};
restClient.performRequestAsync("GET", "/", responseListener); //方式2: 提供谓词,终节点,一些查询字符串参数和响应监听器来发送异步请求
Map<String, String> params = Collections.singletonMap("pretty", "true");
restClient.performRequestAsync("GET", "/", params, responseListener); //方式3:提供谓词,终节点,可选查询字符串参数,
// org.apache.http.HttpEntity对象中包含的请求主体以及在请求完成后通知响应侦听器 来发送异步请求
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
NStringEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
restClient.performRequestAsync("PUT", "/posts/doc/1", params, entity, responseListener); //方式4:提供谓词,终节点,可选查询字符串参数,可选请求主体
// 以及用于为每个请求尝试创建org.apache.http.nio.protocol.HttpAsyncResponseConsumer回调实例的可选工厂 来发送异步请求。
// 控制响应正文如何从客户端的非阻塞HTTP连接进行流式传输。
// 如果未提供,则使用默认实现,将整个响应主体缓存在堆内存中,最大为100 MB。
HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory consumerFactory =
new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024);
restClient.performRequestAsync("GET", "/posts/_search", params, null, consumerFactory, responseListener);

接下来是一个发送异步请求的基本示例:

final CountDownLatch latch = new CountDownLatch(documents.length);
for (int i = 0; i < documents.length; i++) {
restClient.performRequestAsync(
"PUT",
"/posts/doc/" + i,
Collections.<String, String>emptyMap(),
//此处假设文档已存在 HttpEntity数组里
documents[i],
new ResponseListener() {
@Override
public void onSuccess(Response response) {
//处理返回的响应内容
latch.countDown();
} @Override
public void onFailure(Exception exception) {
// 由于通信错误或带有指示错误的状态码的响应,用于处理返回的异常
latch.countDown();
}
}
);
}
latch.await();

上面列出的每个方法都支持通过Header 可变参数发送请求头,源码如下:

使用Java客户端操作elasticsearch

一个header时, 如下例所示:

Response response = restClient.performRequest("GET", "/", new BasicHeader("header", "value"));

多个header时,如下所示:

Header[] headers = {
new BasicHeader("header1", "value1"),
new BasicHeader("header2", "value2")
};
restClient.performRequestAsync("GET", "/", responseListener, headers);

获取响应

Response对象(由同步performRequest方法返回或由ResponseListener的onSuccess(Response)中的参数接收),包装从http客户端返回的响应对象并公开一些其他的信息。

 RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")).build();
Response response = restClient.performRequest("GET", "/");
RequestLine requestLine = response.getRequestLine();//关于已执行请求的信息
HttpHost host = response.getHost();//返回响应的主机
int statusCode = response.getStatusLine().getStatusCode();//响应状态行,可以从中获取状态码
Header[] headers = response.getHeaders();// 获取响应头
String header=response.getHeader("content-type");// 获取指定名称的响应头
String responseBody = EntityUtils.toString(response.getEntity());//响应体包含在org.apache.http.HttpEntity对象中

执行请求时,会在以下情况中引发异常(异步时在ResponseListener#onFailure(Exception)中作为参数接收到该异常):

  1. IOException,通信问题(例如SocketTimeoutException)
  2. ResponseException,返回了一个响应,但是它的状态码表明是错误的(不是2xx)。 ResponseException是一个有效的http响应,因此它暴露了其相应的Response对象,可以访问返回的响应。

对于返回404状态代码的HEAD请求,不会引发ResponseException,因为它是预期的HEAD响应,它只是表示找不到资源。

Response response = restClient.performRequest("HEAD", "/s");//不会抛异常

除非ignore参数包含404,否则所有其他HTTP方法(例如GET)都会为404响应抛出ResponseException。

ignore是一个特殊的客户端参数,它不会发送到Elasticsearch,且包含以逗号分隔的错误状态码列表。 它允许控制是否应将某些错误状态码视为预期响应而不是异常。

这对于get api来说很有用,因为它可以在缺少文档时返回404,在这种情况下,响应主体将不会包含错误,而是通常的get api响应,只是没有文档,因为它没有找到。

注意,低级客户端不会序列化或反序列化json。用户可以*使用他们喜欢的库。

底层的Apache Async Http Client附带不同的org.apache.http.HttpEntity实现,允许以不同格式(流,字节数组,字符串等)提供请求体。

至于读取响应体,HttpEntity的getContent方法很方便,它会返回来自先前缓冲的响应体的InputStream。作为一种替代方法,可以提供一个自定义org.apache.http.nio.protocol.HttpAsyncResponseConsumer来控制如何读取和缓冲字节。

日志

The Java REST client使用了和Apache Async Http Client相同的日志库:Apache Commons Logging,
它支持许多流行的日志实现。 用于启用日志记录功能的java包分别是客户端本身的org.elasticsearch.client,以及嗅探器的org.elasticsearch.client.sniffer。

也可以启用以curl格式来记录每个请求和相应的响应。 这使得调试时非常方便。

例如在需要手动执行请求以检查它是否仍然产生相同的响应时。 为跟踪器包启用日志记录以打印出此类日志。 请注意,该类型的日志记录非常昂贵,不应始终在生产环境中启用,而只是在需要时暂时使用。

官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-overview.html

使用Java客户端操作elasticsearch的更多相关文章

  1. 使用Java客户端操作elasticsearch(二)

    承接上文,使用Java客户端操作elasticsearch,本文主要介绍 常见的配置 和Sniffer(集群探测) 的使用. 常见的配置 前面已介绍过,RestClientBuilder支持同时提供一 ...

  2. Elasticsearch入门系列~通过Java一系列操作Elasticsearch

    Elasticsearch索引的创建.数据的增删该查操作 上一章节已经在Linux系统上安装Elasticsearch并且可以外网访问,这节主要通过Java代码操作Elasticsearch 1.创建 ...

  3. HDFS的Java客户端操作代码&lpar;HDFS的查看、创建&rpar;

    1.HDFS的put上传文件操作的java代码: package Hdfs; import java.io.FileInputStream; import java.io.FileNotFoundEx ...

  4. Hive学习(三)Hive的Java客户端操作

    Hive的Java客户端操作分为JDBC和Thrifit Client,首先启动Hive远程服务: hive --service hiveserver 一.JDBC 在MyEclipse中首先创建连接 ...

  5. springboot整合es客户端操作elasticsearch(五)

    springboot整合es客户端操作elasticsearch的总结: 客户端可以进行可以对所有文档进行查询,就是不加任何条件: SearchRequest searchRequest = new ...

  6. Java 客户端操作 FastDFS 实现文件上传下载替换删除

    FastDFS 的作者余庆先生已经为我们开发好了 Java 对应的 SDK.这里需要解释一下:作者余庆并没有及时更新最新的 Java SDK 至 Maven *仓库,目前*仓库最新版仍旧是 1.2 ...

  7. java客户端的elasticSearch索引库的相关操作

    package com.hope.es;import org.elasticsearch.client.transport.TransportClient;import org.elasticsear ...

  8. springboot整合es客户端操作elasticsearch(四)

    对文档查询,在实际开发中,对文档的查询也是偏多的,记得之前在mou快递公司,做了一套事实的揽件数据操作,就是通过这个来存储数据的,由于一天的数据最少拥有3500万数据 所以是比较多的,而且还要求查询速 ...

  9. springboot整合es客户端操作elasticsearch(二)

    在上章节中整合elasticsearch客户端出现版本问题进行了处理,这章来进行springboot整合得操作 环境:elaticsearch6.2.1,springboot 2.1.8 客户端版本采 ...

随机推荐

  1. 【Todo】OSGi学习

    经常听到.见到OSGi这个名字.那么就单开一篇文章记录一下对OSGi的学习吧. 主要是做一些概念上面的学习.暂时不打算深入实践. 主要参考:http://www.osgi.com.cn/article ...

  2. BZOJ 2054 疯狂的馒头

    并查集把染过色的并在一起.倒着染色. #include<iostream> #include<cstdio> #include<cstring> #include& ...

  3. Java学习之Java的单例模式

    单例模式有一下特点: 1.单例类只能有一个实例.2.单例类必须自己自己创建自己的唯一实例.3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个 ...

  4. MVC创建XML&comma;并实现增删改

    原文:MVC创建XML,并实现增删改 如果创建如下的XML: <?xml version="1.0" encoding="utf-8" standalon ...

  5. 利用Bootstrap Paginator插件和KnockoutJS完成分页功能

    在最近一个项目中,需要结合一堆条件查询并对查询的结果数据完成一个简单分页功能,可是做着做着,自己的思路越来越模糊,做到心态崩溃!!! 哈哈,特此花点时间重新总结,并从最简单的分页,然后向多条件查询分页 ...

  6. 盘点海口最好吃的西餐厅top10

    Top 1:主厨的餐桌 餐厅地址:龙华区海秀路九号民航宾馆一楼大堂 主厨的餐桌Chef's Table是三位志同道合的大厨一起携手开办的西餐厅,正宗的西式料理.浓郁的浪漫气息,都是Chef's Tab ...

  7. Error&colon; Cannot find module &&num;39&semi;babel-runtime&sol;regenerator&&num;39&semi;

    在做调用阿里云短信接口时遇到的一个问题 错误原因:没有正确安装相应的mmodule 解决办法: 第一步:在package.json中加入依赖label-runtime 第二步:在Terminal中 n ...

  8. MFS 服务扫描与爆破

    MSF 服务发现 常用来发现局域网内,的常见服务,比如HTTP,FTP,TELNET等. MSF模块搜索: [root@localhost ~]# msfconsole msf5 > searc ...

  9. Spring注解&commat;Component、&commat;Repository、&commat;Service、&commat;Controller &commat;Resource、&commat;Autowired、&commat;Qualifier、&commat;scope

    以下内容摘自部分网友的,并加上了自己的理解 @Service用于标注业务层组件(我们通常定义的service层就用这个) @Controller用于标注控制层组件(如struts中的action.Sp ...

  10. JavaScript中的类数组对象

    在javascript中,对象与数组都是这门语言的原生规范中的基本数据类型,处于并列的位置. 一般来说,如果我们有一个对象obj和一个数组a: obj["attr1"];    / ...