【发布时间】:2010-12-17 07:25:21
【问题描述】:
我们正在为其他内部应用提供客户端 jar,以连接到我们应用的 REST API。我们的 API 依赖于一些标准的 Jakarta 库。将这些 JAR 文件包含在我们的客户端 jar 文件中是最佳做法吗?还是您只是记录依赖关系,并由客户来确保他们的类路径中有这些 jar?
【问题讨论】:
标签: java client-library
我们正在为其他内部应用提供客户端 jar,以连接到我们应用的 REST API。我们的 API 依赖于一些标准的 Jakarta 库。将这些 JAR 文件包含在我们的客户端 jar 文件中是最佳做法吗?还是您只是记录依赖关系,并由客户来确保他们的类路径中有这些 jar?
【问题讨论】:
标签: java client-library
您应该不将任何第三方 jar 作为 uber jar 捆绑到您自己的 jar 中,但最好将您的发行版中所需的所有 jar 的副本包含在一个lib 目录或任何其他目录。
主要原因是您的客户可能正在使用某种形式的依赖管理系统(maven/ivy 等),并且提供实际上不属于您的项目的包和类将使这些方案无效。
还有一种替代方法,那就是使用 maven shade plugin 之类的东西将您的依赖项重新定位到您自己的包命名空间中。这当然有不利的一面,即您会增加库的代码大小,但有利的一面是,您几乎可以保证依赖项的版本,而不会影响您的客户可能正在使用的任何其他库。
编辑:回应马库斯·莱昂的评论:
无需捆绑/重新定位的可能解决方案:
最后,实际上很难确保你拥有你想要的依赖项,因为 java 是一种后期绑定的语言,你的依赖项(即使是捆绑的)可能会被在类路径上包含不同版本的人覆盖.
注意:我最近度过了非常糟糕的一天,试图找出为什么我们的一个应用无法找到新版本的 log4j。原因:有人试图提供帮助,把它捆绑到一个随机的完全不相关的罐子里。
【讨论】:
您应该包含您所依赖的所有 jar。如果您允许客户端提供标准 jar,则您依赖它们提供正确的版本。如果您包含您知道您的应用可以使用的版本,这对你们双方来说都会轻松得多。
【讨论】:
捆绑到单个 jar 中的优点显然是:
捆绑的缺点是:
另一种选择是使用单个主 jar(您的代码)并设置类路径清单属性来吸收其他 jar。我个人不喜欢这样,因为很容易错过这些半隐藏的依赖关系。
最后,如果你只是说一两个罐子,我会把它们分开。如果您说的是 10 或 15,则可能需要考虑捆绑。
【讨论】:
如果您将应用程序部署为独立应用程序,则应包含这些 jar。如果您正在部署源代码以供某人构建并且您提供了一个 maven pom 文件,那么您不一定需要。
【讨论】:
您表达了对非常具体的库版本依赖关系的紧张情绪(我可以理解,考虑到 Hibernate 在其不同模块之间的紧密耦合程度——只有某些版本的 Hibernate-annotations 与一个 hibernate-core 一起工作,这又必须与特定的休眠验证器一起使用)。
如果你知道一个包需要作为更大平台的一部分工作(例如,作为一个框架的插件,可能会加载它自己的 jars),你真的需要更强大的 OSGI 多版本类加载(又名 JSR-291): OSGI Technology
对于支持 OSGI 的框架,如 Spring、Eclipse、Jonas 或 Glassfish,您可以在 XML 文件中指定您的特定版本依赖项,以及是否依赖于捆绑包 libfoo-1.1.4,而另一个插件依赖于libfoo-2.0a,OSGI 依赖管理器将确保每个加载正确的版本。
【讨论】: