由于在 Elastic Stack 8.x 中天然地添加了安全性,我们在使用 Java 客户端进行连接的时候,我们可以通过不同的途径来完成。在我之前的文章中,我创建了一系列的文章来展示:
在上面,我们可以通过 Java HTTP 的集成来访问 Elasticsearch。这个是不依赖于 Elasticsearch 的版本来进行访问的。我们也可以通过 Elastic 公司所提供的 Elasticsearch Java client 8.x 来进行访问。在通常的情况下,Elasticsearch Java client 会更为高效。它提供了良好的 JSON 支持以及对连接的管理。这样也是被推荐的方法。
在今天的文章中,我将使用另外一种方式来进行展示。我将使用 Low Level client API 来进行连接及访问。
如果你还没有安装好自己的 Elasticsearch 及 Kibana。请参阅我之前的文章:
在默认的情况下,Elastic Stack 8.x 的安装已带有安全。如果你是自托管型的集群,那么你的证书应该是自签名的证书。
有两个官方的 Elasticsearch 客户端:低级客户端和 Elasticsearch 8.x (https://github.com/elastic/elasticsearch-java) 提供的新类型客户端。 低级用于与 Elasticsearch 通信,主要特点如下:
要创建 RestClient,我们将执行以下步骤:
1)我们需要添加用于执行 HTTP 调用的 Elasticsearch HTTP 客户端库。 该库位于 search.maven.org 的主 Maven 存储库中。 要在 Maven pom.xml 项目中启用编译,只需添加以下代码:
pom.xml
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0modelVersion>
-
- <groupId>org.examplegroupId>
- <artifactId>ELasticsearchJava-lowlevelartifactId>
- <version>1.0-SNAPSHOTversion>
-
- <properties>
- <maven.compiler.source>8maven.compiler.source>
- <maven.compiler.target>8maven.compiler.target>
- properties>
-
- <dependencies>
- <dependency>
- <groupId>org.elasticsearch.clientgroupId>
- <artifactId>elasticsearch-rest-clientartifactId>
- <version>8.0.0version>
- dependency>
- dependencies>
-
- project>
2)如果我们想实例化一个客户端并使用 get 方法获取一个文档,代码将如下所示:
ElasticsearchJavaLowLevel.java
- import org.apache.http.HttpEntity;
- import org.apache.http.HttpHost;
- import org.apache.http.HttpStatus;
- import org.apache.http.auth.AuthScope;
- import org.apache.http.auth.UsernamePasswordCredentials;
- import org.apache.http.client.CredentialsProvider;
- import org.apache.http.conn.ssl.NoopHostnameVerifier;
- import org.apache.http.conn.ssl.TrustAllStrategy;
- import org.apache.http.impl.client.BasicCredentialsProvider;
- import org.apache.http.impl.nio.client.
- HttpAsyncClientBuilder;
- import org.apache.http.ssl.SSLContextBuilder;
- import org.apache.http.util.EntityUtils;
- import org.elasticsearch.client.*;
-
- import java.io.IOException;
- import java.security.*;
- import javax.net.ssl.SSLContext;
-
- public class ElasticsearchJavaLowLevel {
- public static void main(String[] args) throws
- KeyManagementException, NoSuchAlgorithmException,
- KeyStoreException {
- RestClientBuilder clientBuilder = RestClient.
- builder(new HttpHost("localhost", 9200, "https"))
- .setCompressionEnabled(true);
- final CredentialsProvider credentialsProvider =
- new BasicCredentialsProvider();
- credentialsProvider.setCredentials(AuthScope.ANY,
- new UsernamePasswordCredentials(System.
- getenv("ES_USER"), System.getenv("ES_PASSWORD")));
- final SSLContext sslContext = new
- SSLContextBuilder().loadTrustMaterial(null,
- TrustAllStrategy.INSTANCE).build();
- clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
- public HttpAsyncClientBuilder
- customizeHttpClient(HttpAsyncClientBuilder
- httpClientBuilder) {
- return httpClientBuilder
- .setSSLContext(sslContext)
- .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
- .setDefaultCredentialsProvider(credentialsProvider);
- }
- });
- RestClient client = clientBuilder.build();
- try {
- Request request = new Request("GET", "/mybooks/_doc/1");
- Response response = client.
- performRequest(request);
- if (response.getStatusLine().getStatusCode()
- != HttpStatus.SC_OK) {
- System.err.println("Method failed: " +
- response.getStatusLine());
- } else {
- HttpEntity entity = response.getEntity();
- String responseBody = EntityUtils.
- toString(entity);
- System.out.println(responseBody);
- }
- } catch (IOException e) {
- System.err.println("Fatal transport error: "
- + e.getMessage());
- e.printStackTrace();
- } finally {
- // Release the connection.
- try {
- client.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
我们需要在环境变量中设置你访问 Elasticsearch 集群的用户名及密码。
上面的代码实现的功能相当于我们在 Kibana 下打入如下的命令:
GET mybooks/_doc/1
为了能够让上面的代码顺利执行,我们首先在 Kibana 中创建如下的一个索引:
- PUT mybooks/_doc/1
- {
- "uuid": "1",
- "title": "Great math"
- }
在内部,Elasticsearch RestClient 客户端使用 Apache HttpComponents 库并用更方便的方法包装它。如果你想了解如何使用 Apache HttpComponents 来建立和 Elasticsearch 的连接,请参考我之前的文章 “ Elasticsearch:使用标准 Java HTTP 的集成 - Elastic Stack 8.x”。 我们执行了前面的步骤来创建和使用 RestClient。 让我们更详细地看一下它们:
1)第一步是初始化 RestClient 对象。 这是通过以下代码片段完成的:
- RestClientBuilder clientBuilder = RestClient.builder(new HttpHost("localhost", 9200, "https"))
- // some stuff to setup SSL and auth as seen in previous
- example
- …
- RestClient client = clientBuilder.build();
builder 方法接受一个多值 HttpHost 主机(通过这种方式,你可以传递一个 HTTP 地址列表)并在后台返回 RestClientBuilder。
2)RestClientBuilder 对象允许通过多种方法自定义客户端通信,例如:
3)创建 RestClient 后,我们可以通过几种 performRequest 方法对它执行一些请求,用于同步调用和 performRequestAsync 方法用于异步调用。这些方法允许你设置参数,例如:
在前面的示例中,我们使用以下代码执行了 GET REST 调用:
Response response = client.performRequest(request);
响应对象是 org.elasticsearch.client.Response,它包装了 Apache HttpComponents 响应。
运行上面的代码,我们可以看到的结果为:
- {"_index":"mybooks","_id":"1","_version":1,"_seq_no":0,"_primary_term":1,"found":true,"_source":{
- "uuid": "1",
- "title": "Great math"
- }
- }
我们可以看到它的结果和我们之前的是没有什么不同。