SpringBoot整合Elasticsearch的Java Rest Client

2020年八月修订:
SpringBoot 已经升级了ES的客户端,Spring Data Elasticsearch 4.0已经使用 Elasticsearch 7.6.2了,若希望使用Spring的ES模板可已自行尝试.


首先明确一点,SpringBoot自带的ES模板,不建议使用,建议使用Rest Client。如果业务简单,且无特殊要求,可以使用SpringBoot的模板ElasticsearchRepository来搞定。这个非常简单,这里不作介绍,有需要看最底下的连接

ElasticsearchRepository

  • 优点: 简单,SpringBoot无缝对接,配置简单
  • 缺点: 基于即将废弃的TransportClient, 不能支持复杂的业务

创建SpringBoot项目

IDEA 创建SpringBoot工程

如果不会创建,可以参考:https://www.jianshu.com/p/2101d176555b
maven 和 gradle都可以,建议使用 JDK使用1.8 因为Elasticsearch 的Java High Level REST Client 对java的版本要求是8。你们可以去官网查证。
【参考:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-maven.html

添加Rest Client依赖,增加配置

maven工程:

 <!-- 工具类 -->
<dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.8.1</version>
</dependency>

 <!-- Java Low Level REST Client -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>6.3.2</version>
</dependency>

 <!-- Java High Level REST Client -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>6.3.2</version>
</dependency>

gradle 工程

dependencies {
    compile 'org.elasticsearch.client:elasticsearch-rest-client:6.3.2'
    compile 'org.elasticsearch.client:elasticsearch-rest-high-level-client:6.3.2'
}

版本号请根据自己安装的ES版本酌情选择,因为ES5和ES6的API有些差别

编写单例Rest Low Level Client 和Rest High Level Client的bean

想用Spring 的IOC管理ES的连接客户端,可分下面几步

  • 配置ES节点
  • 配置Rest Client
  • 配置Rest High Level Client
  • 使用IOC注入

根据我从其他网站上查询的资料,Rest Client是长连接,而且内部有默认的线程池管理,因此一般无需自定义线程池管理连接。如果不对请指正

基于以上结论。先把连接点全部配置到配置文件中.(为了省事,直接一个数组搞定,有心的朋友可以注入成list+对象)

  1. 配置节点
elasticsearch.ip=127.0.0.1:9200,127.0.0.2:9200,127.0.0.3:9200,127.0.0.4:9200,127.0.0.5:9200,127.0.0.6:9200
  1. 编写Config类,配置Rest Client和Rest High Level Client

请找一个pack,创建ElasticsearchRestClient 类

/**
 * this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 * Create By @author zing  @date 2018/7/18 17:20
 */
@Slf4j
@Configuration
public class ElasticsearchRestClient {
    private static final int ADDRESS_LENGTH = 2;
    private static final String HTTP_SCHEME = "http";

    /**
     * 使用冒号隔开ip和端口1
     */
    @Value("${elasticsearch.ip}")
    String[] ipAddress;

    @Bean
    public RestClientBuilder restClientBuilder() {
        HttpHost[] hosts = Arrays.stream(ipAddress)
                .map(this::makeHttpHost)
                .filter(Objects::nonNull)
                .toArray(HttpHost[]::new);
        log.debug("hosts:{}", Arrays.toString(hosts));
        return RestClient.builder(hosts);
    }


    @Bean(name = "highLevelClient")
    public RestHighLevelClient highLevelClient(@Autowired RestClientBuilder restClientBuilder) {
        restClientBuilder.setMaxRetryTimeoutMillis(60000);
        return new RestHighLevelClient(restClientBuilder);
    }


    private HttpHost makeHttpHost(String s) {
        assert StringUtils.isNotEmpty(s);
        String[] address = s.split(":");
        if (address.length == ADDRESS_LENGTH) {
            String ip = address[0];
            int port = Integer.parseInt(address[1]);
            return new HttpHost(ip, port, HTTP_SCHEME);
        } else {
            return null;
        }
    }
}

注:@Slf4j注解是lombok的日志注解,可以自行删除,切换成其他日志方式;Stream不会的朋友可以写成for循环,速度大约能快些

业务使用

强烈建议从TransportClient迁移到RestClient,因为业务压测发现TransportClient存在并发瓶颈。
在service里然后使用之前创建的highLevelClient呢?
demo如下

@Service
public class XXXServiceImpl implements XXXService {
    @Autowired
    RestHighLevelClient highLevelClient;

    @Override
    public boolean testEsRestClient(){
        SearchRequest searchRequest = new SearchRequest("gdp_tops*");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("city", "北京市"));
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(sourceBuilder);
        try {
            SearchResponse response = highLevelClient.search(searchRequest);
            Arrays.stream(response.getHits().getHits())
                    .forEach(i -> {
                        System.out.println(i.getIndex());
                        System.out.println(i.getSource());
                        System.out.println(i.getType());
                    });
            System.out.println(response.getHits().totalHits);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}

如果你没有Query DSL的基础,建议先学习ES的基本查询方法,如果有时间我可能会写一些,但是网上已经有N多入门教程。

ps:

ES 没有事务概念,ES存储暂时可以理解成每次请求是原子性的,如果涉及多种数据库操作,如:存完ES再存MySQL,且要保证一致性的话,可以考虑使用消息队列做失败补偿,如果需要及时返回的存储,最好不要同时操作两种数据库。否则则需要手动控制事务失败后的恢复。相对麻烦很多

RestClient其他详细使用方法参考我前面的文章:

Elasticsearch Java Rest Client 上手指南(上)

Elasticsearch Java Rest Client 上手指南(下)

想用自带SpringBoot光环的ElasticsearchRepository的可参考:https://juejin.im/post/5aec0b386fb9a07abb23784d

By: Max Zing
转载请注明出处:https://www.jianshu.com/p/0b4f5e41405e
如有错误,请不吝指正。谢谢
我的博客:https://micorochio.github.io/

转载请勿使用本文章推广任何自媒体!请勿追加任何媒体的二维码!

一口奶到位,我把项目里的代码抽离做成了Maven版的Sample,https://github.com/xzing/SpringBootElasticsearchSample.git
各位看官喜欢可以点个赞

====
感谢@一纳秒的指正,由于项目繁忙,忘记更新博客的代码了,文章不是一天写完的,所以有错误的话欢迎指正

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容