14 低级客户端入门


说明:一般来说不会使用低级客户端,都会选用高级客户端,这里只做简单的介绍,后面会面详细介绍高级客户端的使用,高级客户端也是基于低级客户端的。

1 环境准备

1.1 依赖

  1. 依赖
<dependencies>
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-client</artifactId>
        <version>7.10.1</version>
    </dependency>
    <dependency>
    	<!--高级客户端-->
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.10.1</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.16</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.1</version>
    </dependency>
 </dependencies>

1.2 索引库准备

PUT books
{
  "settings": {
    "number_of_shards": 3, 
    "number_of_replicas": 1
  }, 
  "mappings": {
      "properties": {
        "id":{
          "type": "long"
        },
        "title":{
          "type": "text",
          "analyzer": "ik_max_word"
        },
        "language":{
          "type": "keyword"
        },
        "author":{
          "type": "keyword"
        },
        "price":{
          "type": "double"
        },
        "year":{
          "type": "date",
          "format": "yyyy-MM-dd"
        },
        "description":{
          "type": "text",
          "analyzer": "ik_max_word"
        }
      }
    }
  
}

2 客户端初始化

2.1 基本用法

只需要设置es服务的ip和端口,以及通讯协议即可

 @Test
 public void testBuild() throws IOException {
     // 1 构造RestClient
     RestClient client = RestClient.builder(
             new HttpHost("localhost", 9200, "http")
     ).build();
     // 2 关闭
     client.close();
 }
public static RestClientBuilder builder(HttpHost... hosts) {
     if (hosts == null || hosts.length == 0) {
         throw new IllegalArgumentException("hosts must not be null nor empty");
     }
     List<Node> nodes = Arrays.stream(hosts).map(Node::new).collect(Collectors.toList());
     return new RestClientBuilder(nodes);
 }

可见这个方法接受的是一个可变参数,所以如果是集群,可以传HttpHost对象的数组即可

2.2 可配置项目

配置请求头
/**
 *  配置请求头
 */
public void testConfigHead() throws IOException {
    Header[] hears = new Header[]{new BasicHeader("key","value")} ;
    // 接受的是一个Header数组
    RestClient client = restClientBuilder.setDefaultHeaders(hears).build();
    client.close();
}
配置失败监听器
 /****
     * 配置监听器
     */
    @Test
    public void testConfigListener() throws IOException {
        // 设置一个监听器,该监听器在每次节点失败时都会收到通知,在启用嗅探时在内部使用。
        RestClient client = restClientBuilder.setFailureListener(new RestClient.FailureListener() {
            @Override
            public void onFailure(Node node) {
                super.onFailure(node);
            }
        }).build();
        client.close();
    }
配置节点选择器
/****
* 设置节点选择器
*/
@Test
public void testConfigNodeSelector() throws IOException {
   RestClient client = restClientBuilder.setNodeSelector(NodeSelector.SKIP_DEDICATED_MASTERS)
           .build();
   client.close();
}
配置超时时间
/****
  * 配置超时时间
  */
 @Test
 public void testConfigTimeout() throws IOException {
     RestClient client = restClientBuilder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
         public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
             // 设置套接字超时时间
             requestConfigBuilder.setSocketTimeout(10000);
             // 链接超时时间
             requestConfigBuilder.setConnectTimeout(5000);
             return requestConfigBuilder;
         }
     }).build();
     client.close();
 }
配置线程数
/****
  * 配置线程数量
  * @throws IOException
  */
 @Test
 public void testConfigThread() throws IOException {
     RestClient client= restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
         @Override
         public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
            httpClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(2).build());
             return httpClientBuilder;
         }
     }).build();
     client.close();
 }

完整的测试样例

package study.wyy.es.client.base;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.Node;
import org.elasticsearch.client.NodeSelector;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

/**
 * @author by wyaoyao
 * @Description
 * @Date 2021/1/3 5:20 下午
 */
@Slf4j
public class RestClientBuilderTest {

    RestClientBuilder restClientBuilder;

    @Before
    public void initHost(){
        restClientBuilder = RestClient.builder(
                new HttpHost("localhost", 9200, "http")
        );

    }
    @Test
    public void hello(){
        log.info("hello world");
    }

    /**
     *  构造简单的es RestClient
     */
    @Test
    public void testBuild() throws IOException {
        // 1 构造RestClient
        RestClient client = RestClient.builder(
                new HttpHost("localhost", 9200, "http")
        ).build();
        // 2 关闭
        client.close();
    }

    /**
     *  配置请求头
     */
    public void testConfigHead() throws IOException {
        Header[] hears = new Header[]{new BasicHeader("key","value")} ;
        // 接受的是一个Header数组
        RestClient client = restClientBuilder.setDefaultHeaders(hears).build();
        client.close();
    }

    /****
     * 配置监听器
     */
    @Test
    public void testConfigListener() throws IOException {
        // 设置一个监听器,该监听器在每次节点失败时都会收到通知,在启用嗅探时在内部使用。
        RestClient client = restClientBuilder.setFailureListener(new RestClient.FailureListener() {
            @Override
            public void onFailure(Node node) {
                super.onFailure(node);
            }
        }).build();
        client.close();
    }

    /****
     * 设置节点选择器
     */
    @Test
    public void testConfigNodeSelector() throws IOException {
        RestClient client = restClientBuilder.setNodeSelector(NodeSelector.SKIP_DEDICATED_MASTERS)
                .build();
        client.close();
    }

    /****
     * 配置超时时间
     */
    @Test
    public void testConfigTimeout() throws IOException {
        RestClient client = restClientBuilder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
            public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
                // 设置套接字超时时间
                requestConfigBuilder.setSocketTimeout(10000);
                // 链接超时时间
                requestConfigBuilder.setConnectTimeout(5000);
                return requestConfigBuilder;
            }
        }).build();
        client.close();
    }

    /****
     * 配置线程数量
     * @throws IOException
     */
    @Test
    public void testConfigThread() throws IOException {
        RestClient client= restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
            @Override
            public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
               httpClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(2).build());
                return httpClientBuilder;
            }
        }).build();
        client.close();
    }
}

3 构建请求

@Test
public void testBuildRequest() throws IOException {
    // 构建一个请求:localhost:9200/
    Request request = new Request("GET", "/");
    Response response = restClient.performRequest(request); 
    log.info("response: {}", EntityUtils.toString(response.getEntity()));
    restClient.close();
}
  • 通过org.elasticsearch.client.Request进行构建请求参数的
    • 参数一:就是请求方法,GET,POST等
    • 参数二:就是请求的endPoint

关于响应结果的解析,后面在介绍。这里就是简单看一下日志的输出

{
  "name" : "01DR11620116651",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "tWcocvlyQxWfNFhIshS5Dw",
  "version" : {
    "number" : "7.10.1",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa",
    "build_date" : "2020-12-05T01:00:33.671820Z",
    "build_snapshot" : false,
    "lucene_version" : "8.7.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

再比如查询我们上面准备的索引中_id=1的文档,注意下,这时索引库中一条数据还没有

@Test
public void testBuildRequest3() throws IOException {
    // 构建一个请求
    Request request = new Request("GET", "books/_doc/1");
    Response response = restClient.performRequest(request);
    log.info("response: {}", EntityUtils.toString(response.getEntity()));
    restClient.close();
}

执行发现404:

org.elasticsearch.client.ResponseException: method [GET], host [http://localhost:9200], URI [books/_doc/1], status line [HTTP/1.1 404 Not Found]
{"_index":"books","_type":"_doc","_id":"1","found":false}

但是是有结果的,日志里面已经看到:这不就是kibana上执行查询的结果


可点击key和value值进行编辑
{
    "_index":"books",
    "_type":"_doc",
    "_id":"1",
    "found":false
}

那么去kibana新增一条数据之后,在测试呢:

PUT books/_doc/1
{
    "id":"1",
    "title":"Java编程思想",
    "language":"java",
    "author":"Bruce Eckel",
    "price":70.2,
    "publish_time":"2007-10-01",
    "description":"Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉。"
}

此时就会发现不会出现404,测试不会报错了。

完整的测试代码

package study.wyy.es.client.base;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

/**
 * @author wyaoyao
 * @description
 * @date 2021/1/8 10:47
 */
@Slf4j
public class BuildRequestTest {

    RestClient restClient;

    @Before
    public void buildRestClient(){
        restClient = RestClient.builder(new HttpHost("localhost", 9200, "http"))
                .build();
    }

    /***
     * 构建请求对象
     */
    @Test
    public void testBuildRequest() throws IOException {
        // 构建一个请求
        Request request = new Request("GET", "/");
        Response response = restClient.performRequest(request);
        log.info("response: {}", EntityUtils.toString(response.getEntity()));
        restClient.close();
    }

    @Test
    public void testBuildRequest2() throws IOException {
        // 构建一个请求
        Request request = new Request("GET", "_cat/indices");
        Response response = restClient.performRequest(request);
        log.info("response: {}", EntityUtils.toString(response.getEntity()));
        restClient.close();
    }

    @Test
    public void testBuildRequest3() throws IOException {
        // 构建一个请求
        Request request = new Request("GET", "books/_doc/1");
        Response response = restClient.performRequest(request);
        log.info("response: {}", EntityUtils.toString(response.getEntity()));
        restClient.close();
    }
}

4 执行请求

es的客户端提供了两种执行方式

  • 同步执行
  • 异步执行

4.1 同步执行

同步执行:restClient.performRequest()
前面的代码已经演示如何使用了,这里不多赘述

4.2 异步执行

当异步执行,客户端不需要等es服务返回响应。为了能够异步处理,所以需要一个监听器,来监听es服务的响应,进行相应的处理

API介绍
  1. 调用的方法的就是restClient.performRequestAsync(),接收两个参数

    • 请求对象Request
    • 监听器”:ResponseListener
  2. org.elasticsearch.client.ResponseListener

public interface ResponseListener {

    /**
     * Method invoked if the request yielded a successful response
     * // 执行成功的回调函数
     */
    void onSuccess(Response response);

    /**
     *  // 执行异常的回调函数
     */
    void onFailure(Exception exception);
}
示例
package study.wyy.es.client.base;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseListener;
import org.elasticsearch.client.RestClient;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

/**
 * @author wyaoyao
 * @description
 * @date 2021/1/8 13:49
 */
@Slf4j
public class PerformRequestTest {

    /***
     * 测试异步
     * @throws IOException
     */
    public static void main(String[] args) {
        RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200, "http"))
                .build();
        // 构建一个请求
        Request request = new Request("GET", "/");
        restClient.performRequestAsync(request, new ResponseListener() {
            // 执行成功的回调函数
            public void onSuccess(Response response) {
                log.info("执行成功");
            }
            // 执行异常的回调函数
            public void onFailure(Exception exception) {
                log.error("执行异常:{}",exception.getMessage(),exception);
            }
        });
        // 不能在这关闭了,异步请求,可能还没有拿到结果,客户端关闭了
        //restClient.close();
    }
}

5 响应解析

package study.wyy.es.client.base;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.RequestLine;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

/**
 * @author wyaoyao
 * @description
 * @date 2021/1/8 14:29
 */
@Slf4j
public class ParseResponseTest {
    RestClient restClient;

    @Before
    public void buildRestClient(){
        restClient = RestClient.builder(new HttpHost("localhost", 9200, "http"))
                .build();
    }


    @Test
    public void parseResponseTest() throws IOException {
        // 构建一个请求
        Request request = new Request("GET", "books/_doc/1");
        Response response = restClient.performRequest(request);
        // 拿到请求信息
        RequestLine requestLine = response.getRequestLine();
        log.info("请求信息: {}",requestLine);
        // 拿到host地址
        HttpHost host = response.getHost();
        log.info("es地址:{}",host);
        // 响应头
        Header[] headers = response.getHeaders();
        log.info("响应头:{}",headers);
        String contentType = response.getHeader("content-type");
        log.info("contentType:{}",contentType);
        // 状态码
        int statusCode = response.getStatusLine().getStatusCode();
        log.info("状态码:{}",statusCode);
        // 响应体
        String body = EntityUtils.toString(response.getEntity());
        log.info("响应体:{}",body);

    }

}
请求信息: GET books/_doc/1 HTTP/1.1
es地址:http://localhost:9200
响应头:content-type: application/json; charset=UTF-8
contentType:application/json; charset=UTF-8
 状态码:200
 响应体:{"_index":"books","_type":"_doc","_id":"1","_version":1,"_seq_no":4,"_primary_term":1,"found":true,"_source":{
    "id":"1",
    "title":"Java编程思想",
    "language":"java",
    "author":"Bruce Eckel",
    "price":70.2,
    "publish_time":"2007-10-01",
    "description":"Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉。"
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值