通過maven-shade-plugin 解決Elasticsearch與hbase的jar包衝突問題
今天在專案中整合hbase1.0.0-cdh5.5.2和ElasticSearch2.2.0時出現了問題,原先在整合hbase時,引入了架包com.google.guava(16.0版本),後來在整合ES時發現es中也用到了guava的18.0版本。這時候問題來了,如果將原來的guava 16.0版本修改為18.0版本,hbase就是因為版本太高而報錯。如果繼續使用16.0版本es的javaAPI就會因為guava的版本太低而報錯。好尷尬。。。。
於是乎查詢了一下資料,發現在ES的官網上有一篇關於jar包衝突的blog。所以參考修改了一下,折騰一天終於搞定。下面回顧一下整個過程:
1.首先是參考es官網blog:https://www.elastic.co/blog/to-shade-or-not-to-shade ,新建一個maven專案
<?xml version="1.0" encoding="UTF-8"?> <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.0</modelVersion> <groupId>my.elasticsearch</groupId> <artifactId>es-shaded</artifactId> <version>1.0-SNAPSHOT</version> <properties> <elasticsearch.version>2.2.0</elasticsearch.version> </properties> <dependencies> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>${elasticsearch.version}</version> </dependency> <dependency> <groupId>org.elasticsearch.plugin</groupId> <artifactId>shield</artifactId> <version>${elasticsearch.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.1</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <relocations> <relocation> <pattern>com.google.guava</pattern> <shadedPattern>my.elasticsearch.guava</shadedPattern> </relocation> <relocation> <pattern>org.joda</pattern> <shadedPattern>my.elasticsearch.joda</shadedPattern> </relocation> <relocation> <pattern>com.google.common</pattern> <shadedPattern>my.elasticsearch.common</shadedPattern> </relocation> <relocation> <pattern>com.google.thirdparty</pattern> <shadedPattern>my.elasticsearch.thirdparty</shadedPattern> </relocation> </relocations> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer" /> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> <repositories> <repository> <id>elasticsearch-releases</id> <url>http://maven.elasticsearch.org/releases</url> <releases> <enabled>true</enabled> <updatePolicy>daily</updatePolicy> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
如上配置完成後,其實就是將org.joda等4個可能有衝突的jar包通過maven-shade-plugin外掛遷移後重新打個jar包從而使得在引入這個jar包時能夠使用該jar包自己的依賴而不是使用外部依賴。
這裡笨小蔥一開始犯了個嚴重的錯誤,我一直以為只有guava這一個包衝突了,所以一開始並沒有做com.google.common的jar包遷移。所以在使用hbase時出現瞭如下錯誤:
java.lang.IllegalAccessError: tried to access method com.google.common.base........
後來引入com.google.common後才解決問題。
pom檔案配置完成後執行:
mvn clean install
然後看到build success的話表示打包成功,新的依賴包會在.m2檔案的倉庫中。
下面回到原來的整合專案的pom檔案中。引入該jar包: (注意這裡需要排除掉es2.2.0的jar包,不然maven會將2.2.0的jar包打進去,造成衝突)
<dependency> <groupId>my.elasticsearch</groupId> <artifactId>es-shaded</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> </exclusion> </exclusions> </dependency>
好啦,到這裡測試一下會發現,衝突問題解決啦。
補充:如果需要定位到具體是哪個class引起的衝突,可以通過在tomcat的bin/catalina.sh中配置:
JAVA_OPTS="-verbose:class" tomcat啟動後會在catalina.out日誌檔案中打印出載入的類的位置。從而定位出哪個class載入了不正確的jar包.