先说需求吧,是公司的一个maven项目,需要接入翼支付即时到帐接口,去支付时需要使用CA加密签名,翼支付给我们发送了3个jar包,一个证书和1个test.java测试类。
在一个空的测试项目中引入包,引入证书,引入测试类,测试运行,完全正常。 然后准备接入正式项目中,暂且将公司正式maven项目叫做pay吧
我先将3个jar包:bcmail-jdk15-1.47.jar、bcprov-jdk15-1.45.jar、iTrusCertAPI-3.0.0.jar 分别导入在本地maven仓库中去
第二步,在pay项目的pom.xml中引入以上三个包的坐标
<!-- CA证书加密包 --> <dependency> <groupId>signaturev1.0_java</groupId> <artifactId>itruscertapi</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>signaturev1.0_java</groupId> <artifactId>bcmail-jdk15</artifactId> <version>1.47</version> </dependency> <dependency> <groupId>signaturev1.0_java</groupId> <artifactId>bcprov-jdk15</artifactId> <version>1.45</version> </dependency>
第二步:导入测试类test.java,修改证书路径和证书密码,然后测试运行,发现出现了以下的包冲突异常
由类名和反编译发现:ASN1Object类,存在bcprov-jdk15-1.45.jar中,首先排除其他两项。
Exception in thread "main" java.lang.SecurityException: class "org.bouncycastle.asn1.ASN1Object"'s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(ClassLoader.java:952) at java.lang.ClassLoader.preDefineClass(ClassLoader.java:666) at java.lang.ClassLoader.defineClass(ClassLoader.java:794) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:425) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:358) at com.itrus.cryptorole.Sender.<init>(Sender.java:23) at com.itrus.cryptorole.bc.SenderBcImpl.<init>(SenderBcImpl.java:98) at com.chinatelecom.web.trade.utils.CAUtil.<init>(CAUtil.java:17) at com.chinatelecom.web.trade.utils.CAUtil.getInstance(CAUtil.java:28) at com.chinatelecom.web.trade.utils.CAUtilTest.main(CAUtilTest.java:18)
既然是包的异常,那么只需要找到冲突包的名称,然后排除了这个包就可以了。思路很简单,那就开工吧!
...
首先我逐步排查,发现到pay项目的pom.xml中,引入了一个web-service-p的jar包,只要把它删掉,包冲突问题就解决了
<dependency> <groupId>com.chinatelecom.web</groupId> <artifactId>web-service-p</artifactId> <version>1.0.1-RELEASE</version> </dependency>
但是,就是但是,删除掉肯定会影响其他项目的依赖,其他项目自然也无法运行,删调此包肯定是行不通的。
...
然后我发现如果将上面的web-service-p的包版本,修改为1.0.0,这时候包冲突问题也是可以解决的
...
当然,这个办法也是治标不治本的,为了不影响其他项目和本项目的正常运行,找出冲突的包,排除掉才是关键!
关键字:mvn dependency:tree
首先,查看正确运行的,将web-service-p的版本设置为1.0.0 ,然后在pay项目的pom.xml中右键,使用maven命令查看项目依赖树:dependency:tree
在控制台中,搜索相关上面bcprov包名称,看是否有多个,结果发现,只存在一个bcprov-jdk15.jar包,所以运行正常
...
然后,又将web-service-p的版本设置会1.0.1版本,再次使用上面的命令,发现在A依赖的B,B下面的C,C下面的D,D依赖于有一个相同的名称,只是版本不同罢了
看到上图中,有一个133版本的bcprov的包,存在多级的依赖,所以,在pay项目的pom.xml中,将其排除调问题就应该解决了。
当然我们需要知道它的坐标是多少才行,我们在maven在线库中搜索:http://search.maven.org/ 输入关键字,查询到如下坐标点
或者,搜索上级x-fire-ws-security,在路径:https://repo1.maven.org/maven2/org/codehaus/xfire/xfire-ws-security/1.2.6/xfire-ws-security-1.2.6.pom 中找到坐标点
<dependency> <groupId>org.codehaus.xfire</groupId> <artifactId>bcprov-jdk15</artifactId> <version>133</version> </dependency>
最后一步,坐标点有了,那么在依赖的顶级,web-server-p的依赖中进行排除调,问题就正常解决了
<dependency> <groupId>com.chinatelecom.web</groupId> <artifactId>web-service-trade</artifactId> <version>1.0.1-SNAPSHOT</version> <exclusions> <exclusion> <groupId>org.codehaus.xfire</groupId> <artifactId>bcprov-jdk15</artifactId> </exclusion> </exclusions> </dependency>
特别说明:排除的位置不要写错了,一开始我写成了下面方式,结果不管怎么都不行,后来公司大牛东东,提醒说位置不对,一下子就明白怎么回事了! 糗大了!
<dependency> <groupId>signaturev1.0_java</groupId> <artifactId>bcprov-jdk15</artifactId> <version>1.45</version> <exclusions> <exclusion> <groupId>org.codehaus.xfire</groupId> <artifactId>bcprov-jdk15</artifactId> </exclusion> </exclusions> </dependency>
特此写篇文章,经验总结