Drools Spring与Jasper Report引发CompilationResult依赖冲突如何解决?
这种类加载冲突在Maven项目里太常见了——两个依赖引入了同路径同名称但不同版本的类,JVM不知道该加载哪一个,自然就抛出异常了。针对你遇到的org.eclipse.jdt.internal.compiler.CompilationResult类冲突问题,我给你几个可行的解决方案,按优先级排序:
1. 直接排除冲突的依赖(最推荐)
先搞清楚哪个依赖是你项目实际不需要的,或者说哪个类实现不会影响现有功能。你可以通过mvn dependency:tree命令查看完整依赖树,确认jdtcore和ecj的引入路径:
mvn dependency:tree -Dverbose -Dincludes=org.eclipse.jdt,org.eclipse.jdt.core.compiler
方案A:排除JasperReports中的jdtcore
如果你的Drools功能依赖ecj,且测试后发现JasperReports可以脱离jdtcore正常运行(很多场景下JasperReports只是用它做表达式编译,ecj可以替代),就在jasperreports的依赖里添加排除:
<dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports</artifactId> <version>3.7.2</version> <exclusions> <exclusion> <groupId>org.eclipse.jdt</groupId> <artifactId>jdtcore</artifactId> </exclusion> </exclusions> </dependency>
方案B:排除Drools-Spring中的ecj
反之,如果JasperReports必须依赖jdtcore,而Drools可以兼容jdtcore,就排除drools-spring里的ecj:
<dependency> <groupId>org.drools</groupId> <artifactId>drools-spring</artifactId> <version>5.6.0.Final</version> <exclusions> <exclusion> <groupId>org.eclipse.jdt.core.compiler</groupId> <artifactId>ecj</artifactId> </exclusion> </exclusions> </dependency>
关键:排除后一定要测试两个框架的核心功能,确保没有因为依赖缺失导致新问题。
2. 统一指定兼容版本的依赖
如果两个框架都需要这个类库的功能,你可以在dependencyManagement里强制指定一个兼容两者的版本,让Maven统一使用这个版本替代冲突的包。比如ecj是jdtcore的后续演进版本,功能上可以兼容,你可以指定一个稳定的ecj版本:
<dependencyManagement> <dependencies> <dependency> <groupId>org.eclipse.jdt.core.compiler</groupId> <artifactId>ecj</artifactId> <version>3.10.1</version> <!-- 选择一个同时兼容JasperReports 3.7.2和Drools 5.6.0的版本 --> </dependency> </dependencies> </dependencyManagement>
这样Maven在解析依赖时,会自动用你指定的ecj版本替换掉jdtcore,避免冲突。
3. 升级依赖版本(长远解决方案)
你的JasperReports 3.7.2和Drools 5.6.0都是比较老的版本了,升级到更新版本可能从根源上解决冲突:
- JasperReports 6.x及以上版本已经不再依赖jdtcore,转而使用ecj,和Drools的依赖更兼容;
- Drools的新版本也可能优化了依赖管理,减少冲突概率。
不过升级依赖需要注意兼容性问题,比如API变更、配置调整,需要做好充分的测试。
内容的提问来源于stack exchange,提问作者user9233229

