Maven 打包 jar 包的四种方式

点击数:16

说明

Maven 打包 jar 包可分为两种:可执行 jar 包和不可执行 jar 包。顾名思义,可执行就是可以通过命令启动程序:java -jar xxx-demo.jar,不可执行则使用该命令会报no main manifest attribute, in xxx.jar错误。

maven 打包 jar 包的四种方式

  • 可执行 jar 包的必要条件:
    1. 程序代码中必须要有 main 方法;
    2. 在 jar 包中META-INF/MANIFEST.MF中指定Main-Class;
    3. 要能加载到依赖包。
  • 不可执行 jar 包:
    1. 程序代码中是否有 main 方法无所谓
    2. 打成的 jar 包中META-INF/MANIFEST.MF中不会指定Main-Class。
    3. 依赖根据需要而决定。
  • 不可执行 agent jar 包:
    1. 程序中需要有 premain 方法
    2. 打成的 jar 包中META-INF/MANIFEST.MF中要指定Premain-Class 以及 Agent-Class。
    3. 依赖需要打包。

使用maven-shade-plugin插件打包

使用maven-shade-plugin打包,执行命令mvn clean package,会在 target 目录下生成两个 jar 文件:xxx-demo.jaroriginal-xxx-demo.jar,其中xx-demo是项目名称,当然这个名字会根据你的其他插件有所变化。没有 original 开头的 jar 包是包含了依赖jar 的,有 original 的则是不包含的。

需要注意的是,该插件打包依赖的时候,是把其他依赖文件的 class 文件连同包名一起拷贝到目标 jar 目录,并不是把依赖 jar 的 jar 包 copy 到目标 jar 目录下面。

├── org
│   └── objectweb
│       └── asm
│           ├── AnnotationVisitor.class
│           ├── AnnotationWriter.class
│           ├── Attribute.class
│           ├── ByteVector.class
│           ├── ClassAdapter.class
│           ├── ClassReader.class
│           ├── ClassVisitor.class
│           ├── ClassWriter.class

如上树状结构,是项目依赖asm:asm-all:3.1.jar包,打包后的目标 jar 里面的结构。

使用 maven-shade-plugin 插件时,某些情况下需要指定<id>标签,如果不指定则会出现如下错误:

shade for parameter resource: Cannot find ‘resource’ in
class org.apache.maven.plugins.shade.resource.ManifestResourceTransformer

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <!-- 如果不添加 ID 可能会出现下面的错误 -->
            <!--shade for parameter resource: Cannot find 'resource' in
            class org.apache.maven.plugins.shade.resource.ManifestResourceTransformer-->
            <id>share-my-jar</id>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <artifactSet>
                    <excludes>
                       <!-- 排除不想打包到目标包中的依赖 jar 包 -->
                        <exclude>com.google.code.findbugs:jsr305</exclude>
                        <exclude>org.slf4j:*</exclude>
                        <exclude>log4j:*</exclude>
                    </excludes>
                </artifactSet>
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                        </excludes>
                    </filter>
                </filters>
                <transformers>
                      <!-- 对于没有入口类的程序,可以不用该 transformer,注释掉即可 -->
                    <transformer
                            implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <!--  对于可执行 jar 包,添加入口类,两种方法均可以,如果没有入口,即不是可执行的 jar 包则不需要声明 -->
                        <!--方法 1 -->
                        <mainClass>com.openmind.asm.Main</mainClass>
                        <!-- 方法 2 -->
                        <!--<manifestEntries>-->
                            <!--<Main-Class>com.openmind.asm.Main</Main-Class>-->
                        <!--</manifestEntries>-->
                    </transformer>

                    <!-- 下面两条 transformer 标签均为在打包时添加的资源,此处是对于 spring 的配置,如果不用可以忽略-->
                    <transformer
                            implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer
                            implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>

使用maven-assembly-plugin打包

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.1.0</version>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <mainClass></mainClass>
            </manifest>
        </archive>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

上面配置后,执行mvn clean package 后会在 target 目录下生成一个xxx-jar-with-dependencies.jar文件,这个文件不但包含了自己项目中的代码和资源,还包含了所有依赖包的内容。所以可以直接通过java -jar来运行。

如果maven-assembly-plugin插件没有配置此段:

 <executions>
     <execution>
         <id>make-assembly</id>
         <phase>package</phase>
         <goals>
            <goal>single</goal>
         </goals>
     </execution>
 </executions>

则需要在执行命令的时候加上assembly:single,其中<phase>package</phase><goal>single</goal>表示在执行 package 打包时,执行 assembly:single,所以当配置 executions 的代码块后可以直接使用mvn package打包。

使用 maven-jar-plugin 和 maven-dependency-plugin 插件打包

maven-jar-plugin用于生成META-INF/MANIFEST.MF文件的部分内容,<mainClass>com.xxg.Main</mainClass>指定 MANIFEST.MF 中的 Main-Class,<addClasspath>true</addClasspath>会在MANIFEST.MF加上Class-Path项并配置依赖包,<classpathPrefix>lib/</classpathPrefix>指定依赖包所在目录,生成的信息如下:

Manifest-Version: 1.0
Implementation-Title: crack-agent
Implementation-Version: 0.0.1-SNAPSHOT
# 下面这写配置与javaagent 有关 
Premain-Class: com.openmind.asm.AgentMain
Agent-Class: com.openmind.asm.AgentMain
Can-Redefine-Classes: true
Can-Retransform-Classes: true
# 如果有 main 入口,则会有下面此项
Main-Class: com.openmind.asm.Main
# 依赖 jar 包路径
Class-Path: lib/asm-3.1.jar lib/asm-all-3.1.jar
Build-Jdk-Spec: 1.8
Created-By: Maven Archiver 3.4.0

上面生成的清单信息与下面的配置有关。

  • 与 Javaagent 有关的信息来自于 manifestEntries 配置标签相关
  • 与入口和依赖包有关的信息与 manifest 配置标签相关
  • 其他信息都是一些基本信息
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <!-- 默认就是盖目录,可以不配置 -->
        <classesDirectory>target/classes/</classesDirectory>
        <archive>
            <!-- manifestEntries 主要配置 Agent 相关的信息,如果没有 agent,则不需要次标签-->
            <!-- 关于 agent,此处说的是 javaagent 相关的信息或者 java attach 相关的知识点 -->
            <manifestEntries>
                <Agent-Class>com.openmind.asm.AgentMain</Agent-Class>
                <Premain-Class>com.openmind.asm.AgentMain</Premain-Class>
                <Can-Redefine-Classes>true</Can-Redefine-Classes>
                <Can-Retransform-Classes>true</Can-Retransform-Classes>
                <!--<Main-Class>com.openmind.asm.Main</Main-Class>-->
                <Class-Path>.</Class-Path>
            </manifestEntries>
            <!-- manifest 配置 class 的清单信息 -->
            <manifest>
                <addClasspath>true</addClasspath>
                <classpath-prefix>lib/</classpath-prefix>
                <mainClass>com.openmind.asm.Main</mainClass>
                <!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
                <useUniqueVersions>false</useUniqueVersions>
            </manifest>
        </archive>
    </configuration>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.1.1</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <type>jar</type>
                <includeTypes>jar</includeTypes>
                <includeScope>runtime</includeScope>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

maven-dependency-plugin插件用于将依赖包拷贝到<outputDirectory>${project.build.directory}/lib</outputDirectory>指定的位置,即lib目录下。

注意,此方式生成的 jar 包中并没有 lib 目录,而包含依赖包的 lib 目录在 target 目录下面,和生成的目标 jar 通同级。如果要执行该 jar 包,就需要将 lib 目录一同复制到环境目录。

“` toml
.
├── classes
│ └── com
│ └── openmind
│ └── asm
│ ├── AgentMain.class
│ ├── Main.class
│ ├── MyClassFileTransformer.class
│ ├── MyClassVistor.class
│ └── MyMethodVistor.class
├── crack-agent-0.0.1-SNAPSHOT.jar # 生成的目标 jar, crack-agent是项目名
└── lib # 依赖包目录
├── asm-3.1.jar
└── asm-all-3.1.jar

“`

不过这种方式生成jar包有个缺点,就是生成的jar包太多不便于管理,而使用maven-shade-plugin插件打包使用maven-assembly-plugin打包两种方式只生成单个jar文件,包含项目本身的代码、资源以及所有的依赖包。因此,就需要一种方式把 lib 包和目标 jar 整合在一起,那就是下面的使用maven-assembly-plugin引入配置打包

使用maven-assembly-plugin引入配置打包

不过,maven-assembly-plugin 插件大多数的时候还有另一种用法,需要额外配置一个 assembly.xml 文件配合该插件进行打包,该插件可以和maven-dependency-plugin一起使用,也可单独使用。

不管是哪一种,如果需要用到清单相关信息,就必须增加maven-jar-plugin插件:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <!-- manifestEntries 主要配置 Agent 相关的信息,如果没有 agent,则不需要次标签-->
      <!-- 关于 agent,此处说的是 javaagent 相关的信息或者 java attach 相关的知识点 -->
      <manifestEntries>
        <Agent-Class>com.openmind.asm.AgentMain</Agent-Class>
        <Premain-Class>com.openmind.asm.AgentMain</Premain-Class>
        <Can-Redefine-Classes>true</Can-Redefine-Classes>
        <Can-Retransform-Classes>true</Can-Retransform-Classes>
        <!--<Main-Class>com.openmind.asm.Main</Main-Class>-->
      </manifestEntries>
      <!-- manifest 配置 class 的清单信息 -->
      <manifest>
        <addClasspath>true</addClasspath>
        <!-- 注意,此处的 classpath 前缀一定要和打包资源后的依赖 jar 包保持一致-->
        <classpath-prefix>lib/</classpath-prefix> 
        <mainClass>com.openmind.asm.Main</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>
  • 单独使用maven-assembly-plugin
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.1.0</version>
    <configuration>
        <descriptors>
            <descriptor>assembly.xml</descriptor>
        </descriptors>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

下面是 assembly.xml 的内容:

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
    <id>dist</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <!-- 复制 directory 目录下的资源到 outputDirectory 指定的 bin 目录,bin 是打包后的文件中的一个目录-->
        <!-- 可以是任意资源,包括静态文件,jar 包等-->
        <fileSet>
            <directory>${project.build.directory}/dubbo/META-INF/assembly/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <fileMode>0755</fileMode>
        </fileSet>
    </fileSets>

    <!-- 该标签主要收集项目的依赖包,包括自身的 jar 包,然后打包时复制到 outputDirectory 指定的目录-->
    <!-- 此处有个细节,加入自身的编译包名为 xxx-demo-SNAPSHOT-0.0.1.jar,复制的时候也是这个名字-->
    <!-- 而我们再 bulid 标签中指定的 finalName 此时还没有生效-->
    <dependencySets>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
        </dependencySet>
    </dependencySets>
    <files>
        <file>
             <!-- 在这里 bulid 标签中指定的 finalName 才生效-->
            <!-- 将 finalName 指定的名字的 jar 复制到压缩包的 outputDirectory 指定的目录 -->
            <source>core/target/${project.build.finalName}.jar</source>
            <outputDirectory>.</outputDirectory>
            <filtered>false</filtered>
        </file>
    </files>

</assembly>

上面的配置打包会出现什么问题呢?就是自身的 jar 包打了两遍。第一遍是在<dependencySet>标签中引入了一个包含版本号的 jar 包,第二次引入在<file>标签中。当然,<file>标签是可以不要的。我们把压缩包xxx-demo-dist.tar.gz解压之后就会发现文件结构(此处项目名为crack-agent,在 build 标签中配置 finalName 为 crack-agent):

.
├── crack-agent.jar
└── lib
    ├── asm-3.1.jar
    ├── asm-all-3.1.jar
    └── crack-agent-0.0.1-SNAPSHOT.jar

我们再解压目录执行java -jar crack-agent.jar运行 ok!

  • 配合maven-dependency-plugin使用
 <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-dependency-plugin</artifactId>
   <version>3.1.1</version>
   <executions>
     <execution>
       <!-- 如果在打包的时候需要依赖其他包的一些资源信息,那就需要解包,将信息复制到指定的目录-->
       <id>unpack</id>
       <phase>package</phase>
       <goals>
         <goal>unpack</goal>
       </goals>
       <configuration>
         <artifactItems>
           <artifactItem>
             <groupId>com.alibaba</groupId>
             <artifactId>dubbo</artifactId>
             <version>2.5.3</version>
             <outputDirectory>${project.build.directory}/dubbo</outputDirectory>
             <includes>META-INF/assembly/**</includes>
           </artifactItem>
         </artifactItems>
       </configuration>
     </execution>
     <execution>
       <!-- copy 依赖包-->
       <id>copy-dependencies</id>
       <phase>package</phase>
       <goals>
         <goal>copy-dependencies</goal>
       </goals>
       <configuration>
         <outputDirectory>${project.build.directory}/lib</outputDirectory>
       </configuration>
     </execution>
   </executions>
</plugin>
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>3.1.0</version>
  <configuration>
    <descriptors>
      <descriptor>assembly.xml</descriptor>
    </descriptors>
    <archive>
      <manifest>
        <mainClass>com.openmind.asm.AgentMain</mainClass>
      </manifest>
    </archive>
  </configuration>
  <executions>
    <execution>
      <id>make-assembly</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
</plugin>

下面是新配置的 assembly.xml(主要删除了<dependencySets>的配置信息):

<assembly>
    <id>dist</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/dubbo/META-INF/assembly/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <fileMode>0755</fileMode>
        </fileSet>
        <fileSet>
            <directory>target/lib</directory>
            <outputDirectory>lib</outputDirectory>
            <fileMode>0755</fileMode>
            <includes>
                <include>%regex[^((?!sources).)*\.jar$]</include>
            </includes>
        </fileSet>
    </fileSets>
    <files>
        <!-- 将 target/${project.build.finalName}.jar 文件添加到最后的压缩包中-->
        <file>
            <source>target/${project.build.finalName}.jar</source>
            <!-- 研所包的根目录-->
            <outputDirectory>.</outputDirectory>
            <filtered>false</filtered>
        </file>
    </files>
</assembly>

我们可以考到压缩包中内容如下:

.
├── bin
│   ├── dump.sh
│   ├── restart.sh
│   ├── server.sh
│   ├── start.bat
│   ├── start.sh
│   └── stop.sh
├── crack-agent.jar
└── lib
    ├── asm-3.1.jar
    └── asm-all-3.1.jar

配合maven-dependency-plugin的好处是,处理资源更加灵活了,想用哪里的资源就去哪里获取资源,我可以 unpack拿取其他 jar 包的配置信息,我也可以 copy-dependencies,复制其他 jar 包。

spring-boot-maven-plugin+maven-dependency-plugin打包

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.1.1</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <type>jar</type>
                <includeTypes>jar</includeTypes>
                <includeScope>runtime</includeScope>
                <outputDirectory>
                    ${project.build.directory}/libs
                </outputDirectory>
                <!-- 配置不需要打包的模块,但是该模块的 jar 包会被打入到上面的 libs 目录 -->
                <excludeArtifactIds>demo-client</excludeArtifactIds>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.0.0.RELEASE</version>
    <configuration>
        <fork>true</fork>
        <mainClass>cn.xxx.yyy.AppMain</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

spring-boot-maven-plugin 插件打包,会将依赖的 jar 包打包到目标 jar 一起。只针对 springboot 项目。打包jar 解压后看到如下目录层级:

.
├── BOOT-INF
│   ├── classes
│   │   ├── app.xml
│   │   ├── application-default.properties
│   │   ├── cn
│   │   ├── logback-spring.xml
│   │   ├── mybatis
│   │   └── spring
│   └── lib
│       ├── HdrHistogram-2.1.10.jar
│       ├── android-json-0.0.20131108.vaadin1.jar
│       ├── ... 省略 N 行
│       ├── spring-boot-2.0.0.RELEASE.jar
│       ├── spring-boot-actuator-2.0.0.RELEASE.jar
│       ├── spring-boot-actuator-autoconfigure-2.0.0.RELEASE.jar
│       ├── spring-boot-autoconfigure-2.0.0.RELEASE.jar
│       ├── spring-boot-starter-2.0.0.RELEASE.jar
│       └── zookeeper-3.4.8.jar
├── META-INF
│   ├── MANIFEST.MF
│   └── maven
│       └── org.springframework.boot
└── org
    └── springframework
        └── boot
            └── loader
                ├── ExecutableArchiveLauncher.class
                ├── JarLauncher.class
                ├── LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
                ├── LaunchedURLClassLoader.class
                ├── Launcher.class
                ├── MainMethodRunner.class
                ├── PropertiesLauncher$1.class
                ├── PropertiesLauncher$ArchiveEntryFilter.class
                ├── PropertiesLauncher$PrefixMatchingArchiveFilter.class
                ├── PropertiesLauncher.class
                ├── WarLauncher.class
                ├── archive
                ├── data
                ├── jar
                └── util

如果需要分离将依赖包和目标 jar 包分离,需要注释掉spring-boot-maven-plugin包,加入maven-jar-plugin包:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <classesDirectory>target/classes/</classesDirectory>
        <archive>
            <manifest>
                <mainClass>com.tsingning.worksite.Application</mainClass>
                <!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
                <useUniqueVersions>false</useUniqueVersions>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
            </manifest>
            <manifestEntries>
                <Class-Path>.</Class-Path>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

关于maven-jar-plugin更多细节,可以参考上面其他组合的配置。

其他插件

maven-compiler-plugin 编译插件

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <source>${maven.compiler.source}</source>
        <target>${maven.compiler.target}</target>
    </configuration>
</plugin>

proguard-maven-plugin 代码混淆插件

<plugin>
    <groupId>com.github.wvengen</groupId>
    <artifactId>proguard-maven-plugin</artifactId>
    <version>2.0.11</version>
    <executions>
        <execution>
            <!-- 混淆时刻,这里是打包的时候混淆-->
            <phase>package</phase>
            <goals>
                <!-- 指定使用插件的混淆功能 -->
                <goal>proguard</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- 是否将生成的PG文件安装部署-->
        <attach>true</attach>
        <!-- 是否混淆-->
        <obfuscate>true</obfuscate>
        <!-- 指定生成文件分类 -->
        <attachArtifactClassifier>pg</attachArtifactClassifier>
        <proguardInclude>${basedir}/proguard.conf</proguardInclude>
        <libs>
            <lib>${java.home}/lib/rt.jar</lib>
            <lib>${java.home}/lib/jce.jar</lib>
        </libs>
        <!-- 对什么东西进行加载,这里仅有classes成功,不可能对配置文件及JSP混淆吧-->
        <injar>classes</injar>
        <outjar>kara-pg.jar</outjar>
        <!-- 输出目录-->
        <outputDirectory>${project.build.directory}</outputDirectory>
    </configuration>
</plugin>

maven-surefire-plugin 测试用例插件

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.18.1</version>
    <configuration>
        <argLine>${argLine} -Xmx1024m</argLine>
        <threadCount>1</threadCount>
        <properties>
            <property>
                <name>junit</name>
                <value>false</value>
            </property>
        </properties>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-testng</artifactId>
            <version>3.0.0-M1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-junit47</artifactId>
            <version>3.0.0-M1</version>
        </dependency>
    </dependencies>
</plugin>

jacoco-maven-plugin 单元测试覆盖率

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.0</version>
    <executions>
        <execution>
            <id>default-prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>default-report</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据