• 【Java】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、要能加载到依赖包。

    搭建示例项目

      1、新建Maven工程

      

      2、编辑pom.xml文件

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <modelVersion>4.0.0</modelVersion>
     6 
     7     <groupId>org.example</groupId>
     8     <artifactId>test-mvn-package</artifactId>
     9     <version>1.0-SNAPSHOT</version>
    10 
    11     <dependencies>
    12         <dependency>
    13             <groupId>cn.hutool</groupId>
    14             <artifactId>hutool-all</artifactId>
    15             <version>5.3.7</version>
    16         </dependency>
    17     </dependencies>
    18 </project>

      3、编辑主类MyMain.java

     1 public class MyMain {
     2 
     3     public static void main(String[] args) {
     4         System.out.println("===========程 序 启 动===========");
     5 
     6         // 当前时间字符串,格式:yyyy-MM-dd HH:mm:ss
     7         // DateUtil 第三方jar包中的类
     8         String now = DateUtil.now();
     9         System.out.println("当前时间:" + now);
    10 
    11         System.out.println("===========程 序 关 闭===========");
    12     }
    13 }

      4、测试,运行主方法,效果如下:

        

      5、直接mvn package,打包后,运行jar包

        运行方法一:java -jar test-mvn-package-1.0-SNAPSHOT.jar

        

        运行方法二(指定主类):java -cp test-mvn-package-1.0-SNAPSHOT.jar com.test.api.MyMain

        

        均无法直接运行

    项目打包

      使用Maven有以下几种方法可以生成能直接运行的jar包,可以根据需要选择一种合适的方法。

    方法一:使用maven-jar-plugin和maven-dependency-plugin插件打包

      1、在pom.xml中配置:

     1 <build>
     2     <plugins>
     3 
     4         <!-- 使用maven-jar-plugin和maven-dependency-plugin插件打包 -->
     5         <plugin>
     6             <groupId>org.apache.maven.plugins</groupId>
     7             <artifactId>maven-jar-plugin</artifactId>
     8             <version>3.1.0</version>
     9             <configuration>
    10                 <archive>
    11                     <manifest>
    12                         <addClasspath>true</addClasspath>
    13                         <classpathPrefix>lib/</classpathPrefix>
    14                         <mainClass>com.test.api.MyMain</mainClass>
    15                     </manifest>
    16                 </archive>
    17             </configuration>
    18         </plugin>
    19         <plugin>
    20             <groupId>org.apache.maven.plugins</groupId>
    21             <artifactId>maven-dependency-plugin</artifactId>
    22             <version>3.1.1</version>
    23             <executions>
    24                 <execution>
    25                     <id>copy-dependencies</id>
    26                     <phase>package</phase>
    27                     <goals>
    28                         <goal>copy-dependencies</goal>
    29                     </goals>
    30                     <configuration>
    31                         <outputDirectory>${project.build.directory}/lib</outputDirectory>
    32                     </configuration>
    33                 </execution>
    34             </executions>
    35         </plugin>
    36 
    37     </plugins>
    38 </build> 

        说明:

        maven-jar-plugin用于生成META-INF/MANIFEST.MF文件的部分内容,com.xx.Main指定MANIFEST.MF中的Main-Class,true会在MANIFEST.MF加上Class-Path项并配置依赖包,lib/指定依赖包所在目录。

        只是生成MANIFEST.MF文件还不够,maven-dependency-plugin插件用于将依赖包拷贝到${project.build.directory}/lib指定的位置,即lib目录下。

      2、使用maven命令:mvn clean package 打包

      3、target目录内容如下,多了lib目录

        

        反编译jar包,MANIFEST.MF文件内容如下:

        

      4、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT.jar,可以直接运行

        

    方法二:使用maven-assembly-plugin插件打包

      1、在pom.xml中配置:

     1 <build>
     2     <plugins>
     3 
     4         <!-- 使用maven-assembly-plugin插件打包 -->
     5         <plugin>
     6             <groupId>org.apache.maven.plugins</groupId>
     7             <artifactId>maven-assembly-plugin</artifactId>
     8             <version>3.2.0</version>
     9             <configuration>
    10                 <archive>
    11                     <manifest>
    12                         <mainClass>com.test.api.MyHttpRequest</mainClass>
    13                     </manifest>
    14                 </archive>
    15                 <descriptorRefs>
    16                     <descriptorRef>jar-with-dependencies</descriptorRef>
    17                 </descriptorRefs>
    18             </configuration>
    19             <executions>
    20                 <execution>
    21                     <id>make-assembly</id>
    22                     <phase>package</phase>
    23                     <goals>
    24                         <goal>single</goal>
    25                     </goals>
    26                 </execution>
    27             </executions>
    28         </plugin>
    29 
    30     </plugins>
    31 </build>

      2、使用maven命令:mvn clean package 打包

      3、target目录内容如下,多了test-mvn-package-1.0-SNAPSHOT-jar-with-dependencies.jar包

        

        反编译jar包,test-mvn-package-1.0-SNAPSHOT-jar-with-dependencies.jar内容如下:

        

        可以看到其中把第三方包的内容放到新的jar包中了

        不过,如果项目中用到hutool-all第三方包,用这种方式打出来的包运行时可能会出错,但实验中没有出现这种情况。项目中最好使用maven依赖源包

      4、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT.jar,无法运行

      5、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT-jar-with-dependencies.jar,可以直接运行

        

    方法三:使用maven-shade-plugin插件打包

      1、在pom.xml中配置:

     1 <build>
     2     <plugins>
     3 
     4         <!-- 使用maven-shade-plugin插件打包 -->
     5         <plugin>
     6             <groupId>org.apache.maven.plugins</groupId>
     7             <artifactId>maven-shade-plugin</artifactId>
     8             <version>3.2.3</version>
     9             <configuration>
    10                 <createDependencyReducedPom>false</createDependencyReducedPom>
    11             </configuration>
    12             <executions>
    13                 <execution>
    14                     <phase>package</phase>
    15                     <goals>
    16                         <goal>shade</goal>
    17                     </goals>
    18                     <configuration>
    19                         <transformers>
    20                             <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
    21                                 <mainClass>com.test.api.MyMain</mainClass>
    22                             </transformer>
    23                         </transformers>
    24                     </configuration>
    25                 </execution>
    26             </executions>
    27             </plugin>
    28 
    29     </plugins>
    30 </build>

      2、使用maven命令:mvn clean package 打包 

      3、target目录内容如下,多了original-test-mvn-package-1.0-SNAPSHOT.jar包

        

        反编译jar包,test-mvn-package-1.0-SNAPSHOT.jar内容如下:

        

        可以看到其中把第三方包的内容放到新的jar包中了

        不过,如果项目中用到hutool-all第三方包,用这种方式打出来的包运行时可能会出错,但实验中没有出现这种情况。项目中最好使用maven依赖源包

      4、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT.jar

        

  • 相关阅读:
    CVPR2020论文解读:3D Object Detection三维目标检测
    CVPR2020论文介绍: 3D 目标检测高效算法
    自动驾驶感知系统盘点
    CVPR2020论文解析:实例分割算法
    HttpContext
    c# ExecuteScalar()
    C#中DBNull.Value和Null的用法和区别
    Guid
    CommandType.Text
    数据可视化基础专题(三):Pandas基础(二) csv导入与导出
  • 原文地址:https://www.cnblogs.com/h--d/p/13060299.html
Copyright © 2020-2023  润新知