记一次elasticSearch7.3.x+springboot配置+排错过程

最近在我的一个资源站(www.kuizii.com)中做一个检索功能接入了ElasticSearch.原因众所周边,众所周知,ES(简称)对内容站的检索比操作数据库快上很多在数据量巨大的情况下,数据量小没必要,链路越多,依赖的三方中间件越多,所产生的不稳定因互也会增加。

大家应该知道ES比起原生Luncene多了一次封装,为了适配luncene各版本以及es程序的各版本(不同版本往上往下都没有很多的兼容),同时官方的sdk有众多的三方依赖,比如netty,log4j,在搭建使用springboot+es时往往会出现很多错误,Spring的ioc特性给大家带来好处的同时还带来一堆问题,比如依赖组件的版本冲突,基本上都得编译时再会报出一堆错误堆栈信息让人去排查。

百度上虽然一堆文章,还是大多陈旧以及千篇一律。看似轻松搭建,实际可能会遇到不少问题。

以上废话

先来一遍开发流程

1.从https://www.elastic.co/cn/elasticsearch下载 7.3.2版本。安装(或解压)并启动。(如果你ES恰好是6.4.3,哪么与本文的异常无关)

2.添加MAVEN的引用,引用最新(平时理所当然以为最新版本可以满足,所以引用写该文章时最新版本 2.2.5)

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-elasticsearch -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>

3.实现  ElasticsearchRepository<T,V> 接口,用以直接操作数据

public interface BookRepository extends ElasticsearchRepository<ResourceDto, String> {

    //Page<ResourceDto> findByNameOrContent(String name, Pageable pageable);
}

4.在Service层或Controller层或其它哪一层注入XXXRepository 就可以使用了。

@Service
public class BookSerivceImpl implements BookService {

    @Autowired
    BookRepository bookRepository;

    @Override
    public Optional<ResourceDto> findById(String id) {
        return bookRepository.findById(id);
    }

    @Override
    public ResourceDto save(ResourceDto book) {
        return bookRepository.save(book);
    }

    @Override
    public void delete(ResourceDto book) {
        bookRepository.delete(book);
    }
}

DEBUG,发现编译报错。注入失败

Description:

Field bookRepository in com.kuizii.ebook.core.elastic.search.service.impl.BookSerivceImpl required a bean of type 'com.kuizii.ebook.core.elastic.search.repository.BookRepository' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)

像这样的问题经常见,出现这种问题无论是否跟本文内容有关   大家一定要先想到这是因为spring容器没有扫描(其实是反射)到要创建的对象。这种原因大多是因为一个,未指定扫描位置,添加下面一句 @EnableElasticsearchRepositories(basePackages=xxx)

@SpringBootApplication
@MapperScan(basePackages = {"com.kuizii.ebook.core.dao"})//mybatis扫描组件用的
@ComponentScan(basePackages = {"com.kuizii"}) //spring扫描组件用的
@EnableElasticsearchRepositories(basePackages = "com.kuizii.ebook.core.elastic") //这里,es扫描组件用的,添加这一句
public class EbookStarterApplication{

    public static void main(String[] args) {

       
       SpringApplication.run(EbookStarterApplication.class,args);
    }
}

接下来 继续编译,诶,又报错

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticsearchClient' defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.transport.TransportClient]: Factory method 'elasticsearchClient' threw exception; nested exception is java.lang.NoSuchFieldError: LUCENE_6_0_0
	at ............
略N个堆栈信息
Caused by: java.lang.NoSuchFieldError: LUCENE_6_0_0
	at org.elasticsearch.Version.<clinit>(Version.java:47) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.common.logging.DeprecationLogger.<clinit>(DeprecationLogger.java:158) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.common.unit.ByteSizeValue.<clinit>(ByteSizeValue.java:38) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.common.network.NetworkService.<clinit>(NetworkService.java:56) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.transport.TcpTransport.<clinit>(TcpTransport.java:153) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.client.transport.TransportClient.newPluginService(TransportClient.java:103) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.client.transport.TransportClient.buildTemplate(TransportClient.java:133) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.client.transport.TransportClient.<init>(TransportClient.java:283) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.transport.client.PreBuiltTransportClient.<init>(PreBuiltTransportClient.java:128) ~[transport-6.4.3.jar:6.4.3]
	at org.elasticsearch.transport.client.PreBuiltTransportClient.<init>(PreBuiltTransportClient.java:114) ~[transport-6.4.3.jar:6.4.3]

从内容稍加分析可以得知,代码里的ES版本咋是6.4.3.而我是7.3.2..why?其实从 MAVEN引用层级可以看出spring-boot-starter-data-elasticsearch2.2.5依赖了spring-data-elasticsearch 3.1.3-->再依赖了elasticsearch相关6.4.3的版本。那为什么提示 java.lang.NoSuchFieldError: LUCENE_6_0_0,这是我一开始提到的,es依赖了6.0的lucene.

因为目前到我写文章的时间

spring-boot-starter-data-elasticsearch最高版本是2.2.5 ,那就不引用它了。直接引用elasticsearch依赖的组件就行了。

有些人问为什么不引用最新的spring-boot-data-elasticsearch (当前是3.2.5),因为还不够新,3.2.5依赖的是es6.8.5,

有些人还专门作了对照图,倒不如放弃依赖spring-boot-data-elasticsearch 。直接引用官方

如图:

        <!-- https://mvnrepository.com/artifact/org.elasticsearch.client/transport -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
             <version>7.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
             <version>7.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
             <version>7.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
             <version>7.3.2</version>
        </dependency>

这次编译,通过!

编译通过不代表可以顺利运行,执行查询方法bookService.findAll();怎么又报错?

Caused by: java.lang.NoSuchMethodError: org.elasticsearch.search.SearchHits.getTotalHits()J
	at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.doCount(ElasticsearchTemplate.java:513) ~[spring-data-elasticsearch-3.2.5.RELEASE.jar:3.2.5.RELEASE]
	at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.count(ElasticsearchTemplate.java:490) ~[spring-data-elasticsearch-3.2.5.RELEASE.jar:3.2.5.RELEASE]

package org.elasticsearch.search;
.....

    @Nullable
    public TotalHits getTotalHits() {
        return this.totalHits;
    }

咱们查看代码很容易看出es 的getTotalHits返回的类型为TotalHits,而spring-data-elasticsearch3.1.5返回类型却为long。明显是spring-data的代码版本没更新引用的代码错误。

尝试更新到最新的spring-data-elasticsearch 3.2.5,仍然是未对totalhits作处理。怎么办呢?看来截止发文(20-3-9)是无法使用es7.X.X版本了,不然得对spring-data-elasticsearch 作更改,当然不是不行,而是代价太大(比如可以用aspectj对报错方法进行拦截),最简单的只能是降低ES的版块(目前3.2.5支持的elasticsearch最高版本为6.8.6,将es版本换下来,即可正常运行。也可不使用spring-data-elasticsearch,直接直接elasticsearchTemplate调用)。

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值