Maven打包指定main函数入口

By | 2021年12月31日

1 maven打包可执行jar条件

Maven可以使用mvn package指令对项目进行打包,如果使用Java -jar xxx.jar执行运行jar文件,会出现”no main manifest attribute, in xxx.jar”(没有设置Main-Class)、ClassNotFoundException(找不到依赖包)等错误。
要想jar包能直接通过java -jar xxx.jar运行,需要满足:
(1)在jar包中的META-INF/MANIFEST.MF中指定Main-Class。
(2)要能加载到依赖包。

2 maven-jar-plugin和maven-dependency-plugin插件打包(仅打包当前项目文件)

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.6</version>
        <configuration>
            <archive>
                <manifest>
                    <addClasspath>true</addClasspath>
                    <classpathPrefix>lib/</classpathPrefix>
                    <mainClass>com.study.MyApp</mainClass>
                </manifest>
            </archive>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
            <execution>
                <id>copy-dependencies</id>
                <phase>package</phase>
                <goals>
                    <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                    <outputDirectory>${project.build.directory}/lib</outputDirectory>
                </configuration>
            </execution>
        </executions>
    </plugin>
</plugins>

maven-jar-plugin插件用于生成META-INF/MANIFEST.MF文件的部分内容,com.study.MyApp指定MANIFEST.MF中的Main-Class,addClasspath=true会在MANIFEST.MF加上Class-Path项并配置依赖包,lib/指定依赖包所在目录。下面是一个通过maven-jar-plugin插件生成的MANIFEST.MF文件片段:

Class-Path: lib/commons-lang3-3.8.1.jar
Main-Class: com.study.MyApp

maven-dependency-plugin插件用于将依赖包拷贝到${project.build.directory}/lib目录下。

指定了Main-Class,又有了依赖包,现在我们可以运行jar包了:java -jar ./myapp.jar com.study.MyApp

3 maven-assembly-plugin插件打包(全部打到一个jar包中)

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <mainClass>com.study.MyApp</mainClass>
            </manifest>
        </archive>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

package、single表示在执行package打包时,执行assembly:single,所以可以直接使用mvn package打包。
mvn clean package打包后会在target目录下生成一个myapp-jar-with-dependencies.jar文件,这个文件不但包含了自己项目中的代码和资源,还包含了所有依赖包的内容(class文件)。所以可以直接通过java -jar来运行:java -jar ./myapp-jar-with-dependencies.jar com.study.MyApp

4 java -cp 的使用

cp是class path的简称。第2节我们使用maven-jar-plugin插件将class path添加到了MANIFEST.MF文件中,执行jar包时就不需要指定 -cp了。这次我们使用maven-jar-plugin只添加 Main-Class到清单文件,不添加Class-Path,maven-jar-plugin插件配置就不再贴出来了。
此时执行 java -jar ./myapp.jar com.study.MyApp 会报错,因为可执行jar包依赖其他jar包,解决的办法是使用 -cp替代-jar,下面以linux为例:
java -cp ./lib/*:./myapp.jar com.study.MyApp

请注意,将 ./lib/* 写成 ./lib/ ./lib都会报错。
之前写的Storm文件上也有关于cp的讲解:storm -cp

发表评论

您的电子邮箱地址不会被公开。