5

我构建了一个独立的 Java 应用程序,它具有一堆依赖项(Apache Commons 库等)以及对 Spring 框架的依赖项,而 Spring 框架又具有一堆依赖项。

我在 Eclipse 中构建了它,它运行良好。现在我需要将它部署到生产环境中,因此我试图找出将它与所有依赖项打包的最佳方法,以及如何调用它(它将从命令行调用)。

蛮力的方法是将我的项目导出为一个 jar,找到所有依赖的 jar(及其依赖项!),将它们复制到一个公共目录,编写一个包含类路径中每个的 shell 脚本并运行它。显然,这看起来既愚蠢又乏味。

我应该使用 Ant、Maven 吗?我应该将所有依赖的 Spring jar 打包到一个大文件中吗?有关处理此问题的任何提示都会有所帮助。

4

10 回答 10

4

Java 部署在 2009 年仍然是愚蠢和乏味的。所以通常的选择是编写这个小脚本。如果您将所有 JAR 放入一个目录(例如lib\),您可以使用自动构建类路径的通用脚本(请参阅此博客条目)。我建议cd /d %~dp0在 cd 的开头添加一个到脚本的目录。

Maven 2 有一个插件,可以将您的应用程序组装到一个“超级 JAR”(mvn assembly:assembly)中。除非您使用 DB2 JCC 驱动程序(其中包含转换为 com.ibm .- > ClassNotFoundException 的“COM.ibm.”包),否则此方法有效。

最后一个解决方案,如果您已经有一个可以工作的 ANT build.xml,是解压缩所有依赖的 JAR 并自己创建一个“超级 JAR”。

于 2009-02-19T09:43:22.780 回答
2

使用 Ant,您可以执行以下操作:

  1. 将所有依赖项组合在一起。
  2. 使用您的应用程序打包一个 JAR 文件,并在 MANIFEST.MF 文件中嵌入对依赖项的引用,并在 jar 中使用“Class-Path”指令。这应该消除在启动时构建类路径的需要。
  3. 将它们捆绑在一起作为存档,然后分发。使用“java -jar your.jar”直接运行 jar 就足够了。

为了管理您的依赖关系,您可以使用Ivy。与 Maven 非常相似,它能够在构建时从您配置的任何存储库中检索依赖项,包括 Maven 存储库或您自己的私有存储库。

于 2009-02-19T10:16:39.860 回答
1

我们发现依赖管理和打包的最佳解决方案是使用 Maven 和Assembly插件。这为将项目以及所有运行时依赖项和支持脚本打包到二进制发行版中提供了一种非常优雅的方法。使用程序集的最大优势之一是可以根据需要将项目拆分为不同的组件。如果您使用的是 Spring Integration,它很常见,您将有单独的组件拆分到多台机器上。程序集插件允许您根据需要对其进行配置。

于 2009-02-19T09:44:43.900 回答
1

所有这些 Maven 的爱,没有人提到 Ivy?哦亲爱的!

好吧,这里是Ant Ivy,这里是与 Maven2 的比较。在与几乎每个人的建议一起去之前,请先看看它。

于 2009-02-21T15:00:18.027 回答
0

我们正在使用带有m2eclipse插件的 Maven 2;效果很好。插件有一个依赖关系图视图,将显示冲突等。

现在,如果您想将所有依赖项打包到单个 jar 中,您可以查看Jar Jar Links(不开玩笑!)。

于 2009-02-20T00:01:17.523 回答
0

您可以使用正确设置类路径的启动器。然后,您将有更多的灵活性来打包您的 JAR。您可以轻松地将它们全部放在一个目录中,这比创建“混蛋” ueber jar 要干净得多...

这样的启动器之一是commons-launcher

于 2009-02-19T09:50:48.817 回答
0

如果您使 JAR 可执行并添加包括 ClassPath 的清单,那么您的很多顾虑都会消失。不幸的是,您确实必须将 JAR 及其依赖项压缩在一起,但您的 CLASSPATH 问题已得到解决。

创建一个 OSGi 包怎么样?我自己还没有研究过它,但它应该是打包 Java 应用程序的下一步。它用于应用服务器,如 Spring 的 dm 服务器。也许它也可以帮助你。

于 2009-02-21T14:22:51.847 回答
0

在我的 ANT 构建脚本中,我生成了 *.bat 和 *.sh 启动脚本,其中包含在构建时根据构建的 lib 目录的内容动态构建的 JAR 列表。

例如,要创建带有适当分隔符的 jar 列表:

<path id="jar-classpath">
    <fileset dir="${build.war.dir}/WEB-INF/lib">
        <include name="**/*.jar" />
    </fileset>
</path>

<pathconvert refid="jar-classpath" targetos="unix" property="exec.classpath.unix">
       <map from="${build.war.dir}\WEB-INF\lib\" to="../lib/"/>
</pathconvert>

<pathconvert refid="jar-classpath" targetos="windows" property="exec.classpath.windows">
        <map from="${build.war.dir}\WEB-INF\lib\" to="../lib/"/>
</pathconvert>

然后,您可以在 java 调用脚本中使用${exec.classpath.unix}和值。${exec.classpath.windows}

于 2009-02-21T14:41:46.963 回答
0

maven-assembly-plugin 可能不是最佳选择。您应该查看 onejar-maven-plugin,如下所述:

http://blog.jayway.com/2009/03/22/executable-jar-with-onejar-maven-plugin/

它让你所有的依赖 jar 都保持在 jar 中,并且你的代码在它自己的 jar 中。所有这些罐子都放在一个更大的罐子里,它是可执行的。

于 2009-04-17T06:43:50.210 回答
0

你也可以使用 Gradle,这里是你可以在那里做的:

mainClassName = "my.App"

task runnableJar(type: Jar, dependsOn: [':assemble']) {
    from files(sourceSets.main.output.classesDir)
    from files(sourceSets.main.output.resourcesDir)
    from configurations.runtime.asFileTree.files.collect { zipTree(it) }

    manifest {
        attributes 'Main-Class': mainClassName
    }
}
于 2017-04-25T00:17:10.580 回答