Maven 核心插件详解

maven-clean-plugin

该插件只有一个插件目标:clean:clean,用于尝试清除项目工作目录中因构建而生成的文件。默认情况下,它会发现并删除在 project.build.directoryproject.build.outputDirectoryproject.build.testOutputDirectoryproject.reporting.outputDirectory 所配置的目录。

通过配置 <filesets/> 元素也可以删除默认目录以外的文件。

clean:clean 插件目标

可选参数

  • <excludeDefaultDirectories> 。删除时排除项目的默认输出目录。如果设置为 true(默认为 false),则仅删除通过 <filesets> 元素选择的文件和目录。从 3.0.0 版本开始,对应的 property 名称已从 clean.excludeDefaultDirectories 变为 maven.clean.excludeDefaultDirectories

  • <failOnError>。如果在删除时出现错误,是否仍继续进行构建。

  • <filesets>。指定除默认目录外,要删除的文件集列表。例如:

    <filesets>
      <fileset>
        <directory>src/main/generated</directory>
        <followSymlinks>false</followSymlinks>
        <useDefaultExcludes>true</useDefaultExcludes>
        <includes>
          <include>*.java</include>
        </includes>
        <excludes>
          <exclude>Template*</exclude>
        </excludes>
      </fileset>
    </filesets>
    
  • <followSymLinks>。从项目默认输出目录中删除文件时是否应遵循符号链接。默认为 false不遵循符号链接需要更多 IO 操作和堆内存,而不管符号链接是否实际存在。因此,如果项目的输出目录很大,并且故意不包含符号链接,则可以通过将此参数设置为 true 来提高性能。从 3.0.0 版本开始,该属性已从clean.followSymLinks 重命名为 maven.clean.followSymLinks

  • <retryOnError>。指示如果第一次尝试删除失败,则是否应进行再次尝试(在短暂延迟后)删除文件。这是为了帮助删除由第三方工具(如病毒扫描程序或搜索索引)临时锁定的文件。

  • <skip>。禁用插件的执行。从 3.0.0 版本开始,对应的 property 已从 clean.skip 重命名为 maven.clean.skip

  • <verbose>。设置插件是否以详细模式运行。从 2.3 版本开始,默认值来自 Maven 的全局 debug 标志(命令行开关 -X)。从 3.0.0 版本开始,该 property 已从 clean.verbose 重命名为 maven.clean.verbose

示例

删除未向 Maven 公开的其他文件

默认情况下,Maven Clean 插件将删除 ${basedir}/src/target 目录。您可以将其配置为删除其他目录和文件。比如:

<build>
  [...]
  <plugin>
    <artifactId>maven-clean-plugin</artifactId>
    <version>3.1.0</version>
    <configuration>
      <filesets>
        <fileset>
          <directory>some/relative/path</directory>
          <includes>
            <include>**/*.tmp</include>
            <include>**/*.log</include>
          </includes>
          <excludes>
            <exclude>**/important.log</exclude>
            <exclude>**/another-important.log</exclude>
          </excludes>
          <followSymlinks>false</followSymlinks>
        </fileset>
      </filesets>
    </configuration>
  </plugin>
  [...]
</build>

注意:文件集中的目录是项目中的相对路径,换句话说,

<directory>some/relative/path</directory>

相当于:

<directory>${basedir}/some/relative/path</directory>

您还可以在父 POM 中定义文件集规则。

跳过 Clean 的执行

要跳过为特定项目的 clean 操作,则请将 skip property 设置为 true

<build>
  [...]
    <plugin>
      <artifactId>maven-clean-plugin</artifactId>
      <version>3.1.0</version>
      <configuration>
        <skip>true</skip>
      </configuration>
    </plugin>
  [...]
</build>

通过执行以下命令,也可以通过命令行跳过 clean:

mvn clean -Dmaven.clean.skip=true

忽略 Clean 错误

要在为特定项目运行 clean 时忽略错误,请将 failOnError property 设置为 false

<build>
  [...]
    <plugin>
      <artifactId>maven-clean-plugin</artifactId>
      <version>3.1.0</version>
      <configuration>
        <failOnError>false</failOnError>
      </configuration>
    </plugin>
  [...]
</build>

您还可以通过执行以下命令,通过命令行忽略 clean 时的错误:

mvn clean -Dmaven.clean.failOnError=false

maven-resources-plugin

资源插件负责将项目资源到输出目录。Maven 项目有两种不同的资源:主资源和测试资源。区别在于,主资源(默认在 src/main/resources 目录)是与主源代码(位于 src/main/java 目录下)关联的资源,而测试资源(默认在 src/test/resources 目录)与测试源代码(位于 src/main/test 目录下)关联。从 2.3 版本开始,该插件可以使用 Maven 过滤组件来过滤资源。

资源插件将 resource 元素所指定的文件复制到输出目录。以下三个插件目标仅在指定资源和输出目录的 XML 元素的方式上有所不同。

resources:resources 插件目标

该插件目标的全称为 org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources,主要负责将主源代码的资源复制到主输出目录。该目标通常自动执行,因为它默认绑定到 process-resources 生命周期阶段。它始终使用project.build.resources 元素来指定资源,默认情况下使用 project.build.outputDirectory property 来指定输出目录。

必选参数

  • <outputDirectory>。要将资源复制到其中的输出目录。默认为 ${project.build.outputDirectory} property 的值。

可选参数

  • <addDefaultExcludes>。默认情况下,会排除 .gitignore.cvsignore 等文件,这意味着不会复制这些文件。如果您出于特定原因需要它们,可以通过将此设置为 false 来实现(默认为 true)。这意味着将复制以下所有文件:

    • 杂项:**/*~**/#*#**/.#***/%*%**/._*
    • CVS:**/CVS**/CVS/****/.cvsignore
    • RCS:**/RCS**/RCS/**
    • SCCS:**/SCCS**/SCCS/**
    • VSSercer:**/vssver.scc
    • MKS: **/project.pj
    • SVN:**/.svn**/.svn/**
    • GNU:**/.arch-ids**/.arch-ids/**
    • Bazaar:**/.bzr**/.bzr/**
    • SurroundSCM:**/.MySCMServerInfo
    • Mac:**/.DS_Store
    • Serena Dimension:**/.metadata**/.metadata/**
    • Mercurial:**/.hg**/.hg/**
    • GIT:**/.git**/.gitignore**/.gitattributes**/.git/**
    • Bitkeeper:**/BitKeeper**/BitKeeper/****/ChangeSet**/ChangeSet/**
    • Darcs:**/_darcs**/_darcs/****/.darcsrepo**/.darcsrepo/****/-darcs-backup***/.darcs-temp-mail
  • <delimiters>。指定在资源中进行筛选的表达式的分隔符。这些分隔符以 beginToken*endToken 的形式指定。如果未给出 *,则假定起始和结束的分隔符相同。因此,可以将默认筛选分隔符指定为:

    <delimiters>
      <delimiter>${*}</delimiter>
      <delimiter>@</delimiter>
    </delimiters>
    

    因为 @ 分隔符在两端都是相同的,所以我们不需要指定 @*@(尽管我们可以)。

  • <encoding>。读取和写入筛选资源时要使用的字符编码。默认使用 ${project.build.sourceEncoding} property 的值。

  • <escapeString>。前面带有此字符串的表达式将不会被插值。在此字符串前面的任何其他内容都将原封不动地通过。例如,\${foo} 将替换为 ${foo},但如果此参数已设置为反斜杠,则 \${foo} 将替换为 \\value-of-foo

  • <escapeWindowsPaths>。是否在windows样式路径中转义反斜杠和冒号。默认为 true

  • <fileNameFiltering>。支持过滤文件名、文件夹等。

  • <filters>。要与 POM build/filters 部分中指定的系统属性、项目属性和过滤器属性一起使用的额外属性文件列表,这些文件应在当前 Mojo 执行期间用于过滤。通常,这些将在插件的 execution 部分进行配置,从而为特定 execution 提供一组不同的过滤器。例如,从 Maven 2.2.0 开始,您可以选择使用 default-resourcesdefault-testResources 来为两种不同类型的资源提供不同的配置。通过提供 extraFilters 配置,您可以区分哪些筛选器用于哪种类型的资源。

  • <includeEmptyDirs>。复制 resources 元素中包含的任何空目录。默认为 false

  • <mavenFilteringHints>。实现了 MavenResourcesFiltering.filterResources() 的 plexus 组件提示列表。它们将在资源复制/筛选后执行。为 java.util.List 类型。

  • <nonFilteredFileExtensions>。不进行过滤的文件扩展名列表(已定义为:jpgjpeggifbmppng)。为 java.util.List 类型。

  • <overwrite>。覆盖现有文件,即使目标文件较新。默认为 false

  • <propertiesEncoding>。读取和写入过滤属性文件时要使用的字符编码。如果未指定,它将默认为 encoding 参数的值。

  • <skip>。如果需要,可以跳过插件的执行。不推荐使用,但有时使用起来相当方便。默认为 false

  • <supportMultiLineFiltering>。停止搜索行末尾的 endToken。默认为 false

  • <useBuildFilters>。如果为 false,则在处理此 Mojo 执行中的资源时,不要使用 POM 的 build/filters 部分中指定的过滤器。默认为 true

  • <useDefaultDelimiters>。除了自定义分隔符(如果有)之外,还使用默认分隔符。默认为 true

resources:testResources 插件目标

该插件目标的全称为 org.apache.maven.plugins:maven-resources-plugin:3.2.0:test-Resources,主要负责将测试源代码的资源复制到测试输出目录。该插件目标通常自动执行,因为默认情况下它与 process-test-resources 生命周期阶段相关联。它总是使用 project.build.testResources 元素指定资源,默认情况下使用 project.build.testOutputDirectory property 指定要输出的目录。

必选元素

  • <outputDirectory>。要将资源复制到其中的输出目录。默认使用 ${project.build.testOutputDirectory} property 的值。
  • <resources>。要转移的资源列表。默认使用 ${project.testResources} property 的值。

可选参数

该插件目标支持的可选元素与 resources:resources 插件目标支持的可选元素相同。

resources:copy-resources 插件目标

该插件目标的全称为 org.apache.maven.plugins:maven-resources-plugin:3.2.0:copy-resources,主要负责将资源复制到输出目录。此目标要求您配置要复制的资源,并指定输出目录。

必选元素

  • <outputDirectory>。要将资源复制到其中的输出目录。
  • <resources>。要转移的资源列表。

可选参数

该插件目标支持的可选元素与 resources:resources 插件目标支持的可选元素相同。

示例

指定字符编码

可以选择 ASCII、UTF-8 或 UTF-16 等字符编码方案用于文件的读写。最佳实践是通过 ${project.build.sourceEncoding} property 来定义用于复制筛选资源的编码,该 property 应在 POM 的 properties 部分中定义,如下所示:

<project ...>
 ...
 <properties>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   ...
 </properties>
 ..
</project>

通过使用上述 property,maven-resources-plugin 将自动使用此编码。有时,为了不同的目的,您需要显式地更改编码。这可以通过如下配置定义编码来实现:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          ...
          <encoding>UTF-8</encoding>
          ...
        </configuration>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

指定资源目录

默认情况下,Maven 将在 src/main/resources 下查找项目的资源:

Project
|-- pom.xml
`-- src
    `-- main
        `-- resources

但是,您的所有资源可能不在 src/main/resources 中。因此,您必须通过向 POM 添加以下内容来指定这些目录。

<project>
 ...
 <build>
   ...
   <resources>
     <resource>
       <directory>[your folder here]</directory>
     </resource>
   </resources>
   ...
 </build>
 ...
</project>

因此,如果您的资源驻留在 src/my-resources 中:

Project
|-- pom.xml
`-- src
    `-- my-resources

可以通过执行以下操作指定该目录:

   ...
   <resources>
     <resource>
       <directory>src/my-resources</directory>
     </resource>
   </resources>
   ...

此外,通过添加多个 <resource> 元素,您可以拥有多个目录:

   ...
   <resources>
     <resource>
       <directory>resource1</directory>
     </resource>
     <resource>
       <directory>resource2</directory>
     </resource>
     <resource>
       <directory>resource3</directory>
     </resource>
   </resources>
   ...

过滤

在资源中可以包含变量。这些由 ${…} 分隔符表示的变量可以来自系统属性、项目属性、过滤器资源和命令行。例如,如果我们有一个资源src/main/resources/hello.txt,其中包含:

src/main/resources/hello.txt

还有像这样的 POM:

<project>
  ...
  <name>My Resources Plugin Practice Project</name>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>src/main/resources</directory>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>

通过调用命令:mvn resources:resources,这将在 target/classes/hello.txt 中创建一个包含完全相同文本的资源输出:

Hello ${name}

但是,如果我们向 POM 添加 <filtering> 元素并将其设置为 true,如下所示:

      ...
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
      ...

我们的 target/classes/hello.txt 文件在调用 mvn resources:resources 命令之后其内容如下:

Hello My Resources Plugin Practice Project

这是因为 name 变量被替换为项目名称的值(在 POM 中指定)。此外,我们还可以使用 -D 选项通过命令行来指定该值。例如,要将变量名的值更改为“world”,只需调用命令:mvn resources:resources -Dname="world"。则 target/classes/hello.txt 中的输出为:

Hello world

此外,我们不限于使用预定义的项目变量。我们可以在 <properties> 元素中指定自己的变量及其值。例如,如果要将变量从“name”更改为“your.name”,可以通过在 <properties> 元素中添加 <your.name> 元素来实现。如下所示:

<project>
  ...
  <properties>
    <your.name>world</your.name>
  </properties>
  ...
</project>

但是为了组织项目,您可能希望将所有变量及其值放在一个单独的文件中,这样您就不必重写 POM,也不必在每次构建时始终设置它们的值。这可以通过添加过滤器来实现。

<project>
  ...
  <name>My Resources Plugin Practice Project</name>
  ...
  <build>
    ...
    <filters>
      <filter>[a filter property]</filter>
    </filters>
    ...
  </build>
  ...
</project>

例如,我们可以通过指定包含以下内容的筛选文件 my-filter-values.properties 将“your.name”与 POM 分开:

your.name = world

并将该文件路径添加到我们的 POM 中:

    ...
    <filters>
      <filter>my-filter-values.properties</filter>
    </filters>
    ...

注意:不要过滤含有二进制内容的文件,如图像文件,这极有可能损坏这些二进制文件!

如果同时有文本文件和二进制文件作为资源,建议使用两个单独的文件夹。一个文件夹 src/main/resources(默认)用于未筛选的资源,另一个文件夹src/main/resources-filtered 用于筛选的资源。

<project>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>src/main/resources-filtered</directory>
        <filtering>true</filtering>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>

现在,您可以将不应过滤的文件放入 src/main/resources 目录中,将其他文件放入需要过滤的 src/main/resources-filtered 目录中。如前所述,过滤图像、pdf 等二进制文件可能损坏这些二进制文件。为了防止此类问题,您可以配置不会被过滤的文件扩展名

过滤 properties 文件

在筛选资源时,如果要筛选 properties 文件,则必须特别小心。如果筛选的属性文件包含非 ASCII 字符,并且 project.build.sourceEncoding 设置为 ISO-8859-1 以外的任何其他值,则可能会受到影响。Maven 资源插件在 3.2.0 版本之前默认在过滤资源时使用 project.build.sourceEncoding property 的值作为编码。因此,除非您在 Maven 资源插件中显式配置了 encoding 参数来覆盖 project.build.sourceEncoding property 的值来作为编码。

当 Properties 类用于读取和写入 properties 文件时,它们要求 properties 文件使用 ISO-8859-1 编码。Java11 的情况仍然如此,如 Properties 类的 API 文档所示。因此,以这种方式使用的 properties 文件需要使用 ISO-8859-1 编码。

当 properties 文件用作 ResourceBundle(属性资源包)时,不同版本的 Java 所需的编码不同。在 Java 8 之前(包括 Java 8),这些文件需要使用 ISO-8859-1 编码。从 Java 9 开始,对于属性资源包,首选的编码是 UTF-8。它可能与 ISO-859-1 一起使用,但是正如在 JDK 9 的国际化增强文档中所示的,您应该考虑将属性资源包转换成 UTF-8 编码。

您需要做两件事:

  • 根据在项目中使用 properties 文件的方式,决定对 properties 文件使用哪种编码。
  • 使用 3.2.0 版本中引入的 propertiesEncoding 配置参数显式地相应地配置 Maven 资源插件。

在大多数情况下,它看起来是这样的:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          ...
          <propertiesEncoding>ISO-8859-1</propertiesEncoding>
          ...
        </configuration>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

包括和排除文件和目录

指定资源目录时,可能不需要用到该目录中的所有文件。因此,我们可能只需要指定要包含的文件或只需要排除的文件。要包含资源,我们只需要添加 <includes> 元素。

<project>
  ...
  <name>My Resources Plugin Practice Project</name>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>[your directory]</directory>
        <includes>
          <include>[resource file #1]</include>
          <include>[resource file #2]</include>
          <include>[resource file #3]</include>
          ...
          <include>[resource file #n]</include>
        </includes>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>

要排除资源,我们只需要添加一个 <excludes> 元素。

<project>
  ...
  <name>My Resources Plugin Practice Project</name>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>[your directory]</directory>
        <excludes>
          <exclude>[non-resource file #1]</exclude>
          <exclude>[non-resource file #2]</exclude>
          <exclude>[non-resource file #3]</exclude>
          ...
          <exclude>[non-resource file #n]</exclude>
        </excludes>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>

例如,如果我们希望包含 src/my-resources 目录下以及其所有子目录下的 txt 和 rtf 文件,我们可以执行以下操作:

<project>
  ...
  <name>My Resources Plugin Practice Project</name>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>src/my-resources</directory>
        <includes>
          <include>**/*.txt</include>
          <include>**/*.rtf</include>
        </includes>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>

此外,如果我们想包括位图、JPEG 和 GIF 以外的所有内容,我们可以通过以下方式排除它们:

<project>
  ...
  <name>My Resources Plugin Practice Project</name>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>src/my-resources</directory>
        <excludes>
          <exclude>**/*.bmp</exclude>
          <exclude>**/*.jpg</exclude>
          <exclude>**/*.jpeg</exclude>
          <exclude>**/*.gif</exclude>
        </excludes>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>

当然,我们也可以同时拥有 <include><excludes> 元素。例如,如果我们想要包含文件名中不包含单词“test”的所有文本文件。

<project>
  ...
  <name>My Resources Plugin Practice Project</name>
  ...
  <build>
    ...
    <resources>
      <resource>
        <directory>src/my-resources</directory>
        <includes>
          <include>**/*.txt</include>
        </includes>
        <excludes>
          <exclude>**/*test*.*</exclude>
        </excludes>
      </resource>
      ...
    </resources>
    ...
  </build>
  ...
</project>

转义过滤

您可以使用可配置特定的转义字符串(默认为反斜杠)来转义过滤。这意味着前面的表达式 ${}@@ 将替换为表达式。比如,\${java.home} 过滤之后为 ${java.home}\@java.home@ 过滤之后为 @java.home@,而不会进行插值。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          ...
          <escapeString>\</escapeString>
          ...
        </configuration>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

复制资源

您可以使用 copy-resources 插件目标来复制不在默认 Maven 布局中或未在 build/resources 元素中声明的资源,并将其附加到一个生命周期阶段:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
          <execution>
            <id>copy-resources</id>
            <!-- here the phase you need -->
            <phase>validate</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target/extra-resources</outputDirectory>
              <resources>          
                <resource>
                  <directory>src/non-packaged-resources</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>              
            </configuration>            
          </execution>
        </executions>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

二进制文件过滤

该插件默认将防止对文件扩展名为 jpgjpeggifbmppng 的二进制文件进行过滤。如果您想添加补充文件扩展名,只需使用如下配置即可实现:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          ...
          <nonFilteredFileExtensions>
            <nonFilteredFileExtension>pdf</nonFilteredFileExtension>
            <nonFilteredFileExtension>swf</nonFilteredFileExtension>
          </nonFilteredFileExtensions>
          ...
        </configuration>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

自定义资源过滤器

使用 2.5 版,您现在可以构建自定义的资源过滤器。自定义资源过滤器类必须实现 org.apache.maven.shared.filtering.MavenResourcesFiltering

自定义资源筛选器类必须标记为 Plexus 组件。下面是一个带有 roleHint itFilter的示例。

/**
 * @plexus.component role="org.apache.maven.shared.filtering.MavenResourcesFiltering" 
 *                   role-hint="itFilter"
 */
public class ItFilter implements MavenResourcesFiltering

然后,您必须在构建中激活 mojo,它将扫描 javadoc 注释,以将这些注释转换为 Plexus 组件元数据。

  <plugin>
    <groupId>org.codehaus.plexus</groupId>
    <artifactId>plexus-component-metadata</artifactId>
    <version>1.7.1</version>
    <executions>
      <execution>
        <goals>
          <goal>generate-metadata</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

您的类必须在 maven-resources-plugin 类路径中可用,这可以通过将您的工件添加到插件依赖项来完成。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          ...
        </configuration>
        <dependencies>
          <dependency>
            <groupId>custom resources filters artifact groupId</groupId>
            <artifactId>custom resources filters artifact artifactId</artifactId>
            <version>custom resources filters artifact version</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
    ...
  </build>
  ...
</project>

现在必须在插件中声明自定义过滤器。mavenFilteringHint 必须遵守与 Plexus 组件 roleHint 相同的语法。

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
      ...
      <mavenFilteringHints>
        <mavenFilteringHint>itFilter</mavenFilteringHint>
      </mavenFilteringHints>
     </configuration>
     ...
   </configuration>
 </plugin>

maven-compiler-plugin

该插件用于编译项目的源代码。从 3.0 开始,默认编译器是 javax.tools.JavaCompiler(如果使用的是 java 1.6),用于编译 java 源代码。如果要强制该插件使用 javac ,必须为该插件配置 forceJavacCompilerUse 选项。

还要注意,目前默认的 source 值为 1.6,默认的 target 值为 1.6,与运行 Maven 的 JDK 无关。强烈建议您通过设置 Java 编译器的 -source-target 中所述的 sourcetarget 来更改这些默认值。可以使用 javac 以外的其他编译器,有些编译器已经在 AspectJ、.NET 和 C# 上可以使用了。

该插件有两个插件目标。两者都已经绑定到 Maven 生命周期中的适当阶段,因此会在各自的阶段自动执行。

compiler:compile 插件目标

可选参数

该插件目标全名为 org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile,用于编译 Maven 项目主目录下 java 子目录中的源代码。默认绑定在 compile 生命周期阶段。

  • <annotationProcessorPaths>。用作注解处理器路径类路径元素。如果指定,编译器将仅在这些类路径元素中检测注解处理器。如果省略,则使用默认的类路径用于检测注解处理器。检测本身取决于 annotationProcessors 的配置。每个类路径元素都是使用它们的 Maven 坐标(groupIdartifactIdversionclassifiertype)指定的。可传递依赖项将自动添加。示例如下 :

    <configuration>
      <annotationProcessorPaths>
        <path>
          <groupId>org.sample</groupId>
          <artifactId>sample-annotation-processor</artifactId>
          <version>1.2.3</version>
        </path>
        <!-- ... more ... -->
      </annotationProcessorPaths>
    </configuration>
    
  • <annotationProcessors>。要运行的注解处理器的名称。仅适用于 JDK 1.6+,如果未设置,则使用默认的注解处理器发现进程。

  • <compilerArgs>。如果 fork 设置为 true,则设置要传递给编译器的参数。例子:

    <compilerArgs>
      <arg>-Xmaxerrs</arg>
      <arg>1000</arg>
      <arg>-Xlint</arg>
      <arg>-J-Duser.language=en_us</arg>
    </compilerArgs>
    
  • <compilerArgument>。如果 fork 设置为 true,则设置要传递给编译器的未格式化单个参数的字符串。要传递多个参数(例如 -Xmaxerrs 1000,实际上是两个参数),则必须使用 compilerArgs。这是因为传递给 Java 编译器的有效参数列表因编译器版本而异。

  • <compilerId>。要使用的编译器 id,不同的编译器 id 代表使用不同的编译器。默认使用 maven.compiler.compilerId property 的值。默认值为 javac。有关使用不同编译器更多信息,请参阅这里

  • <compilerReuseStrategy>。重新使用创建的 Javacc 类的策略:

    • reuseCreated(默认):将重用已创建的,但在多线程构建的情况下,每个线程将有自己的实例。默认使用 ${reuseCreated} 的值。
    • reuseSame:即使对于多线程构建,每次编译也将使用相同的 Javacc 类。
    • alwaysNew:将为每个编译创建一个新的 Javacc 类。

    注意:此参数值取决于您使用的操作系统和 JDK,但默认值应适用于大多数环境。

  • <compilerVersion>。如果 fork 设置为 true,则指定要使用的编译器版本,例如 1.31.5。默认使用 maven.compiler.compilerVersion property 值。

  • <debug>。设置为 true (默认值)以在编译的类文件中包含调试信息。默认使用 maven.compiler.debug property 值。

  • <debuglevel>。要附加到 -g 命令行开关的关键字列表。合法值为无或以下关键字的逗号分隔列表:linesvarssource。如果未指定该参数,默认情况下,-g 后不会追加任何内容。如果未启用调试,则将忽略此属性。默认使用 maven.compiler.debuglevel property 的值。

  • <excludes>。编译器的排除筛选器列表。

  • <executable>。设置当 forktrue 时要使用的编译器的可执行文件。默认使用 maven.compiler.executable property 的值。

  • <failOnError>。指示即使存在编译错误,构建是否仍将继续。默认为 true

  • <failOnWarning>。指示即使存在编译警告,构建是否仍将继续。默认为 false

  • <fileExtensions>。需要检查时间戳的文件扩展名以用于增量构建,默认仅包含 .class

  • <forceJavacCompilerUse>。编译器如今可以使用 javax.tools(如果在当前 JDK 中可用),可以使用 -Dmaven.compiler.forceJavacCompilerUse=true 或在插件中进行配置来禁用此功能。默认为 false

  • <fork>。允许在不同的进程中运行编译器。如果为 false(默认),则使用内置编译器,如果为 true,则使用可执行文件来作为编译器。默认使用 maven.compiler.fork property 的值。

  • <generatedSourcesDirectory>。指定放置由注解处理所创建的源文件的位置。仅适用于 JDK1.6+。默认使用 ${project.build.directory}/generated-sources/annotations property 的值。

  • <includes>。编译器的包含筛选器列表。

  • <jdkToolchain>。指定此 JDK toolchain 的所需的参数。这将否决 maven-toolchain-plugin 插件选择的 toolchain。

  • <maxmem>。设置内存分配池的最大大小(以 MB 为单位),例如 128128m(如果 fork 设置为 true)。默认使用 maven.compiler.maxmem property 的值。

  • <meminitial>。内存分配池的初始大小(以 MB 为单位),例如 6464m(如果 fork 设置为 true)。默认使用 maven.compiler.meminitial property 的值。

  • <multiReleaseOutput>。当设置为 true 时,类将被放置在 META-INF/versions/${release} 中。必须设置 release 值,否则插件将失败。

  • <outputFileName>。将一组源文件编译为单个文件时,设置输出文件的名称。expression="${project.build.finalName}"

  • <parameters>。设置为 true 以生成元数据以反射方法参数。默认为 false。默认使用 maven.compiler.parameters property 的值。

  • <proc>。设置是否执行注解处理。仅适用于 JDK 1.6+,如果未设置,编译和注解处理将同时执行。允许的值为:

    • none:不执行任何注解处理。
    • only:仅完成注解处理,不进行编译。
  • <showDeprecation>。设置是否显示使用已弃用 API 的源位置。默认为 false。默认使用 maven.compiler.showDeprecation property 的值。

  • <showWarnings>。设置为 true (默认为 false)以显示编译警告。默认使用 maven.compiler.showWarnings property 的值。

  • <skipMain>。将该参数设置为 true 以绕过 main 源代码的编译。不推荐使用,但有时使用起来相当方便。默认使用 maven.main.skip property 的值。

  • <skipMultiThreadWarning>。默认使用 maven.compiler.skipMultiThreadWarning property 的值,默认为 false。

  • <encoding>。指定传递给编译器的 -encoding 参数,表示按哪种编码格式读取源代码文件。默认使用 ${project.build.sourceEncoding} property 的值。

  • <source>。指定传递给编译器的 -source 参数,表示按哪个 JDK 版本的语法读取源代码。默认使用 maven.compiler.source property 的值,默认为 1.6。

  • <target>。指定传递给编译器的 -target 参数,表示生成适用于哪个 JDK 版本的编译文件。默认使用 maven.compiler.target property 的值,默认为 1.6。

  • <release>。Java 编译器的 -release 参数,自 Java 9 以来一直受支持。默认使用 maven.compiler.release property 的值。

  • <staleMillis>。根据上次修改时间之后经过多少毫秒数来测试源文件是否需要重新编译。默认使用 lastModGranularityMs property 的值,默认为 0

  • <useIncrementalCompilation>。设置是否启用增量编译功能。默认使用 maven.compiler.useIncrementalCompilation property 的值,默认为 true

  • <verbose>。设置为 true 以显示有关编译器正在执行的操作的消息。默认使用 maven.compiler.verbose property 的值,默认为 false

compiler:testCompile 插件目标

可选参数

该插件目标全名为 org.apache.maven.plugins:maven-compiler-plugin:3.8.1:testCompile,用于编译 Maven 项目主目录下 test 子目录中的源代码。默认绑定在 test-compile 生命周期阶段。

compiler:testCompile 插件目标不但包含了 compiler:compile 插件目标的所有可选参数,此外,该插件目标还可以使用参数参数:

  • <testCompilerArgument> 。如果 fork 参数设置为 true,则设置要传递给测试编译器的未格式化的单个参数字符串。这是因为传递给 Java 编译器的有效参数列表因编译器版本而异。
  • <testCompilerArguments>。如果 fork 参数设置为 true,则设置要传递给测试编译器的多个参数(在破折号之前)。这是因为传递给 Java 编译器的有效参数列表因编译器版本而异。
  • <testExcludes>。编译器的排除筛选器列表。
  • <testIncludes>。编译器的包含筛选器列表。
  • <testRelease>。测试 Java 编译器的 -release 参数。默认使用 maven.compiler.testRelease property 的值。
  • <testSource>。测试 Java 编译器的 -source 参数,表示按哪个 JDK 版本来读取测试源代码。默认使用 maven.compiler.testSource property 的值。
  • <testTarget>。测试 Java 编译器的 -target 参数,表示生成适用于哪个 JDK 版本的编译测试文件。默认使用 maven.compiler.testTarget property 的值。

示例

使用不同的 JDK 编译源代码

使用 Maven Toolchain

使用不同 JDK 的更好方法是使用 toolchain 机制。在项目构建过程中,Maven 在没有 toolchain 的情况下,将使用 JDK 执行各种步骤,如编译 Java 源代码、生成Javadoc、运行单元测试或对 JAR 进行签名。这些插件中的每一个都需要 JDK 的一个工具来操作:javacjavadocjarsigner 等等。toolchain 是一个以集中的方式指定 JDK 路径的方法、独立于运行 Maven 自身的 JDK 的插件。

要进行设置,请参阅 toolchain 指南。使用 maven-toolchains-plugin,您可以为所有相关的 Maven 插件配置一个默认 JDK toolchain。由于 Maven 编译器插件 3.6.0 在与 Maven 3.3.1+ 一起使用时,也可以为该编译插件提供自己的 toolchain,这在每个执行块调用不同 JDK 的情况下非常有用。例如,与 main 目录中的源代码相比,test 中的测试源代码需要不同的编译器。

配置编译插件

在 toolchain 之外,仍然可以告诉编译器插件在编译期间要使用的特定 JDK。请注意,这样的配置是特定于该插件的,并且不会影响其他插件。compilerVersion 参数可用于指定插件将使用的编译器版本。当然,您还需要将 fork 设置为 true,这样才能工作。例如:

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <verbose>true</verbose>
          <fork>true</fork>
          <executable><!-- path-to-javac --></executable>
          <compilerVersion>1.3</compilerVersion>
        </configuration>
      </plugin>
    </plugins>
    [...]
  </build>
  [...]
</project>

为了避免硬编码可执行文件的文件系统路径,可以使用属性。例如:

<executable>${JAVA_1_4_HOME}/bin/javac</executable>

然后,每个开发人员在 settings.xml 中定义该属性,或设置一个环境变量,以便构建保持可移植性。

<settings>
  [...]
  <profiles>
    [...]
    <profile>
      <id>compiler</id>
        <properties>
          <JAVA_1_4_HOME>C:\Program Files\Java\j2sdk1.4.2_09</JAVA_1_4_HOME>
        </properties>
    </profile>
  </profiles>
  [...]
  <activeProfiles>
    <activeProfile>compiler</activeProfile>
  </activeProfiles>
</settings>

如果使用不同的 JDK 进行构建,则可能需要自定义 jar 文件清单。

设置 Java 编译器的 -source-target

有时,您可能需要将某个项目编译为与当前使用的版本不同的版本。javac 可以使用 -source-target 接受这样的命令。编译器插件也可以配置为在编译期间提供这些选项。例如,如果您希望使用 Java 8 语言功能(-source 1.8),并且还希望编译的类与 JVM 1.8(-target 1.8)兼容,则可以添加以下两个属性,它们是插件参数的默认属性名称:

<project>
  [...]
  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  [...]
</project>

或者直接配置插件:

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <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>

仅仅设置 target 选项并不能保证您的代码在具有指定版本的 JRE 上一定可以运行。这个缺陷是无意中使用了只存在于后续版本的 JRE 中的 API,这会导致代码在运行时失败,并出现链接错误。为了避免这个问题,您可以配置编译器的启动类路径来匹配目标 JRE,或者使用 Animal Sniffer Maven 插件来验证您的代码没有使用意外的API。同样,设置 source 选项也不能保证代码在具有指定版本的 JDK 上编译。要使用特定的 JDK 版本编译代码(不同于用于启动 Maven 的版本),请参考使用不同 JDK 示例编译代码

使用增强内存分配功能

编译器插件接受 meminitialmaxmem 的配置。您可以按照以下示例将初始内存大小设置为 128MB,最大内存使用量设置为 512MB:

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <fork>true</fork>
          <meminitial>128m</meminitial>
          <maxmem>512m</maxmem>
        </configuration>
      </plugin>
    </plugins>
    [...]
  </build>
  [...]
</project>

传入编译参数

有时,您需要传递其他编译参数,这些参数不是由编译器插件本身处理的,而是由所选编译器 ID 支持的。对于此类参数,请使用编译器插件的 compilerArgs 参数。以下示例将编译器参数传递给 javac 编译器:

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <compilerArgs>
            <arg>-verbose</arg>
            <arg>-Xlint:all,-options,-path</arg>
          </compilerArgs>
        </configuration>
      </plugin>
    </plugins>
    [...]
  </build>
  [...]
</project>

使用不同编译器

编译器插件本身并不编译项目的源代码,而是使用另一个类来编译它们。参数 compilerId 确定将使用哪个类。目前,编译器插件自带了 artifactIdplexus-compiler-javacjavac 编译器,这可以看作是编译器插件的 POM 中声明的依赖项之一。Plexus 编译器组件在名为 org.codehaus.plexusgroupId 下有一些其他编译器 ID 可用:

  • aspectjartifactIdplexus-compiler-aspectj
  • csharpartifactIdplexus-compiler-csharp
  • eclipseartifactIdplexus-compiler-eclipse
  • jikesartifactIdplexus-compiler-jikes

使用其他 Plexus 编译器

要使用任何非 javac 编译器,您需要在编译器插件运行时使对应的编译器工件在类路径中可用。这可以通过在项目的 pom.xml 中声明插件时添加依赖项来实现。下面的示例显示了如何使用 csharp 编译器:

<project>
  [...]
  <build>
    [...]
    <plugins>
      [...]
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <compilerId>csharp</compilerId>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-csharp</artifactId>
            <version>1.6</version>
          </dependency>
        </dependencies>
      </plugin>
  [...]
</project>

包含 module-info 的旧项目

对于希望与旧版本的 Java(即 1.8 或更低版本)兼容,但又希望为 Java 9 提供 module-info.Java 的项目,项目必须知道它们需要调用 javac 两次:module-info.java 必须使用 release=9 编译,而其余的源代码必须使用较低版本的 source/target 编译。

实现这一点的首选方法是使用下面描述的 2 个执行块。JDK9 只支持 Java6 及以上版本的编译,因此想要与 Java5 或以下版本兼容的项目需要使用两种不同的 JDK。使用 toolchain 很容易实现这一点。请注意,至少需要 Maven 3.3.1 才能在插件配置中指定自定义 jdkToolchain。您可以添加一个 jdkToolchain 来执行基本编译执行块,也可以参考 JDK 5。

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <executions>
          <execution>
            <id>default-compile</id>
            <configuration>
              <!-- compile everything to ensure module-info contains right entries -->
              <!-- required when JAVA_HOME is JDK 8 or below -->
              <jdkToolchain>
                <version>9</version>
              </jdkToolchain>
              <release>9</release>
            </configuration>
          </execution>
          <execution>
            <id>base-compile</id>
            <goals>
              <goal>compile</goal>
            </goals>
            <!-- recompile everything for target VM except the module-info.java -->
            <configuration>
              <excludes>
                <exclude>module-info.java</exclude>
              </excludes>
            </configuration>
          </execution>
        </executions>
        <!-- defaults for compile and testCompile -->
        <configuration>
          <!-- jdkToolchain required when JAVA_HOME is JDK 9 or above -->
          <jdkToolchain>
            <version>[1.5,9)</version>
          </jdkToolchain>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
    </plugins>
    [...]
  </build>
  [...]
</project>

如果您希望项目与 Java 6 兼容,最简单的方法是对两个执行块都使用 Java 9。您可以使用 Maven toolchain 插件指定共享 JDK(自 Maven 2.0.9 以来支持)或自定义 jdkToolchain(自 Maven 3.3.1 以来支持),并参考系统上的 JDK 9 安装。或者通过设置 JAVA_HOME=/path/to/jdk-9 来简单地使用 Java9 作为 Maven 的运行时。

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <executions>
          <execution>
            <id>default-compile</id>
            <configuration>
              <!-- compile everything to ensure module-info contains right entries -->
              <release>9</release>
            </configuration>
          </execution>
          <execution>
            <id>base-compile</id>
            <goals>
              <goal>compile</goal>
            </goals>
            <!-- recompile everything for target VM except the module-info.java -->
            <configuration>
              <excludes>
                <exclude>module-info.java</exclude>
              </excludes>
            </configuration>
          </execution>
        </executions>
        <!-- defaults for compile and testCompile -->
        <configuration>
          <!-- Only required when JAVA_HOME isn't at least Java 9 and when haven't configured the maven-toolchains-plugin -->
          <jdkToolchain>
            <version>9</version>
          </jdkToolchain>
          <release>6</release>
        </configuration>
      </plugin>
    </plugins>
    [...]
  </build>
  [...]
</project>

maven-install-plugin

该插件用于在 install 生命周期阶段将工件添加到本地仓库。该插件使用 POM 中的信息(groupIdartifactIdversion)来确定工件在本地仓库中的正确位置。本地仓库是项目构建所需的所有工件的本地缓存。默认情况下,它位于用户的 home 目录中(~/.m2/repository),但可以使用 <localRepository> 元素在~/.m2/settings.xml 中配置该位置。

该插件有三个插件目标。

install:install 插件目标

该插件目标的全称为 org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install,用于将项目的主工件以及生命周期中其他插件附加的任何其他工件安装到本地仓库。默认绑定在 install 生命周期阶段。

可选参数

  • <installAtEnd>。每个项目是否应在其自身的 install 生命周期阶段或在多模块构建结束时安装。如果设置为 true 且构建失败(默认为 false),则不会安装任何项目(实验性)。默认使用 installAtEnd property 的值。
  • <skip>。将此设置为 true(默认为 false)以绕过工件安装。对于不需要安装在本地存储库中的工件,请使用此选项。默认使用 maven.install.skip property 的值。

install:install-file 插件目标

该插件目标的全称为 org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file,用于将文件安装到本地仓库。

必选元素

  • <file>。要安装在本地仓库中的文件。默认使用 file property 的值。

可选元素

  • <groupId>。要安装的工件的 GroupId。如果指定了 POM 文件,则从 POM 文件中检索;如果可用,则从 jar 中的 pom.xml 中提取。默认使用 groupId property 的值。
  • <artifactId>。要安装的工件的 ArtifactId。如果指定了 POM 文件,则从 POM 文件中检索;如果可用,则从 jar 文件中的 pom.xml 中提取。默认使用 artifactId property 的值。
  • <version>。要安装的工件的版本。如果指定了 POM 文件,则从 POM 文件中检索;如果可用,则从 jar 中的 pom.xml 中提取。默认使用 version property 的值。
  • <classifier>。要安装的工件的 classifier 类型。例如,sourcesjavadoc。默认为无,这意味着这是项目的主要工件。默认使用 classifier property 的值。
  • <generatePom>。如果通过参数 pomFile 未提供 POM,则为该工件生成最小 POM。如果本地仓库中还没有已存在的 POM,则默认为 true。默认使用 generatePom property 的值。
  • <javadoc>。与工件一起绑定的 API 文档。默认使用 javadoc property 的值。
  • <localRepositoryPath>。工件要安装到的本地仓库的路径。如果未指定,将使用 Maven 设置中配置的本地仓库路径。默认使用 localRepositoryPath property 的值。
  • <packaging>。要安装的工件的包类型。如果指定了 POM 文件,则从 POM 文件中检索;如果可用,则从 jar 中的 pom.xml 中提取。默认使用 packaging property 的值。
  • <pomFile>。要与主工件一起安装的现有 POM 文件的位置,由 file 参数给出。
  • <sources>。与工件一起绑定的 source。默认使用 sources property 的值。

install:help 插件目标

该插件目标主要用于显示 maven-install-plugin 的帮助信息,不再详细介绍。

示例

使用自定义 POM 安装工件

Apache Maven install 插件可以包括一个预构建的自定义 POM,该 POM 带有本地存储库中的工件。只需将 pomFile 参数的值设置为自定义 POM 的路径。

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=path-to-your-artifact-jar -DpomFile=path-to-pom

如果 JAR 是由 Apache Maven 构建的,那么它将在 META-INF 目录的子文件夹中包含一个 pom.xml,默认情况下会读取它。在这种情况下,您需要做的就是:

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=<path-to-file>

注意:通过使用目标的完全限定路径,可以确保使用 Maven 安装插件的首选版本。使用 mvn install:install 文件时,其版本取决于 pom 中的规范或 Apache Maven 版本。

生成泛型 POM

有时需要将没有 POM 的第三方工件添加到 Maven 项目使用,比如,需要为非 Maven 工具创建的 jar 包,或从网络下载的、且中央仓库中不存在的 jar 包添加 POM 并安装本地仓库中。在这种情况下,install 插件可以创建一个通用 POM,其中包含 Maven 所需的最小 POM 元素集,例如 groupIdartifactIdversionpackage。您告诉 Maven 通过将 generatePom 参数设置为 true 来生成 POM。

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file  -Dfile=path-to-your-artifact-jar \
    -DgroupId=your.groupId \
    -DartifactId=your-artifactId \
    -Dversion=version \
    -Dpackaging=jar \
    -DgeneratePom=true

注意:通过使用插件目标的完全限定路径,可以确保使用 Maven install 插件的首选版本。当使用 mvn install:install 来安装第三方工件的 jar 包文件时,对应的 install 插件版本取决于 pom 中的规范或 Apache Maven 版本。

更新项目的发布信息

更新发布信息意味着强制更新项目元数据,将工件设置为发布版本。它在安装从源代码构建的插件时最有用,这样其他项目就可以使用它,而无需明确要求最新的快照版本。安装时,可通过将 updateReleaseInfo 参数设置为 true 来激活此选项。

mvn install -DupdateReleaseInfo=true

将工件安装到特定的本地仓库路径

默认情况下,Apache Maven install 插件使用 settings.xml 中定义的本地存储库来安装工件。通过在安装时设置 localRepositoryPath 参数,可以在特定的本地仓库上安装工件。

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file  -Dfile=path-to-your-artifact-jar \
    -DgroupId=your.groupId \
    -DartifactId=your-artifactId \
    -Dversion=version \
    -Dpackaging=jar \
    -DlocalRepositoryPath=path-to-specific-local-repo

注意:通过使用插件目标的完全限定路径,可以确保使用 Maven install 插件的首选版本。当使用 mvn install:install 来安装第三方工件的 jar 包文件时,对应的 install 插件版本取决于 pom 中的规范或 Apache Maven 版本。

安装辅助工件

有时,您需要在本地仓库中安装主工件之后安装辅助工件。要安装辅助工件,需要使用 classifier 参数对辅助工件进行分类。假设您想要安装一个旧工件的源代码,比如 commons-logging-1.0.3。对于该版本,中央存储库只有主工件和 -javadoc 工件。将源代码打包到本地磁盘上的 JAR 文件中,然后运行以下命令:

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file  -Dfile=path-to-commons-logging-sources.jar \
                                                                              -DgroupId=commons-logging \
                                                                              -DartifactId=commons-logging \ 
                                                                              -Dversion=1.0.3 \
                                                                              -Dpackaging=jar \
                                                                              -Dclassifier=sources

注意:通过使用插件目标的完全限定路径,可以确保使用 Maven install 插件的首选版本。当使用 mvn install:install 来安装第三方工件的 jar 包文件时,对应的 install 插件版本取决于 pom 中的规范或 Apache Maven 版本。

maven-deploy-plugin

deploy 插件主要在 deploy 生命周期阶段使用,用于将工件添加到远程仓库,以便与其他开发人员和项目共享。这通常在集成或发布环境中完成。它还可用于部署特定工件(例如,第三方 jar)。由于仓库包含的不仅仅是工件,还有诸如 POM、元数据、MD5 和 SHA1 哈希等文件,因此部署不仅意味着复制工件,还意味着确保所有这些信息都得到正确更新。这是 deploy 插件的责任。

部署需要以下信息才能工作:

  • 关于仓库的信息:其位置、用于访问仓库的传输方式(FTP、SCP、SFTP…)以及可选的特定于用户的帐户信息。
  • 有关工件的信息:groupIdartifactIdversionpackageingclassifier 等。
  • 部署者:实际执行部署的方法。这可以实现为装箱传输(使其跨平台),或使用特定于系统的方法。

信息将从隐含(或指定)的 pom 和命令行中获取。还可以解析 settings.xml 文件以检索用户凭证。

该插件包含两个插件目标。

deploy:deploy 插件目标

该插件目标的全称为 org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy,用于将工件部署到远程仓库。默认绑定在 deploy 生命周期阶段。

可选参数

  • <altDeploymentRepository>。指定项目工件应部署到的替代仓库(在 <distributionManagement> 中指定的仓库除外)。
    格式:id::layout::url。其中,id 可用于从 settings.xml 中获取正确的凭证,url 为仓库的地址。从 3.0.0 开始,layout 部分已被删除。默认使用 altDeploymentRepository property 的值。
  • <altReleaseDeploymentRepository>。当项目有最终版本时要使用的替代仓库。默认使用 altReleaseDeploymentRepository property 的值。
  • <altSnapshotDeploymentRepository>。当项目具有快照版本时要使用的替代仓库。默认使用 altSnapshotDeploymentRepository property 的值。
  • <deployAtEnd>。每个项目是应该在自己的 deploy 生命周期阶段部署,还是应该在多模块构建结束时部署。如果设置为 true (默认为 false)且构建失败,则不会部署任何项目(实验性)。默认使用 altSnapshotDeploymentRepository property 的值。
  • <retryFailedDeploymentCount>。在部署失败时尝试重新部署的次数。如果指定的值超出范围 1-10,则该值将被拉至范围 1-10 内最近的值。默认使用 retryFailedDeploymentCount property 的值。默认为 1
  • <skip>。将其设置为 true 以跳过该插件目标的执行。默认使用 maven.deploy.skip property 的值。默认为 false

deploy:deploy-file 插件目标

该插件目标的全称为 org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy,用于将工件部署到远程仓库。

必选参数

  • <file>。要部署的文件。默认为 file property 的值。
  • <repositoryId>。要映射到 settings.xml<server> 部分下的 <id> 的服务器 Id。在大多数情况下,身份验证需要此参数。默认使用 remote-repository property 的值。
  • <url>。将在其中部署工件的 URL。例如:file:///C:/m2-repo or scp://host.com/path/to/repo。默认为 url property 的值。

可选参数

  • <groupId>。要部署的工件的 groupId。如果指定,则从 POM 文件检索。默认使用 groupId property 的值。
  • <artifactId>。要部署的工件的 artifactId。如果指定,则从 POM 文件检索。默认使用 artifactId property 的值。
  • <version>。要部署的工件的版本。如果指定了 POM 文件,则从 POM 文件中检索;如果可用,则从 jar 中的 pom.xml 中提取。默认使用 version property 的值。
  • <types>。要部署的每个辅助工件的类型的逗号分隔列表。如果 filestypes 中的条目数不匹配,则会引发错误。默认使用 types property 的值。
  • <sources>。与工件一起绑定的 source。默认使用 sources property 的值。
  • <javadoc>。与工件集成在一起的 API 文档。默认使用 javadoc property 的值。
  • <classifier>。将 classifier 添加到工件中。默认使用 classifier property 的值。
  • <classifiers>。一个逗号分隔的 classifier 列表,用于每个要部署的额外辅助工件。如果 filestypes 中的条目数不匹配,则会引发错误。默认使用 classifiers property 的值。
  • <description>。传递到生成的 POM 文件的描述(如果 generatePom=true)。默认使用 generatePom.description property 的值。
  • <files>。以逗号分隔的文件列表,用于每个要部署的附加工件。如果 filestypes 中的条目数不匹配,则会引发错误。默认使用 files property 的值。
  • <generatePom>。上传此工件的 POM。如果 pomFile 参数未提供任何 POM,则将生成默认 POM。默认使用 classifiers property 的值。默认为 false
  • <packaging>。要部署的工件的类型。如果指定了 POM 文件,则从 POM 文件的 <packaging> 元素检索。如果未通过命令行或 POM 指定,则默认为文件扩展名。Maven 使用两个术语来引用此数据:整个 POM 的 <packaging> 元素和依赖项规范中的 <type> 元素。默认使用 packaging property 的值。
  • <pomFile>。要与主工件一起部署的现有 POM 文件的位置,由 ${file} 参数给出。默认使用 pomFile property 的值。
  • <retryFailedDeploymentCount>。在部署失败时尝试重新部署的次数。如果指定的值超出范围 1-10,则该值将被拉至范围 1-10 内最近的值。默认使用 retryFailedDeploymentCount property 的值。默认为 1

示例

使用 FTP 部署工件

为了使用 FTP 部署工件,您必须首先在 POM 的 distributionManagement 元素中指定 FTP 服务器的使用,并在构建元素中指定一个扩展,该扩展将引入使用FTP 部署所需的 FTP 工件:

<project>
  ...
  <distributionManagement>
    <repository>
      <id>ftp-repository</id>
      <url>ftp://repository.mycompany.com/repository</url>
    </repository>
  </distributionManagement>
 
  <build>
    <extensions>
      <!-- Enabling the use of FTP -->
      <extension>
        <groupId>org.apache.maven.wagon</groupId>
         <artifactId>wagon-ftp</artifactId>
         <version>1.0-beta-6</version>
      </extension>
    </extensions>
  </build>
  ...
</project>

您的 settings.xml 将包含一个服务器元素,其中该元素的 id 与上面 POM 中指定的 FTP 仓库的 id 匹配:

<settings>
  ...
  <servers>
    <server>
      <id>ftp-repository</id>
      <username>user</username>
      <password>pass</password>
    </server>
  </servers>
  ...
</settings>

当然,在尝试使用 Maven 进行部署之前,您应该确保可以手动登录到指定的 FTP 服务器。一旦您确认所有设置都正确,现在就可以使用 Maven 部署您的工件:

mvn deploy

在外部 SSH 命令中部署工件

为了使用 SSH 部署工件,必须首先在 POM 的 distributionManagement 元素中指定 SSH 服务器的使用,并在 build 元素中指定一个扩展,该扩展将引入使用SSH 部署所需的 SSH 工件:

<project>
  ...
  <distributionManagement>
    <repository>
      <id>ssh-repository</id>
      <url>scpexe://repository.mycompany.com/repository</url>
    </repository>
  </distributionManagement>
 
  <build>
    <extensions>
      <!-- Enabling the use of SSH -->
      <extension>
        <groupId>org.apache.maven.wagon</groupId>
         <artifactId>wagon-ssh-external</artifactId>
         <version>1.0-beta-6</version>
      </extension>
    </extensions>
  </build>
  ..
</project>

如果您是从 Unix 部署或安装了 Cygwin,则不需要在 settings.xml 文件中进行任何其他配置,因为所有内容都将从环境中获取。但是,如果您使用的是 Windows,并且使用的是类似于 plink 的东西,那么您将需要以下东西:

<settings>
  ...
  <servers>
    <server>
      <id>ssh-repository</id>
      <username>your username in the remote system if different from local</username>
      <privateKey>/path/to/your/private/key</privateKey> <!-- not needed if using pageant -->
      <configuration>
        <sshExecutable>plink</sshExecutable>
        <scpExecutable>pscp</scpExecutable>
        <sshArgs>other arguments you may need</sshArgs>
      </configuration>
    </server>
  </servers>
  ...
</settings>

当然,在尝试使用 Maven 进行部署之前,您应该确保可以手动登录到指定的 SSH 服务器。一旦您确认所有设置都正确,现在就可以使用 Maven 部署您的工件:

mvn deploy

有时,您在部署时可能会遇到权限问题,如果是这样,您可以按如下方式设置文件和目录权限:

 <settings>
   ...
   <servers>
     <server>
       <id>ssh-repository</id>
       <!--
        |
        | Change default file/dir permissions
        |
        -->
       <filePermissions>664</filePermissions>
       <directoryPermissions>775</directoryPermissions>
       <configuration>
         <sshExecutable>plink</sshExecutable>
         <scpExecutable>pscp</scpExecutable>
       </configuration>
     </server>
   </servers>
   ...
 </settings>

注意:如果您使用 Putty,它将期望私钥为 PPK 格式而不是标准格式,因此请确保使用 puttygenopenssh 格式密钥转换为 PPK 格式或生成另一个。Windows 用户可以在 Putty 下载页面上找到 Putty 工具。

禁用 pom 的生成

默认情况下,如果在部署第三方工件期间未指定 pom,将生成一个通用 pom,其中包含 pom 所需的最少元素。要禁用它,请将 generatePom 参数设置为false

mvn org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file -Durl=file:///C:/m2-repo \
                                                                            -DrepositoryId=some.id \
                                                                            -Dfile=path-to-your-artifact-jar \
                                                                            -DgroupId=your.groupId \
                                                                            -DartifactId=your-artifactId \
                                                                            -Dversion=version \
                                                                            -Dpackaging=jar \
                                                                            -DgeneratePom=false

注意:通过使用插件目标的完全限定路径,可以确保使用 maven deploy 插件的首选版本。使用 mvn deploy:deploy 文件时,其版本取决于 pom 中的规范或Apache Maven 的版本。

使用定制的 pom 部署工件

如果已经存在一个 pom,并且希望它与第三方工件一起部署,那么将 pomFile 参数设置为 pom.xml 的路径。

mvn org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file -Durl=file:///C:/m2-repo \
                                                                            -DrepositoryId=some.id \
                                                                            -Dfile=path-to-your-artifact-jar \
                                                                            -DpomFile=path-to-your-pom.xml

请注意,groupIdartifactIdversionpackage 信息是从给定 pom 自动检索的。

注意:通过使用插件目标的完全限定路径,可以确保使用 deploy 插件的首选版本。使用 mvn deploy:deploy-file 时,其版本取决于 pom 中的规范或 Apache Maven 的版本。

使用 classifier 部署工件

除了主工件之外,还有附加到 Maven 项目的其他文件。这样的附加字段可以被其 classifier 识别和访问。

例如:从以下工件名称中,classifier 位于工件的版本名和扩展名之间。

  • artifact-name-1.0.jar。主 jar,其中包含编译时没有调试信息(如行号)的类。
  • artifact-name-1.0-debug.jar。分类的 jar,它包含使用调试信息编译的类,因此会更小。
  • artifact-name-1.0-site.pdf。包含站点文档导出的 pdf。

您可以在一次运行中部署主工件和 classified 工件。假设文档的原始文件名为 site.pdf:

mvn org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file -Durl=http://localhost:8081/repomanager/ \
    -DrepositoryId=some.id \
    -Dfile=path/to/artifact-name-1.0.jar \
    -DpomFile=path-to-your-pom.xml \
    -Dfiles=path/to/artifact-name-1.0-debug.jar,path/to/site.pdf \
    -Dclassifiers=debug,site \
    -Dtypes=jar,pdf

如果您只想部署调试 jar 并想保留分类器,那么可以像下面这样执行部署文件:

mvn org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file -Durl=http://localhost:8081/repomanager/ \
    -DrepositoryId=some.id \
    -Dfile=path-to-your-artifact-jar \
    -DpomFile=path-to-your-pom.xml \
    -Dclassifier=bin

注意:通过使用插件目标的完全限定路径,可以确保使用 deploy 插件的首选版本。使用 mvn deploy:deploy-file 时,其版本取决于 pom 中的规范或 Apache Maven 的版本。

部署 sourcesjavadoc 的 jar

一个项目可能包括一个主 jar 和相关的 sources jar 以及 javadoc jar。

  artifact-name-1.0.jar
  artifact-name-1.0-sources.jar
  artifact-name-1.0-javadoc.jar

sources jar 包含 Java 源代码,javadoc jar 包含生成的 javadoc。要在部署中包含这些文件,请将 sourcesjavadoc 参数设置为指向 sources jar 和 javadoc jar 文件的路径。

mvn org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file -Durl=file:///home/me/m2-repo \
                                                                            -DrepositoryId=some.repo.id \
                                                                            -Dfile=./path/to/artifact-name-1.0.jar \
                                                                            -DpomFile=./path/to/pom.xml \
                                                                            -Dsources=./path/to/artifact-name-1.0-sources.jar \
                                                                            -Djavadoc=./path/to/artifact-name-1.0-javadoc.jar

注意:通过使用插件目标的完全限定路径,可以确保使用 deploy 插件的首选版本。使用 mvn deploy:deploy-file 时,其版本取决于 pom 中的规范或 Apache Maven 的版本。

在传统(Legacy)布局中部署工件

“Legacy” 是 Maven 1 仓库中使用的布局,而 Maven 2 使用“default”。它们在目录结构、默认快照的时间戳和默认元数据文件的存在方面有所不同。

  • 传统布局目录结构:

      groupId
      |--artifactId
         |--jars
            `--artifact
    
  • 默认布局目录结构:

      groupId
      |--artifactId
         |--version
         |  `---artifact
         |---metadata
    

为了能够在仓库的传统布局中部署工件,请将 repositoryLayout 参数设置为 legacy

mvn org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file -Durl=file:///C:/m2-repo \
                                                                            -DrepositoryId=some.id \
                                                                            -Dfile=your-artifact-1.0.jar \
                                                                            -DpomFile=your-pom.xml \
                                                                            -DrepositoryLayout=legacy

注意:通过使用插件目标的完全限定路径,可以确保使用 deploy 插件的首选版本。使用 mvn deploy:deploy-file 时,其版本取决于 pom 中的规范或 Apache Maven 的版本。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • WAR 插件负责收集 Web 应用程序的所有依赖项、类和资源,并将它们打包到 WAR 包中,仅包含 scope 为...
    rosy_dawn阅读 6,670评论 0 0
  • maven-jar-plugin 该插件提供了构建 JAR 包的功能。如果您喜欢对 JAR 包签名,请使用 Mav...
    rosy_dawn阅读 3,272评论 0 0
  • Maven 生命周期及其阶段 Maven 基于生命周期的核心概念。有三个内置的生命周期: clean:负责清理项目...
    rosy_dawn阅读 552评论 0 0
  • 简介 该插件提供了将工件打包成 Uber jar 的功能,包括其依赖项,并对某些依赖项的包进行处理。Shade 插...
    rosy_dawn阅读 18,816评论 0 8
  • POM 代表“Project Object Model”。它是 Maven 项目的 XML 表示形式,保存在名为 ...
    rosy_dawn阅读 1,840评论 0 1