【问题标题】:Package and run a Java application with spring dependencies使用 Spring 依赖项打包并运行 Java 应用程序
【发布时间】:2010-10-08 13:10:34
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: java spring ant build-process packaging


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

          所有这些 Maven 的爱,没有人提到 Ivy?天哪!

          好吧,这里是Ant Ivy,这里是comparison to Maven2。在几乎每个人都建议之前,请先看看它。

          【讨论】:

            【解决方案5】:

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

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

            【讨论】:

              【解决方案6】:

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

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

              【讨论】:

                【解决方案7】:

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

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

                【讨论】:

                  【解决方案8】:

                  在我的 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} 值。

                  【讨论】:

                    【解决方案9】:

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

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

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

                    【讨论】:

                      【解决方案10】:

                      你也可以使用 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
                          }
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2019-05-02
                        • 2018-10-07
                        • 2023-03-10
                        • 1970-01-01
                        • 2012-07-15
                        • 2023-04-08
                        相关资源
                        最近更新 更多