有没有Maven插件运行非脂肪罐?

时间:2015-08-13 16:41:25

标签: java maven maven-plugin

想象一个普通的java maven项目,其Main类生成工件项目-a.jar。该项目依赖于project-b.jar。

是否有Maven插件允许通过类似命令运行该jar?

mvn run-plugin:run org.mygroup:project-a:3.1 <args>

该插件将解析运行时依赖项(使用META-INF / maven /(...)/ pom.xml),将项目及其依赖项安装到本地maven存储库(如果尚未存在),构造类路径并调用

java -cp (...)/project-a-3.1.jar;(...)/project-b-2.1.jar org.mygroup.Main <args>

我知道通常的方法是构建一个包含依赖项的可执行(胖)jar,但这不是我要求的。

实际上,从jar中读取pom甚至不是必需的,因为maven可以从给定坐标的存储库下载它。

为什么这个问题与Maven Run Project问题有所不同:

我不想从已经检查过项目的来源开始。 因此通常使用exec插件不适用。 Maven Run Project问题的OP显然假设存在源代码项目文件夹。她的目的是测试,她接受了一个显然需要一个项目的答案。这两个问题的措辞也是正确的。单词&#34; 项目&#34;之间存在差异和&#34; jar &#34;它们在各自背景下的实际意义完全不同。

4 个答案:

答案 0 :(得分:1)

您可以使用appassembler-maven-plugin插件,它会为您创建一个在类路径中具有依赖关系的shell脚本。下面是一个示例配置

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>appassembler-maven-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>assemble</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <extraJvmArguments>-Xms256m -Xmx1536m</extraJvmArguments>
                <programs>
                    <program>
                        <mainClass>com.package.MyMainClass</mainClass>
                        <name>TestFormattingUtils</name>
                    </program>
                </programs>
            </configuration>
        </plugin>

您可以在.../target/appassembler/bin中找到输出脚本您可以手动检查脚本,您将看到它正在执行您希望通过命令行将jar添加到类路径的命令类型。即java -jar (...)/project-a-3.1.jar -cp (...)/project-b-2.1.jar <args>

答案 1 :(得分:0)

我也不是罐子里的粉丝,但我确实维护了各种具有很多依赖性的工具。所以,有一次,我决定编写一个可执行的AppBoot jar,它将来自lib-subdirectory的所有jar放入类加载器中,然后调用所需(可执行)jar的main方法。这个问题促使我调查exec-maven-plugin是否可以做类似的事情,而且可以。

exec-maven-plugin不需要“Java项目”目录,但目录中需要pom.xml。我使用的pom.xml如下所示,请注意它可以放在任何(空)目录中,并且可以通过在该目录中打开shell /提示并执行mvn exec:exec来启动应用程序。使用mvn -X exec:exec查看exec-maven-plugin使用的类路径。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.descartes</groupId>
    <artifactId>exec-embed-demo</artifactId>
    <version>1.2.2-SNAPSHOT</version>
    <packaging>pom</packaging>

    <!-- Start the demo using Maven repository artifacts, execute with "mvn exec:exec" -->

    <properties>
        <demo.version>1.2.1.GH</demo.version>
        <mainclass>com.descartes.basicjsp.embed.demo.Launch</mainclass>
        <appname>${project.artifactId}</appname>
        <homedir>${project.basedir}/</homedir>
    </properties>

    <dependencies>
        <dependency>
            <!-- exec-maven-plugin will get all required (runtime) jar-files from this dependency. -->
            <groupId>com.descartes</groupId>
            <artifactId>basic-jsp-embed-demo</artifactId>
            <version>${demo.version}</version>
        </dependency>
    </dependencies>

    <build>
        <!-- The "outputDirectory" is added to the classpath by the exec-maven-plugin. -->
        <!-- Add this pom's directory to the classpath instead of "./target/classes". -->
        <!-- The directory should contain "logback.xml" to prevent a million lines of debug output from Tomcat. -->
        <outputDirectory>${homedir}</outputDirectory>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.4.0</version>
                <!-- mvn exec:exec configuration -->
                <!-- Embedded Tomcat will not stop with "ctrl-c" -->
                <!-- Use http://localhost:8080/shutdown instead -->
                <configuration>
                    <executable>java</executable>
                    <arguments>
                        <argument>-Dapp.name=${appname}</argument>
                        <argument>-Dapp.home.dir=${homedir}</argument>
                        <argument>-Dapp.conf.dir=${homedir}</argument>
                        <argument>-cp</argument>
                        <classpath/>
                        <argument>${mainclass}</argument>
                    </arguments>
                </configuration>
                <!-- mvn exec:java configuration -->
                <!-- "ctrl-c" stops Tomcat but embedded Tomcat fails to start properly, probably a classloader issue. -->
                <!--
                <configuration>
                    <mainClass>${mainclass}</mainClass>
                    <systemProperties>
                        <systemProperty>
                            <key>app.name</key>
                            <value>${appname}</value>
                        </systemProperty>
                        <systemProperty>
                            <key>app.home.dir</key>
                            <value>${homedir}/</value>
                        </systemProperty>
                        <systemProperty>
                            <key>app.conf.dir</key>
                            <value>${homedir}/</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
                -->
            </plugin>
        </plugins>
    </build>

</project>

AppBoot是使用嵌入式Tomcat的basic-jsp-embed项目的一部分,可以找到该项目here(安装,下载最新版本,解压缩zip文件并运行“ mvn install“在多模块项目的根目录下)。

侧面说明:管理jar-set很棘手,使用像jHades这样的工具来验证你不会遇到不同jar文件中同一类的多个版本的麻烦。

答案 2 :(得分:-1)

您正在寻找maven exec plugin

mvn exec:java -Dexec.mainClass="com.example.Main" [-Dexec.args="argument1"]

会运行你的程序

答案 3 :(得分:-1)

Maven无法做你想做的事情,只是因为一旦将project A构建到最终的jar中,它就无法解决repositories的依赖关系。

Maven并没有神奇地从互联网上下载库:它的工作原理是pom.xmlpom.xml的定义。没有project A,就像你似乎建议的那样,它怎么知道从哪里下载库? Maven不是下载工具,它是一个项目管理工具,你所拥有的不再是一个项目,而是一个最终的库。

由于您可以控制maven-assembly-plugin,因此您应该真正依赖Maven约定并构建胖jar或程序集(使用pom.xml)。

顺便说一下,位于META-INF下的pom文件不能保证存在,事实上,如果你看一下Spring工件,它就不存在了。看一下Maven Archiver documentation:这个addMavenDescriptor文件的存在是由false布尔属性控制的。将此属性设置为pom,您的主工件将不会包含此beginInvoke文件。