在我的办公室,仅仅提到 Xerces 这个词就足以激起开发人员的杀气。粗略地看一下关于 SO 的其他 Xerces 问题似乎表明几乎所有 Maven 用户都在某个时候被这个问题“感动”了。不幸的是,理解这个问题需要一些关于 Xerces 历史的知识......
历史
Xerces 是 Java 生态系统中使用最广泛的 XML 解析器。几乎每个用 Java 编写的库或框架都以某种方式使用 Xerces(如果不是直接的话,则是传递性的)。
直到今天,官方二进制文件中包含的 Xerces jar都没有版本化。例如,Xerces 2.11.0 实现 jar 被命名
xercesImpl.jar
而不是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 的版本可能是 1.3.03,而 xercesImpl 的版本可能是 2.8.0,即使两者都来自 Xerces 2.8.0。这是因为人们经常用它实现的规范版本来标记 xml-apis jar。还有就是这是一个非常不错的,但不完全击穿这里。
更复杂的是,Xerces 是在 Java API for XML Processing (JAXP) 的参考实现中使用的 XML 解析器,包含在 JRE 中。实现类被重新打包在
com.sun.*
命名空间下,这使得直接访问它们很危险,因为它们在某些 JRE 中可能不可用。但是,并非所有 Xerces 功能都通过java.*
和javax.*
API公开;例如,没有公开 Xerces 序列化的 API。更令人困惑的是,几乎所有 servlet 容器(JBoss、Jetty、Glassfish、Tomcat 等)都在它们的一个或多个
/lib
文件夹中附带 Xerces 。
问题
解决冲突
出于上述某些(或者可能是全部)原因,许多组织在其 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
s。因此,它无法执行冲突解决,并且两个
jar
s 都将作为已解决的依赖项包含在内:
类加载器地狱
如上所述,JRE 随 JAXP RI 中的 Xerces 一起提供。虽然将所有 Xerces Maven 依赖项标记为<exclusion>
s 或为<provided>
,您依赖的第三方代码可能适用于您正在使用的 JDK 的 JAXP 中提供的版本,也可能不适用。此外,您还需要处理 servlet 容器中附带的 Xerces jar。这给您留下了许多选择:您是否删除了 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。投票/观看/贡献这个问题,让我们一劳永逸地解决这个问题。
自 2013 年 2 月 20 日起,Maven Central 中有 2.11.0 JAR (和源 JAR!) Xerces!请参阅Maven Central 中的 Xerces。我想知道他们为什么没有解决https://issues.apache.org/jira/browse/XERCESJ-1454 ...
我用过:
<dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> <version>2.11.0</version> </dependency>
并且所有依赖项都已解决 - 甚至正确
xml-apis-1.4.01
!最重要的是(过去并不明显) - Maven Central 中的 JAR 与官方
Xerces-J-bin.2.11.0.zip
发行版中的 JAR 相同。但是,我找不到
xml-schema-1.1-beta
版本 -classifier
由于其他依赖项,它不能是 Maven版本。