Gradle & Springboot 引入ES低版本的問題
之前在做專案的時候需要在 SpringBoot中引入 ElasticSearch,但是由於伺服器版本較低,最新版 ES 是6.x.x,而我需要的是5.1.1(org.elasticsearch.client:transport:5.1.1
)。當我引入5.1.1的版本包的時候,org.elasticsearch.client:transport:5.1.1
中依賴的org.elasticsearch:elasticsearch
自動升級成了6.x.x。 折騰搜尋了一天,終於找到了原因。在這裡記錄一下整個排查流程。
一開始在啟動SpringBoot
時,會丟擲 ElasticSearch 有某個類/某個方法未找到的異常,因此懷疑是引入的包版本不正確。
使用gradle -q dependencies
指令,輸出如下
+--- org.elasticsearch.client:transport:5.1.1 |+--- org.elasticsearch:elasticsearch:5.1.1 -> 6.4.3 ||+--- org.elasticsearch:elasticsearch-core:6.4.3 ||+--- org.elasticsearch:elasticsearch-secure-sm:6.4.3 ||+--- org.elasticsearch:elasticsearch-x-content:6.4.3 |||+--- org.elasticsearch:elasticsearch-core:6.4.3 |||+--- org.yaml:snakeyaml:1.17 -> 1.23 |||+--- com.fasterxml.jackson.core:jackson-core:2.8.10 -> 2.9.8 |||+--- com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.8.10 -> 2.9.8 |||+--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.8.10 -> 2.9.8 (*) |||\--- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.8.10 -> 2.9.8 ||+--- org.apache.lucene:lucene-core:7.4.0 ||+--- org.apache.lucene:lucene-analyzers-common:7.4.0 ||+--- org.apache.lucene:lucene-backward-codecs:7.4.0 ||+--- org.apache.lucene:lucene-grouping:7.4.0 ||+--- org.apache.lucene:lucene-highlighter:7.4.0 ||+--- org.apache.lucene:lucene-join:7.4.0 ||+--- org.apache.lucene:lucene-memory:7.4.0 ||+--- org.apache.lucene:lucene-misc:7.4.0 ||+--- org.apache.lucene:lucene-queries:7.4.0 ||+--- org.apache.lucene:lucene-queryparser:7.4.0 ||+--- org.apache.lucene:lucene-sandbox:7.4.0 ||+--- org.apache.lucene:lucene-spatial:7.4.0 ||+--- org.apache.lucene:lucene-spatial-extras:7.4.0 ||+--- org.apache.lucene:lucene-spatial3d:7.4.0 ||+--- org.apache.lucene:lucene-suggest:7.4.0 |+--- org.elasticsearch.plugin:transport-netty4-client:5.1.1 -> 6.4.3 ||+--- io.netty:netty-buffer:4.1.16.Final -> 4.1.33.Final (*) ||+--- io.netty:netty-codec:4.1.16.Final -> 4.1.33.Final (*) ||+--- io.netty:netty-codec-http:4.1.16.Final -> 4.1.33.Final ||+--- io.netty:netty-common:4.1.16.Final -> 4.1.33.Final ||+--- io.netty:netty-handler:4.1.16.Final -> 4.1.33.Final (*) ||+--- io.netty:netty-resolver:4.1.16.Final -> 4.1.33.Final (*) ||\--- io.netty:netty-transport:4.1.16.Final -> 4.1.33.Final (*)
可以看到transport下所依賴的部分包自動升級成了6.4.3
。但是在gradle中並沒有設定什麼。 因此繼續使用gradlew -q dependencyInsight --dependency elasticsearch --info
檢視 elasticsearch的具體依賴:
org.elasticsearch:elasticsearch:6.4.3 (selected by rule) variant "runtime" [ org.gradle.status = release (not requested) Requested attributes not found in the selected variant: org.gradle.usage= java-api ] org.elasticsearch:elasticsearch:5.1.1 -> 6.4.3 \--- org.elasticsearch.client:transport:5.1.1 \--- compileClasspath org.elasticsearch:elasticsearch-cli:6.4.3 variant "runtime" [ org.gradle.status = release (not requested) Requested attributes not found in the selected variant: org.gradle.usage= java-api ] org.elasticsearch:elasticsearch-cli:6.4.3 \--- org.elasticsearch:elasticsearch:6.4.3 \--- org.elasticsearch.client:transport:5.1.1 \--- compileClasspath org.elasticsearch:elasticsearch-core:6.4.3 variant "runtime" [ org.gradle.status = release (not requested) Requested attributes not found in the selected variant: org.gradle.usage= java-api ] org.elasticsearch:elasticsearch-core:6.4.3 +--- org.elasticsearch:elasticsearch:6.4.3 |\--- org.elasticsearch.client:transport:5.1.1 |\--- compileClasspath +--- org.elasticsearch:elasticsearch-cli:6.4.3 |\--- org.elasticsearch:elasticsearch:6.4.3 (*) \--- org.elasticsearch:elasticsearch-x-content:6.4.3 \--- org.elasticsearch:elasticsearch:6.4.3 (*)
發現了前兩項直接使用了6.4.3的版本,給出的理由是**selected by rule**
,我就想說gradle這是啥奇奇怪怪的規則。。。經過一番搜尋,終於發現這一篇帖子
大體是說SpringBoot
的外掛,會通過Spring dependency-management-plugin
增加自己的依賴規則,其中包括會強制引入特定的版本,並忽視掉自己在gradle配置的版本(這也太坑了吧)。
//就是這個外掛 apply plugin: 'io.spring.dependency-management'
所以最後的解決方法是自定義全域性的版本控制,如下
allprojects { configurations.all { resolutionStrategy { dependencySubstitution { substitute module('org.elasticsearch:elasticsearch') with module('org.elasticsearch:elasticsearch:5.1.1') substitute module('org.elasticsearch.plugin:transport-netty4-client') with module('org.elasticsearch.plugin:transport-netty4-client:5.1.1') substitute module('org.elasticsearch.client:elasticsearch-rest-client') with module('org.elasticsearch.client:elasticsearch-rest-client:5.1.1') } } } }
這可以告訴gradle
強制使用5.1.1版本去替換依賴的elasticsearch的版本。當然這裡我引入的transport
所依賴的transport-netty4-client
和elasticsearch-rest-client
都被強制升級了,所以這裡也進行配置一下。
最後,也許可以通過配置spring的外掛解決,附上外掛的 github地址 ,有空研究一下