blog/source/_posts/maven-plugins-in-common-use.md
2021-06-16 11:50:09 +08:00

430 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 常用的Maven插件记录
tags:
- JVM
- Java
- Maven
- Plugins
categories:
- - JVM
- 构建工具
keywords: 'maven,plugins,插件'
date: 2021-06-10 17:32:15
---
Maven是一个依赖插件执行的框架每个任务实际上都是由插件完成的。<!-- more -->插件通常提供的是一个目标goal的集合也就是命令行格式`mvn [options] [goals] [phases]`中的`[goals]`。要执行一个插件的目标,可以使用命令格式`mvn [plugin-name]:[goal-name]`,例如`mvn jetty:run`。
在Maven中有Build和Report两种类型的插件其中Build用于在构建时执行Report用于在网站生成过程中执行。
每个插件可以有多个目标,插件可以使用`phase`元素来定义执行时机。要执行的任务则需要绑定到插件的目标上来执行。以下给出一个示例。
```xml
<build>
<plugins>
<plugin>
<!--引入要使用的插件-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<!--定义要执行的动作-->
<executions>
<execution>
<id>on.clean</id>
<!--激活的阶段-->
<phase>clean</phase>
<!--激活的目标-->
<goals>
<goal>run</goal>
</goals>
<configuration>
<!--绑定到目标的任务-->
<tasks>
<echo>Now in clean phase.</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
```
!!! info "plugins和pluginManagemen标签的区别"
`plugins`和`pluginManagement`两个标签都是`build`标签的直接子元素而且大部分POM文件中都可以看到它们。但是这两个标签的使用是有区别的其中`pluginManagement`标签所声明的插件并不会被Maven所使用它的作用主要是提供对于所有继承了当前POM的子POM中所使用的插件的版本。而`plugins`则是将插件实实在在的应用到Maven生命周期中的。换句话说如果项目是由多个POM文件组成的那么可以使用`pluginManagement`来约束各个POM文件中所使用的插件版本如果只有一个POM文件那么可以仅使用`plugins`声明插件的使用即可。
## maven-compiler-plugin
Compiler插件主要用来编译项目源码。在POM中一般用来配置编译所接受的源码版本和编译后能够适应的Java运行时版本。代码版本的配置有两种方式一种是通过配置项指定一种是通过配置插件指定。
以下是通过配置项指定的示例。
```xml
<project>
<properties>
<!--源代码所使用的语言版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<!--编译后要使用的 Java 运行时版本-->
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
```
或者可以直接配置插件。
```xml
<project>
<build>
<plugins>
<plugin>
<!--groupId 是 org.apache.maven.plugins 的插件,可以省略书写 groupId-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
```
## maven-antrun-plugin
Antrun插件用来在一些指定阶段中运行Ant任务并且对书写在POM中的Ant任务提供支持。Antrun插件在前面一些章节已经有所接触其具体使用格式如下。
```xml
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase><!--指定激活阶段--></phase>
<configuration>
<target><!--编写要执行的 Ant 任务--></target>
</configuration>
<goals>
<!-- Antrun 插件只提供了一个目标-->
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
```
## maven-jar-plugin
Jar插件主要用来增强构建Jar包的功能为Jar包中增加`MANIFEST.MF`文件,或者通过提供`MANIFEST.MF`中所需的内容来自动构建`MANIFEST.MF`文件。
以下示例可以打包一个可执行的Jar包。
```xml
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.example.MainApp</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
```
配置好的项目可以通过命令`mvn jar:jar`来完成打包。
## maven-shade-plugin
Shade插件是用来建立Uber-JarFatJar的。Uber-Jar将所有的依赖都包含在了Jar包中在运行时可以不受外界运行时环境的影响。Shade插件提供了两个目标但其中只有`shade:shade`是用来打包的。
使用以下最简单的配置就可以打出一个Uber-Jar包。
```xml
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
```
要创建一个可执行的Jar包就需要指定主类主类是在`execution`元素中的`configuration`元素中定义的。
```xml
<execution>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resources.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.example.MainApp</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
```
常用的`Transformer`类都定义在`org.apache.maven.shade.resources`包中,主要有以下这些。
* `AppendingTransformer`,向资源中添加一个内容。
* `IncludeResourcesTransformer`,向项目中添加文件。
* `ManifestResourcesTransformer`,向`MANIFEST.MF`中设定内容。
* `XmlAppendingTransformer`向XML资源中添加一个XML文件。
除此之外,`configuration`元素中还可以使用以下子元素来实现相应的功能。
* `filters/filter/[includes|excludes]`过滤Jar包中的类或者资源。
* `artifactSet/[includes|excludes]`指定需要打包的Jar。
* `minimizedJar`,自动排除不使用的类。
## maven-assembly-plugin
Assembly插件是用来执行定制化打包操作的。Assembly插件提供了两种打包方式第一种是通过`descriptorRefs`元素来指定使用官方统一定制的打包方式,常用的主要有`bin`、`jar-with-dependencies`、`src`等。
官方统一定制的打包方式可以使用以下方式配置。
```xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
```
另一种定制打包方式是使用`descriptors`元素来指定打包配置文件,通过配置文件来定制打包操作。这种方式的用法如下例所示。
```xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<descriptors>
<descriptor>src/assembly/src.xml</descriptor>
</descriptors>
</configuration>
</plugin>
```
打包配置文件也是一个XML文件以下是其中可以使用的示例格式以及各个元素的含义更详细的配置文件格式需要参考[Assembly插件](https://maven.apache.org/plugins/maven-assembly-plugin/assembly.html)的文档。
```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></id>
<!--输出的打包格式,可以同时指定多种-->
<!--可选格式有 zip、tar、tar.bz、jar、dir、war 等-->
<formats>
<format></format>
</formats>
<!--定制项目依赖的打包方式-->
<dependencySets>
<dependencySet>
<!--相对于根目录的包依赖目录-->
<outputDirectory></outputDirectory>
</dependencySet>
</dependencySets>
<!--指定一组文件的存放位置-->
<fileSets>
<fileSet>
<outputDirectory></outputDirectory>
<!--设定要包含的文件-->
<includes>
<include></include>
</includes>
<!--设定要排除的文件-->
<excludes>
<exclude></exclude>
</excludes>
<fileMode>0755</fileMode>
</fileSet>
</fileSets>
<!--包含指定文件到指定目录-->
<files>
<file>
<!--相对于根目录的源文件路径-->
<source></source>
<outputDirectory></outputDirectory>
<!--在指定目录中的名称-->
<destName></destName>
<fileMode></fileMode>
</file>
</files>
</assembly>
```
## exec-maven-plugin
Exec插件主要用来支持Maven快速启动Java程序可以在不打包为Jar文件时快捷的启动程序而无需等待漫长的打包时间。Exec插件提供了两个目标可供使用`exec:java`和`exec:exec`。其中`exec:java`可以用来启动比较简单不需要复杂命令行配置的Java应用而`exec:exec`则更适合于启动需要复杂配置的应用。
以下配置了`exec:java`目标来启动Java应用。
```xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<verion>1.6.0</verion>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.MainApp</mainClass>
<!--命令行参数-->
<arguements>
<arguement>...</arguement>
</arguements>
<!--配置文件参数,相当于使用 -D 参数-->
<systemProperties>
<systemProperty>
<key></key>
<value></value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>
```
使用`exec:exec`目标就更加复杂,但可以更加灵活。
```xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<verion>1.6.0</verion>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<workingDirectory><!--工作目录--></workingDirectory>
<arguements>
<arguement><!--命令行参数--></arguement>
</arguements>
</configuration>
</plugin>
```
## jpackage-maven-plugin
jpackage插件是一个第三方插件用来调用JDK 14以后引入的jpackage命令来将经过裁剪生成的最简运行时打包为可在不同平台上直接运行的程序包的。jpackage插件值提供了一个目标可供使用`jpackage:jpackage`。因为不是所有的JDK都带有jpackage命令所以在使用jpackage插件的时候需要配置的内容主要是jpackage所在的JDK目录以及所需要打包的Runtime。
以下是一个打包已经使用jlink裁剪好的Runtime的示例。
```xml
<plugins>
<plugin>
<groupId>com.github.akman</groupId>
<artifactId>jpackage-maven-plugin</artifactId>
<version>0.1.2</version>
<configuration>
<!--
设定jpackage命令所在的JDK位置如果不设定这一配置插件将会按照以下顺序寻找jpackage工具。
- 使用Toolchain插件定义的JDK目录
- 使用系统环境变量JAVA_HOME定义的JDK目录
- 由系统环境变量PATH定义的可执行文件目录
-->
<toolhome>${env.JPACKAGE_HOME}</toolhome>
<!--
定义生成的文件放置的位置
-->
<dest>${project.build.directory}/jpackage</dest>
<!--
定义存放应用的子目录名称
-->
<name>appname</name>
<!--
定义要生成的应用包的类型,可选值有:
- PLATFORM根据当前平台确定
- IMAGE生成Linux或macOS使用的应用镜像
- EXE生成可执行文件
- MSI生成Windows应用安装包
-->
<type>IMAGE</type>
<!--
定义已经由jlink工具生成的运行时所在的位置如果没有定义这个配置项
那么插件将会使用以下参数调用jlink生成一个运行时
- strip-debug
- no-header-files
- no-man-pages
- strip-native-commands
-->
<runtimeimage>${project.build.directory}/jlink/runtime-image</runtimeimage>
<!--
定义要生成的应用的版本
-->
<appversion>1.0</appversion>
<!--
定义索要生成的应用的版权信息
-->
<copyright>Copyright</copyright>
<!--
定义所要生成的应用的描述信息
-->
<description>Description</description>
<!--
定义索要生成的应用的制作商信息
-->
<vendor>Vendor</vendor>
<!--
定义索要生成的应用要使用的图标所在的位置
-->
<icon>${project.basedir}/config/jpackage/resources/appname.ico</icon>
<!--
定义应用的主模块名称,以及应用的主类。当设置了这个配置项之后,应用的主模块会被连接到运行时镜像,
这里可以填写的内容可以是模块名称也可以是Jar包名称但不能同时使用。
-->
<module>appModuleName/appClassName</module>
<!--
定义主函数运行所需的参数
-->
<arguments>--opt</arguments>
<!--
定义运行时所需要的参数
-->
<javaoptions>-Dfile.encoding=UTF-8 -Xms256m -Xmx512m</javaoptions>
<!--
定义其他额外的启动器
-->
<addlaunchers>
<addlauncher>
<name>appname-cli</name>
<module>appModuleName/appClassName</module>
<arguments>--help</arguments>
<javaoptions>-Xms256m -Xmx512m</javaoptions>
<appversion>1.0</appversion>
<icon>${project.basedir}/config/jpackage/resources/appname-cli.ico</icon>
<winconsole>true</winconsole>
</addlauncher>
</addlaunchers>
<!--
定义jpackage所使用的资源目录名称
-->
<resourcedir>${project.basedir}/config/jpackage/resources</resourcedir>
</configuration>
</plugin>
</plugins>
```