是否应该在客户端 jar 中提供依赖库?
我们正在为其他内部应用程序提供客户端 jar,以连接到我们应用程序的 REST API。我们的 API 依赖于一些标准 Jakarta 库。将这些 JAR 文件包含在我们的客户端 jar 文件中是否是最佳实践?或者您只是记录依赖关系,并由客户端来确保他们的类路径上有这些 jar 吗?
We're providing a client jar for other internal apps to connect to our app's REST API. Our API depends on a few standard Jakarta libraries. Is it a best practice to include those JAR files within our client jar file? Or do you just document the dependencies and it's up to the clients to ensure they have those jars on their classpath?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您不应该将任何第三方 jar 作为 uber jar 捆绑到您自己的 jar 中,但最好包含您的发行版中所需的所有 jar 的副本,例如在 lib 目录中或任何。
主要原因是您的客户可能正在使用某种形式的依赖管理系统(maven/ivy 等),并且提供实际上不属于您的项目的包和类将使这些方案无效。
有一种替代方法,那就是使用 maven Shade 插件 来将您的依赖项重新定位到您自己的包命名空间中。当然,这有一个缺点,即您将增加库的代码大小,但从好的方面来说,您几乎可以保证依赖项的版本,而不会影响您的客户可能使用的任何其他库。
编辑:回应 Marcus Leon 评论:
无需捆绑/重新定位的可能解决方案:
最后,要真正确保您拥有所需的依赖项是非常困难的,因为 java 是一种后期绑定语言,您的依赖项(即使是捆绑的)可能会被某些人覆盖,包括类路径上您之前的不同版本。
注意:我最近度过了非常糟糕的一天,试图找出为什么我们的一个应用程序无法找到新版本的 log4j。原因:有人试图提供帮助,将其捆绑到一个随机的完全不相关的罐子中。
You should not bundle the any third party jars into your own jar as an uber jar, but it would be good to include a copy of all the jar's that are required in your distribution say in a lib directory or what ever.
The main reason for this is that your clients may be using some form of dependency management system (maven/ivy etc) and providing packages and classes that don't actually belong to your project will invalidate these schemes.
There is one alternative and that is to use something like the maven shade plugin to relocate your dependencies into your own package namespace. This of course has the down side that you will increase the code size of your library but on the up side you can almost guarantee the versions of your dependencies with out effecting any other libraries your clients may be using.
EDIT: in response to Marcus Leon comment:
Possible solutions with out bundling/relocating:
In the end it is extremely hard to actually ensure you have the dependencies you want as java is a late bound language it is possible to have your dependencies (even if bundled) overridden by somebody including a different version before yours on the classpath.
Note: I've recently spent a very bad day trying to find out why one of our apps failed to find a new version of log4j. the cause: somebody trying to be helpful had bundled it into a random completely unrelated jar.
您应该包含您依赖的任何罐子。如果您允许客户端提供标准 jar,您就依赖它们来提供正确的版本。如果您包含您知道您的应用程序可以使用的版本,这对你们俩来说都会轻松得多。
You should include any jars you depend on. If you allow a client to provide standard jars, you rely on them to supply the correct version. It's a lot more painless for you both if you include the versions that you know your app works with.
捆绑到单个 jar 的优点显然是:
捆绑的缺点是:
另一种选择是使用单个主 jar(您的代码),并将类路径清单属性设置为吸收其他 jar。我个人不喜欢这样,因为很容易错过这些半隐藏的依赖项。
最后,如果你只谈论一两个罐子,我会把它们分开。如果您谈论的是 10 或 15 个,您可能需要考虑捆绑。
The pros of bundling into a single jar are obviously:
The cons of bundling are:
Another option is to use a single main jar (your code) with the class-path manifest attribute set to suck in the other jars. Personally I don't like this as it's really easy to miss these semi-hidden dependencies.
In the end, if you're talking just one or two jars, I'd leave them split out. If you're talking 10 or 15, you might want to consider bundling.
如果您将应用程序部署为独立应用程序,则应该包含这些 jar。如果您正在部署源代码供某人构建并且您提供了 Maven pom 文件,那么您不一定需要这样做。
You should include those jars if you're deploying the app as a standalone application. If you're deploying the source for someone to build and you provide a maven pom file then you don't necessarily need to.
你表达了对非常具体的库版本依赖关系的紧张(我可以理解,考虑到 Hibernate 在其不同模块之间的耦合程度如何——只有某些版本的 Hibernate 注释与一个 hibernate 核心一起工作,而 Hibernate 核心又必须与特定的休眠验证器一起使用)。
如果您知道一个包需要作为更大平台的一部分工作(例如,作为可能加载自己的 jar 的框架的插件),那么您确实需要更强大的 OSGI 多版本类加载(又名 JSR -291):
OSGI 技术
使用支持 OSGI 的框架,例如 Spring、Eclipse、Jonas 或 Glassfish,您可以可以在 XML 文件中指定您的特定版本依赖项,如果您依赖于 libfoo-1.1.4 包,而另一个插件依赖于 libfoo-2.0a,OSGI 依赖项管理器将确保每个插件加载正确的版本。
You're expressing nervousness about very specific library version dependencies (and I can understand that, given how tightly coupled, say, Hibernate is between its different modules -- only certain versions of Hibernate-annotations work with one hibernate-core, which in turn must be used with a specific hibernate-validator).
If you know a package needs to work as part of a much larger platform (say, as a plugin to a framework which may be loading its own jars), you really need the more powerful multi-versioned class-loading of OSGI (aka JSR-291):
OSGI Technology
With an OSGI-enabled framework, like Spring, Eclipse, Jonas, or Glassfish, you may specify in an XML file your specific version dependencies, and if you depend upon the bundle libfoo-1.1.4, while another plugin depends upon libfoo-2.0a, the OSGI dependency manager will ensure each loads the correct version.