同时使用两个版本的jar、jar包冲突共存
springboot项目如果遇到第三方jar包冲突,报错java.lang.ClassNotFoundException异常等
情况1,项目中直接引用了两个版本的第三方jar包
对于这种情况,是很好解决的。例如,项目中已经导入了xxx.v1.jar第三方包。现在新功能要求使用xxx.v2.jar第三方包,并且需要保持原来的v1包不动。
我们可以对v2这个jar包的包名重新命名,例如原来是cn.alibaba.XXX格式的包,改成cn.v2.alibaba.XXX包名。项目中使用的时候,import使用cn.v2.alibaba.XXX包即可。
使用maven插件即可实现这个功能maven-shade-plugin
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>com.example.some.library</pattern>
<shadedPattern>com.example.shaded.some.library</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
情况2,项目中两个第三方jar包中引用了两个版本的第三方jar包
例如项目中引用了一个阿里的jar包ali.jar,这个jar包内部又引用了xxx.v1.jar第三方包。
同时项目中也引用了华为的jar包hua.jar,这个jar包内部又引用了xxx.v2.jar第三方包。
因为冲突的包是两个第三方包导致的,我们改不了他们的代码,上面第一种方式不能用了。
sofa-ark方式:
使用https://www.sofastack.tech/projects/sofa-boot/sofa-ark-spring-boot-demo/
原理
原理是利用不同的classLoader之间类是隔离的,框架大概是有一个base服务端jar包,然后自己的业务代码jar包1(其中包含阿里的jar包引用),另一个自己的业务代码jar包2(其中包含华为的jar包引用)。
这样就生成了3个jar包,先启动base服务端jar包,然后剩下的两个业务代码包添加到base服务端。
这种方式比较于其他框架来说,是比较轻量的,但是改了项目结构,还有未知bug。不是很推荐。还是建议手动处理一下冲突的jar包,升级jar包版本,或者使用其他方式。
demo
参考我自己的demo:
git@github.com:shenshuxin01/sofa-ark-guides.git
SOFAArk 工程用例
.
│
├── mina-v1-demo(业务环境1)
│
└── mina-v2-demo(业务环境2)
│
└── start-demo(基础环境)
快速开始
执行mvn clean package
生成jar
start-demo
启动项目先启动这个start-demo,会看到启动日志
16:16:37.093 [SOFA-ARK-telnet-server-worker-0-T1] INFO io.netty.handler.logging.LoggingHandler -- [id: 0x6f1ce4f0] BIND: 0.0.0.0/0.0.0.0:1234
Ark container started in 956 ms.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.3.0)
sofaark监听1234端口
mina-v1-demo
这个是业务环境1,引用了mina1版本的依赖包,包含类org.apache.mina.common.IoFilter
注意这个类是1版本的jar包才有的,
找到对应的jar包mina-v1-demo-1.0-SNAPSHOT-ark-biz.jar
打开telnet 连接1234端口,执行biz -i file:///D:\sofa-ark-fork\mina-v1-demo\target\mina-v1-demo-1.0-SNAPSHOT-ark-biz.jar
看控制台会输出
mina-v2-demo
这个是业务环境2,引用了mina2版本的依赖包,包含类org.apache.mina.core.filterchain.IoFilter
注意这个类是2版本的jar包才有的,
找到对应的jar包mina-v2-demo-1.0-SNAPSHOT-ark-biz.jar
打开telnet 连接1234端口,执行biz -i file:///D:\sofa-ark-fork\mina-v2-demo\target\mina-v2-demo-1.0-SNAPSHOT-ark-biz.jar
看控制台会输出
这样就会同时运行2个版本的jar包了,但是这个对版本依赖有要求,使用jdk8和springboot2.6.6版本的是官网的示例,我自己使用的是
jdk使用21
maven使用3.9
Spring Boot v3.3.0
官网地址
https://www.sofastack.tech/projects/sofa-boot/sofa-ark-spring-boot-demo/
备注
看了几天其他的解决方法,并没有合适的方案,都是要重构项目架构,通过classLoader实现冲突jar包共存。
我看springboot的启动过程中可以指定classLoader,或许可以实例化某个bean的时候设置自定义的classLoader,实现jar包共存
原文地址:https://blog.csdn.net/weixin_48835367/article/details/144362952
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!