在Java / Maven中处理“ Xerces地狱”?
在我的办公室里,仅提及Xerces一词就足以引起开发人员的致命愤怒。粗略地浏览SO上的其他Xerces问题似乎表明,几乎所有Maven用户在某个时候都被该问题“感动”。不幸的是,了解问题需要对Xerces的历史有一点了解... 历史 Xerces是Java生态系统中使用最广泛的XML解析器。几乎所有用Java编写的库或框架都以某种能力使用Xerces(如果不是直接使用,则是透明地使用)。 到目前为止,官方二进制文件中包含的Xerces jar 尚未进行版本控制。例如,Xerces 2.11.0实现jar被命名为xercesImpl.jarnot xercesImpl-2.11.0.jar。 Xerces团队不使用Maven,这意味着他们不将正式发行版上载到Maven Central。 Xerces过去以单个jar(xerces.jar)的形式发布,但被拆分为两个jar,一个包含API(xml-apis.jar),一个包含这些API的实现(xercesImpl.jar)。许多较旧的Maven POM仍声明依赖于xerces.jar。在过去的某个时候,Xerces也发布为xmlParserAPIs.jar,某些较早的POM也依赖于此。 将jar部署到Maven存储库的人分配给xml-apis和xercesImpl jar的版本通常是不同的。例如,即使xml-apis都来自Xerces 2.8.0,也可以给它xml版本1.3.03,给xercesImpl版本2.8.0。这是因为人们经常用实现的规范版本标记xml-apis jar。还有就是这是一个非常不错的,但不完全击穿这里。 使事情复杂化的是,Xerces是JRE中包含的XML处理Java API(JAXP)的参考实现中使用的XML解析器。实现类在com.sun.*名称空间下重新打包,这使得直接访问它们很危险,因为它们在某些JRE中可能不可用。但是,并非所有的Xerces功能都通过java.*和javax.*API 公开;例如,没有API公开Xerces序列化。 令人困惑的是,几乎所有servlet容器(JBoss,Jetty,Glassfish,Tomcat等)都随Xerces一起放在其一个或多个/lib文件夹中。 问题 解决冲突 由于上述某些(或全部)原因,许多组织在其POM中发布和使用Xerces的自定义版本。如果您的应用程序很小并且仅使用Maven Central,那么这并不是真正的问题,但是对于Artifactory或Nexus代理多个存储库(JBoss,Hibernate等)的企业软件而言,这很快就成为一个问题: 例如,组织A可能发布xml-apis为: <groupId>org.apache.xerces</groupId> <artifactId>xml-apis</artifactId> <version>2.9.1</version> 同时,组织B可能发布以下内容jar: <groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> <version>1.3.04</version> 尽管B的jar版本低于A的版本jar,但Maven不知道它们是相同的工件,因为它们具有不同 groupId的。因此,它不能执行冲突解决,并且两个都 jar将作为已解决的依赖项包括在内: 类加载器地狱 如上所述,JRE在JAXP RI中与Xerces一起提供。将所有Xerces Maven依赖项标记为<exclusion>s或as 会很好<provided>,您所依赖的第三方代码可能会或可能不会与您使用的JDK的JAXP中提供的版本一起使用。另外,您还可以将Xerces jars放在servlet容器中以应对。这给您提供了许多选择:是否删除servlet版本,并希望您的容器在JAXP版本上运行?离开servlet版本更好,希望您的应用程序框架在servlet版本上运行是否更好?如果上面概述的一两个未解决的冲突成功地渗入了您的产品(在大型组织中很容易发生),您很快就会陷入类加载器地狱中,想知道类加载器在运行时选择的是哪个版本的Xerces,是否将在Windows和Linux中选择相同的jar(可能不是)。 解决方案? 我们试过标志认证的所有Xerces的Maven依赖作为<provided>或作为<exclusion>,但这是给难以执行(尤其是大型团队)的文物有这么多的别名(xml-apis,xerces,xercesImpl,xmlParserAPIs,等)。此外,我们的第三方库/框架可能无法在JAXP版本或servlet容器提供的版本上运行。 我们如何最好地使用Maven解决这个问题?我们是否必须对依赖项进行这种细粒度的控制,然后依靠分层的类加载?是否有某种方法可以全局排除所有Xerces依赖关系,并强制我们所有的框架/库使用JAXP版本? 更新:Joshua Spiewak已将Xerces构建脚本的修补程序版本上载到XERCESJ-1454,从而可以上载到Maven Central。投票/观看/贡献这个问题,让我们一劳永逸地解决这个问题。