【问题标题】:Is there a good way to use maven to run an executable jar?有没有使用 maven 运行可执行 jar 的好方法?
【发布时间】:2013-02-15 09:10:32
【问题描述】:

我有一个多模块 maven 项目,其中一个模块用于分发。

Project \
| moduleA \
| moduleB \
| ...
| dist-module \

该发行版包含一个我想轻松执行的可执行 jar。但是,要执行它,我必须输入如下内容:

java -jar dist-module/target/dist-module-1.0-SNAPSHOT-full-dist/myJar.jar

最好直接输入:

mvn exec:java \ OR
mvn exec:exec

不幸的是,我找不到让 java 目标执行 .jar 的方法。 exec 目标实际上会这样做,但有一个问题:jar 包含一个嵌入式码头服务器,并且由于 exec 的工作方式(不使用与 maven 相同的 JVM),除非我终止该进程,否则服务器不会终止手动,同样麻烦。

关于如何使用 maven 执行此操作的任何建议?

编辑:
为澄清起见,此命令将主要用于简单的手动冒烟测试;读取日志输出并确保程序在其分发环境中正确启动。因此,它可能应该是一个阻塞调用,使用 ctrl-c 终止服务器和 maven。

嵌入式服务器专门用于运行一些特定的应用程序,并且不会自动重新加载它们。因此,没有必要让服务器长时间独立于 maven 运行。

【问题讨论】:

  • 码头的任务是什么?
  • 你能把有问题的 exec:java 目标定义附加到 pom 上吗?
  • 没有什么好办法,因为maven是一个构建和部署工具。如果您的 jar 是构建过程的一部分,则为它编写一个 maven 插件。如果你只是想使用 maven 来运行你的应用程序,也许考虑别的更好。
  • 您希望在 maven 完成后终止服务器,或者您希望通过其他方式停止它?

标签: java maven build jar embedded-jetty


【解决方案1】:

mvn exec:java 直接从 target/ 下面的编译器输出运行应用程序 - 无需从 jar 运行:

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.2.1</version>
        <executions>
            <execution>
                <id>default-cli</id>
                <goals>
                    <goal>java</goal>
                </goals>
                <configuration>
                    <mainClass>uk.co.pookey.hibernate.App</mainClass>
                    <systemProperties>
                        <systemProperty>
                            <key>derby.stream.error.file</key>
                            <value>${basedir}/target/derby.log</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
            </execution>
        </executions>
    </plugin>            

如果你想用 mvn exec:exec 运行 jar:

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.2.1</version>
        <executions>
            <execution>
                <id>default-cli</id>
                <goals>
                    <goal>exec</goal>
                </goals>
                <configuration>
                    <executable>java</executable>
                    <!-- optional -->
                    <workingDirectory>/tmp</workingDirectory>
                    <arguments>
                        <argument>-jar</argument>
                        <argument>${basedir}/target/hibernate-derby-memory-${project.version}.jar</argument>
                    </arguments>
                </configuration>                        
            </execution>
        </executions>
    </plugin>         

如果您在终止码头时遇到问题,我建议您运行集成测试(或者在没有先终止码头的情况下不要退出码头主线程,或者只使用码头的停止端口)!可以在后台运行一个JVM,让maven在测试后再次停止它。为此分为三个阶段:集成前测试、集成测试或集成后测试。您可以在http://docs.codehaus.org/display/MAVENUSER/Maven+and+Integration+Testing 阅读更多相关信息。使用 jetty maven 插件时,pom.xml 配置可能如下:

   <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <!-- test start/stop: -->
        <executions>                
            <execution>
                <id>start-jetty</id>
                <phase>pre-integration-test</phase>
                <goals>
                    <goal>deploy-war</goal>
                </goals>
                <configuration>
                    <daemon>true</daemon>
                    <systemProperties>
                        <systemProperty>
                            <name>some.prop</name>
                            <value>false</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
            </execution>
            <execution>
                <id>stop-jetty</id>
                <phase>post-integration-test</phase>
                <goals>
                    <goal>stop</goal>
                </goals>
            </execution>
        </executions>    
    </plugin>

您可以绑定 maven antrun 插件来执行任意命令,而不是将 jetty maven 插件绑定到这些阶段。

【讨论】:

  • 我需要运行 jar,因为它包含标识其路径并指定同一目录中的其他资源的逻辑。因此,实际上是分发项目需要执行代码。但是,使用 maven 进行集成测试是一个值得探索的有趣可能性,因此至少为此 +1。
  • 看起来你正在重新发明轮子。如果您需要适当的分发,请考虑使用 war 文件和可能的 tanukisoft 包装器在生产环境中运行它们——如果您不想使用整个应用程序服务器,如 tomcat 和 jetty 就足够了。 tanukisoft 包装器启动一个 jetty 应用程序服务器并从一个解压的分发档案运行你的 webapps。如果您需要示例,请查看 Archiva 的源代码。如果您需要帮助,我之前已经这样做了...并且在使用 war 文件时,您可以使用我提到的 jetty-integration 示例。
  • 如果你的服务器项目有精简版,我可以试一试。不应该太复杂。但我从未设法以编程方式设置 jetty webapps :-)
  • 使用&lt;phase&gt;install&lt;/phase&gt;,mvn clean install 命令可以很好地执行。
  • 链接失效
【解决方案2】:

如果你想执行一些东西,我会使用 maven ant 或 gmaven(然后使用 groovy ant builder)

在您进行编辑后,听起来您使用的是 DropWizard 之类的东西。你可能想看看他们是怎样的solving that problem。

基于 cmets 编辑:

Spring Boot Maven 将创建可执行的战争并执行它们,您不需要 Spring Boot 或 Spring。我在这里的答案中有更多详细信息:Can spring-boot-maven-plugin be used for non spring project?

【讨论】:

  • 虽然我觉得 user1050755 的回答更直接地解决了这个问题,但我感谢您让 DropWizard 引起我的注意。它不太适合我的项目需求,但足够相似,可以作为一个有趣的案例研究。
  • 在撰写本文时,此答案中的两个链接都已失效。
  • @Stephan 实际上,我现在推荐的最佳选择是 Spring Boot maven 插件,顺便说一下,它不需要 Spring Boot 甚至 Spring。在这里查看我的答案:stackoverflow.com/questions/42696495/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-08
  • 2018-06-30
  • 2017-01-29
  • 2020-05-20
  • 2014-11-14
  • 2017-05-12
  • 2020-03-15
相关资源
最近更新 更多