问题描述

集成环境中(比如大数据的 CDH,Oozie)有配套的第三方 Jar 包,在自己编写的工具中使用了相同的包,但是版本不同,就会在运行是报错,包的版本产生冲突

1
java.lang.NoSuchFieldError: INSTANCE

解决办法

使用 maven-shade-plugin 对需要的第三方包重命名并重新打包,映射成自己定义的名字

解决步骤

在 pom.xml 文件中添加 shade 插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<!-- Run shade goal on package phase -->
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>org.elasticsearch</pattern>
<shadedPattern>my.elasticsearch</shadedPattern>
</relocation>

<relocation>
<pattern>org.apache.http</pattern>
<shadedPattern>my.apache.http</shadedPattern>
</relocation>

<relocation>
<pattern>com.fasterxml.jackson</pattern>
<shadedPattern>my.fasterxml.jackson</shadedPattern>
</relocation>
</relocations>

<!-- 配置主类 -->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.xxx.app.EsApp</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

<!-- 配置编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

主要配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<relocations>
<relocation>
<pattern>org.elasticsearch</pattern>
<shadedPattern>my.elasticsearch</shadedPattern>
</relocation>

<relocation>
<pattern>org.apache.http</pattern>
<shadedPattern>my.apache.http</shadedPattern>
</relocation>

<relocation>
<pattern>com.fasterxml.jackson</pattern>
<shadedPattern>my.fasterxml.jackson</shadedPattern>
</relocation>
</relocations>

将官方包的名称及路径修改成为自定义的名称,防止冲突

重新编译打包

推荐使用 luyten 这个工具打开编译打包好的 jar 包,在使用到对应类的 class 文件中就可以看到,原来的 org.elasticsearch 都被替换成 my.elasticsearch 了,其他同理,也就不会出现在集群环境重产生 jar 包冲突的错误了