当前位置 : 首页 » 文章分类 :  开发  »  Apache-Maven

Apache-Maven

Maven 使用笔记

Apache Maven官网
https://maven.apache.org/index.html

Maven in 5 Minutes
https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html

Maven Getting Started Guide
https://maven.apache.org/guides/getting-started/index.html

Spring Maven Repository
http://repo.spring.io/release
http://repo.spring.io/snapshot


Maven 基础

Apache Maven是一个软件项目管理的综合工具。基于项目对象模型(POM)的概念,提供管理项目的构建、文档、报告、依赖、发布等方法,Maven简化和标准化项目建设过程。处理编译,分配,文档,团队协作和其他任务的无缝连接。 Maven增加可重用性并负责建立相关的任务。

maven的好处在于可以将项目过程规范化、自动化、高效化以及强大的可扩展性,利用maven自身及其插件还可以获得代码检查报告、单元测试覆盖率、实现持续集成等等。

Maven的基本原理很简单,采用远程仓库和本地仓库以及一个核心的配置文件pom.xml,pom.xml中定义的jar文件从远程仓库下载到本地仓库,各个项目使用同一个本地仓库的jar,同一个版本的jar只需下载一次,而且避免每个应用都去拷贝jar。同时它采用了现在流行的插件体系架构,所以maven的核心非常的小,只有几兆大小的文件,在执行maven任务时,才会自动下载需要的插件。

Maven入门指南(一)
http://ifeve.com/maven-1/

Maven实战(一)安装和配置
http://www.iteye.com/topic/1123187

使用Eclipse构建Maven项目 (step-by-step)
http://blog.csdn.net/qjyong/article/details/9098213


Maven 核心概念

Artifact:项目产生物,主要有jar, war, maven插件

构建生命周期、阶段和目标

Maven 的构建过程被分解为 **构建生命周期(lifecycle)、阶段(phases)和目标(goals)**。
一个构建周期由一系列的构建阶段组成,每一个构建阶段由一系列的目标组成。当你运行 Maven 的时候,你会传入一条命令。这条命令就是构建生命周期、阶段或目标的名字。如果执行一个生命周期,该生命周期内的所有构建阶段都会被执行。如果执行一个构建阶段,在预定义的构建阶段中,所有处于当前构建阶段之前的阶段也都会被执行。

生命周期(Lifecycle)

Maven 有以下三个标准的生命周期:

  • clean:项目清理的处理
  • default(或 build):项目部署的处理
  • site:项目站点文档创建的处理

一个典型的 Maven 构建(build)生命周期(default 生命周期)是由以下几个阶段的序列组成的:

阶段 处理 描述
验证 validate 验证项目 验证项目是否正确且所有必须信息是可用的
编译 compile 执行编译 源代码编译在此阶段完成
测试 Test 测试 使用适当的单元测试框架(例如JUnit)运行测试。
包装 package 打包 创建JAR/WAR包如在 pom.xml 中定义提及的包
检查 verify 检查 对集成测试的结果进行检查,以保证质量达标
安装 install 安装 安装打包的项目到本地仓库,以供其他项目使用
部署 deploy 部署 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程

Introduction to the Build Lifecycle
https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

mvn clean package 依次执行了 clean、resources、compile、testResources、testCompile、test、jar(打包)等7个阶段。
mvn clean install 依次执行了 clean、resources、compile、testResources、testCompile、test、jar(打包)、install等8个阶段。
mvn clean deploy 依次执行了 clean、resources、compile、testResources、testCompile、test、jar(打包)、install、deploy等9个阶段。

构建阶段(Phase)由插件目标(Goal)构成

一个插件目标代表一个特定的任务(比构建阶段更为精细),这有助于项目的构建和管理。这些目标可能被绑定到多个阶段或者无绑定。不绑定到任何构建阶段的目标可以在构建生命周期之外通过直接调用执行。这些目标的执行顺序取决于调用目标和构建阶段的顺序。

例如,考虑下面的命令:
mvn clean dependency:copy-dependencies package
clean 是构建周期,pakage 是构建阶段,dependency:copy-dependencies 是目标
这里的 clean 周期将会被首先执行,然后 dependency:copy-dependencies 目标会被执行,最终 package 阶段被执行。

依赖和仓库

Maven执行时,其中一个首要目标就是检查项目的 **依赖(dependencies)**。依赖是你的项目用到的jar文件(java库)。如果在本地仓库中不存在该依赖,则Maven会从中央仓库下载并放到本地仓库。本地仓库只是你电脑硬盘上的一个目录。你可以根据需要制定本地仓库的位置。你也可以指定下载依赖的远程仓库的地址。

插件plugins

构建 **插件(plugins)**可以向构建阶段中增加额外的构建目标。如果Maven标准的构建阶段和目标无法满足项目构建的需求,你可以在POM文件里增加插件。Maven有一些标准的插件供选用,如果需要你可以自己实现插件。

配置文件profiles

**配置文件(profiles)**用于以不同的方式构建项目。
比如,你可能需要在本地环境构建,用于开发和测试,你也可能需要构建后用于开发环境。这两个构建过程是不同的。在POM文件中增加不同的构建配置,可以启用不同的构建过程。当运行Maven时,可以指定要使用的配置。

比如,一个项目可能会有多个子module,在特定情况下可能只需要build其中几个module,可以通过 profile 区分。


安装配置

Mac Brew 安装 maven

安装maven
brew install maven

Intel Mac 安装目录 /opt/homebrew/Cellar/maven/3.8.4
M1 Mac 安装目录 /opt/homebrew/Cellar/maven/3.8.4

安装后添加 JAVA_HOME 环境变量

vim ~/.zshrc
export JDK8_HOME="/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home"
export JAVA_HOME=$JDK8_HOME
source ~/.zshrc

Windows下安装及配置maven

http://maven.apache.org/
下载windows版 apache-maven-3.3.9-bin.zip
解压后将文件夹apache-maven-3.3.9拷贝到C:\Program Files即安装完成

配置环境变量
安装配置JDK:安装JDK1.8,新建系统环境变量JAVA_HOME,变量值为C:\Program Files\Java\jdk1.8.0_111
新建系统环境变量MAVEN_HOME,变量值为C:\Program Files\apache-maven-3.3.9
在系统变量Path中增加%MAVEN_HOME%\bin
配置完成后,可打开命令行,输入mvn -v,有版本信息说明配置成功


CentOS7安装maven3

安装maven yum源

通过 yum-config-manager 安装 maven 源

$ sudo yum-config-manager --add-repo http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo
已加载插件:fastestmirror
adding repo from: http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo
grabbing file http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo to /etc/yum.repos.d/epel-apache-maven.repo
repo saved to /etc/yum.repos.d/epel-apache-maven.repo

或者直接 wget 把repo文件下载到 /etc/yum.repos.d/ 目录中
wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo

yum安装maven最新版

yum install -y apache-maven
查看 maven 版本

$ mvn -version
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T15:58:13+08:00)
Maven home: /usr/share/apache-maven
Java version: 1.8.0_232, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-957.1.3.el7.x86_64", arch: "amd64", family: "unix"

yum 安装 maven 后会自动设置 MAVEN_HOMEM2_HOME 环境变量, 并将 mvn 命令链接到 /usr/bin/mvn

$ env|egrep 'MAVEN_HOME|M2_HOME'
MAVEN_HOME=/usr/share/apache-maven
M2_HOME=/usr/share/apache-maven
$ ll -h /usr/bin/mvn
lrwxrwxrwx. 1 root root 31 12月 26 11:11 /usr/bin/mvn -> /usr/share/apache-maven/bin/mvn

Maven Wrapper(mvnw)

背景
Maven 是一款非常流行的 Java 项目构建软件,它集项目的依赖管理、测试用例运行、打包、构件管理于一身,是我们工作的好帮手,maven 飞速发展,它的发行版本也越来越多,如果我们的项目是基于 Maven 构件的,那么如何保证拿到我们项目源码的同事的 Maven 版本和我们开发时的版本一致呢,可能你认为很简单,一个公司嘛,规定所有的同事都用一个 Maven 版本不就万事大吉了吗?一个组织内部这是可行的,要是你开源了一个项目呢?如何保证你使用的 Maven 的版本和下载你源码的人的 Maven 的版本一致呢,这时候 mvnw 就大显身手了。

而 Gradle 提供了一个 Wrapper,可以很好解决版本切换的问题,当然更重要的是不需要预安装Gradle。

Maven虽然没有官方的Wrapper,但是有一个第三方的Wrapper可以使用。
https://github.com/takari/maven-wrapper

mvnw 全名是 Maven Wrapper,它的原理是在 maven-wrapper.properties 文件中记录你要使用的 Maven 版本,当用户执行 mvnw clean 命令时,发现当前用户的 Maven 版本和期望的版本不一致,那么就下载期望的版本,然后用期望的版本来执行mvn命令,比如刚才的mvn clean。

为项目添加mvnw支持很简单,有两种方式:

方法一:在Pom.Xml中添加Plugin声明:

<plugin>
    <groupId>com.rimerosolutions.maven.plugins</groupId>
    <artifactId>wrapper-maven-plugin</artifactId>
    <version>0.0.4</version>
</plugin>

这样当我们执行mvn wrapper:wrapper 时,会帮我们生成 mvnw.bat, mvnw, maven/maven-wrapper.jar, maven/maven-wrapper.properties 这些文件。

然后我们就可以使用mvnw代替mvn命令执行所有的maven命令,比如mvnw clean package

方法二:直接执行Goal(推荐使用这种)
mvn -N io.takari:maven:wrapper -Dmaven=3.3.3 表示我们期望使用的Maven的版本为3.3.3

产生的内容和第一种方式是一样的,只是目录结构不一样,maven-wrapper.jar和maven-wrapper.properties在”.mvn/wrapper”目录下

使用的注意事项

1、由于我们使用了新的Maven ,如果你的settings.xml没有放在当前用户下的.m2目录下,那么执行mvnw时不会去读取你原来的settings.xml文件

2、在mvnw.bat中有如下的一段脚本:if exist "%M2_HOME%\bin\mvn.cmd" goto init,意思是如果找到mvn.cmd就执行初始化操作,但是Maven早期版本不叫mvn.cmd,而是叫mvn.bat,所以会报”Error: M2_HOME is set to an invalid directory”错误,改成你本地的maven的匹配后缀就好了。

mvnw脚本

mvnw是什么?
Maven Wrapper/Maven保持构建工具版本一直的工具
mvnw是一个maven wrapper script,它可以让你在没有安装maven或者maven版本不兼容的条件下运行maven的命令.

原理:

  1. 它会寻找maven在你电脑环境变量path中的路径
  2. 如果没有找到这个路径它就会自动下载maven到一个默认的路径下,之后你就可以运行maven命令了
  3. 有时你会碰到一些项目的peoject和你本地的maven不兼容,它会帮你下载合适的maven版本,然后运行

mvnw是什么(Maven Wrapper/Maven保持构建工具版本一直的工具)
https://www.cnblogs.com/EasonJim/p/7620085.html

maven-wrapper介绍
https://juejin.im/post/5b5c742751882508603d005e

http://mvnrepository.com/artifact/com.rimerosolutions.maven.plugins/wrapper-maven-plugin


Maven命令

mvn [options] [<goal(s)>] [<phase(s)>]
-s,--settings <arg>,指定用户 settings.xml 文件
-D,--define <arg>,定义系统属性,例如 -Dmaven.test.skip=true
-v,--version,查看maven版本
-X,--debug,打开debug输出
-e,--errors 显示maven运行出错的信息

mvn compile,在项目根目录下执行mvn compile命令可编译项目,build success之后在项目根目录下生成target目录,该目录下存放项目编译后的文件,如.class文件

mvn test,会执行src/test/java 下的Junit测试代码,当然在执行测试之前会自动执行编译命令

mvn package,会将项目打成jar包,并放在target目录中。执行此命令之前会先执行编译和测试命令
mvn package -Pdev 指定 dev profile 打包。不写则默认加载 active 的配置。

mvn install,会将项目jar包安装到本地仓库中,以便其他项目使用。执行此命令之前会先执行编译,测试,打包命令

mvn clean,清理项目,会删除target文件夹,该命令可以结合其他命令运行

mvn deploy,部署构件到maven远程仓库,需要配置<distributionManagement>/<repository>和对应的认证信息。

-Pprofile 指定不同profile

-P,--activate-profiles <arg> 指定 Profile 配置,可以用于区分环境,例如 mvn package -PprofileTwo

-pl/-am/-amd 构建指定模块

-pl, --projects 构建指定的模块,模块间用逗号分隔
-am, --also-make 同时构建所列模块的依赖模块,比如A依赖B,B依赖C,构建B,同时构建C
-amd, --also-make-dependents 同时构建依赖于所列模块的模块,比如A依赖B,B依赖C,构建B,同时构建A

例1,单独构建 common 模块,同时构建 common 模块依赖的模块
mvn install -pl common -am

例2,单独构建 common 模块,同时构建 common 依赖的模块,并构建依赖 common 的模块
mvn install -pl common -am -amd

mvn -U 强制更新snapshot依赖

-U,--update-snapshots 强制去远程更新 snapshot 的插件或依赖,默认每天只更新一次。

mvn clean install -e -U 强制更新依赖

-Dmaven.test.skip=true 跳过测试

mvn -U clean install -Dmaven.test.skip=true --settings settings.xml 强制更新并install,跳过测试,指定 settings 文件

-Dmaven.source.skip=true 跳过源码jar

-Dmaven.source.skip=true 是 Maven 的一个命令行选项,当设置为 true 时,它将跳过构建项目源码的 JAR 文件。

mvn -T 并发线程数

mvn -T 4 clean install 4线程并发
mvn -T 1C clean install 等于cpu核数
mvn -T 1.5C clean install 1.5倍cpu核数

mvn dependency:tree 查看依赖树

Apache/ Maven/ Plugins/ Apache Maven Dependency Plugin/ dependency:tree
https://maven.apache.org/plugins/maven-dependency-plugin/tree-mojo.html

mvn dependency:tree,查看maven依赖树,需要再 pom.xml 所在目录执行此命令

mvn dependency:tree | grep kafka 查看 kafka 依赖的版本

mvn dependency:tree -Dincludes=artifactId1,artifactId2,... 只查看指定的依赖
-Dincludes 指定逗号分割的依赖列表,语法为 [groupId]:[artifactId]:[type]:[version],其中每部分都是可选的,也都可以用通配符 * 匹配。
例如
mvn dependency:tree -Dincludes=org.apache.* 只查看 groupId 是 apache 的依赖
mvn dependency:tree -Dincludes=:::*-SNAPSHOT 只查看 snapshot 依赖
mvn dependency:tree -Dincludes=:httpclient 查看 httpclient 依赖

mvn dependency:tree -Dexcludes=artifactId1,artifactId2,... 排除指定的依赖,格式同 -Dincludes

mvn help:describe -Dcmd=phase 列出phase的全部goal

mvn help:describe -Dcmd=PHASENAME

例,查看 compile 生命周期的阶段:

mvn help:describe -Dcmd=compile
[INFO] 'compile' is a phase corresponding to this plugin:

It is a part of the lifecycle for the POM packaging 'pom'. This lifecycle includes the following phases:
* validate: Not defined
* initialize: Not defined
* generate-sources: Not defined
* process-sources: Not defined
* generate-resources: Not defined
* process-resources: Not defined
* compile: Not defined
* process-classes: Not defined
* generate-test-sources: Not defined
* process-test-sources: Not defined
* generate-test-resources: Not defined
* process-test-resources: Not defined
* test-compile: Not defined
* process-test-classes: Not defined
* test: Not defined
* prepare-package: Not defined
* package: Not defined
* pre-integration-test: Not defined
* integration-test: Not defined
* post-integration-test: Not defined
* verify: Not defined
* install: org.apache.maven.plugins:maven-install-plugin:2.4:install
* deploy: org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy

BOM

BOM(Bill Of Materials),材料清单。BOM 是一个普通的 POM 文件,其中罗列了一个工程的所有依赖和其对应的版本。该文件一般被其它工程使用,当其它工程引用 BOM 中罗列的依赖时,不用显示指定具体的版本,会自动使用 BOM 对应的版本。

引用 bom 的两种方式:
1、通过 parent 引用 bom,比如我们的 spring boot 项目通常将 parent 设为 spring-boot-starter-parent, spring-boot-starter-parent 就是个 bom

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.6.5</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>

2、通过 dependencyManagement 引用,比如我们引入 spring cloud 依赖时都会在根 pom 的 dependencyManagement 中加入:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-dependencies</artifactId>
  <version>${spring.cloud.version}</version>
  <type>pom</type>
  <scope>import</scope>
</dependency>

Maven POM

概述

POM全称是Project Object Model,即项目对象模型。pom.xml是maven的项目描述文件,它类似与antx的project.xml文件。pom.xml文件以xml的形式描述项目的信息,包括项目名称、版本、项目id、项目的依赖关系、编译环境、持续集成、项目团队、贡献管理、生成报表等等。总之,它包含了所有的项目信息。
Maven的中心思想是POM文件(项目对象模型)。POM文件是以XML文件的形式表述项目的资源,如源码、测试代码、依赖(用到的外部Jar包)等。POM文件应该位于项目的根目录下。
Maven的POM文件是一个xml文件,描述项目用到的资源,包括源代码目录、测试代码目录等的位置,以及项目依赖的外部jar包。
POM文件描述的是构建“什么”,而不是“如何”构建。如何构建是取决于Maven的构建阶段和目标。当然,如果需要,你也可以向Maven构建阶段中添加自定义的目标。
每一个项目都有一个POM文件。POM文件即pom.xml,应该放在项目的根目录下。一个项目如果分为多个子项目,一般来讲,父项目有一个POM文件,每一个子项目都有一个POM文件。在这种结构下,既可以一步构建整个项目,也可以各个子项目分开构建。

下图说明了Maven是如何使用POM文件的,以及POM文件的主要组成部分:

POM Reference(POM官方文档)
https://maven.apache.org/pom.html

Maven3.3.9 官方参考文档(POM元素详解)
https://maven.apache.org/ref/3.3.9/maven-model/maven.html

史上最全的maven pom.xml文件教程详解
http://blog.csdn.net/yaerfeng/article/details/26448417


Properties属性

自定义属性

在 pom.xml 文件的 <properties> 标签下定义的Maven属性
<properties><some.var>value</some.var></properties> 的值可通过 ${some.var} 访问

POM属性

使用 pom 属性可以引用到 pom.xml 文件对应元素的值
例如 <project><version>1.0</version></project> 可通过 ${project.version} 引用
例如 ${project.build.finalName} 表示打包名称

settings.xml文件属性

与pom属性同理, 用户使用以 settings. 开头的属性引用 settings.xml 文件中的XML元素值
例如 <settings><offline>false</offline></settings> 可通过 ${settings.offline} 访问
例如 ${settings.localRepository} 表示本地仓库的地址;

Java系统属性

所有可通过 java.lang.System.getProperties() 访问的 Java 系统属性都可以使用 Maven 引用
例如 ${java.home}

环境变量属性

所有的环境变量都可以用以env.开头的Maven属性引用
例如 ${env.PATH}, ${env.JAVA_HOME}
使用 mvn help:system 命令可查看所有环境变量;

POM Reference / The Basics / Properties
https://maven.apache.org/pom.html#Properties


Super POM

就像Java中的所有类都隐式继承自Object一样,对于pom.xml来说,它隐式继承超级POM,它包含了一些可以被继承的默认设置。
Maven 使用 effective pom(Super pom 加上工程自己的配置)来执行相关的目标,它帮助开发者在 pom.xml 中做尽可能少的配置,当然这些配置可以被方便的重写。

查看Super POM

查看 Super POM 默认配置的一个简单方法如下:
在你的电脑上的任意目录下创建一个 pom.xml 文件,使用最小pom中的内容,然后打开命令控制台,到 pom.xml 所在的目录下执行以下 mvn 命令:

mvn help:effective-pom

Maven 将会开始处理并显示 effective-pom,由于创建的是最小pom,所以所有内容都继承自超级POM

或者打开Maven安装目录中的lib/maven-model-builder-3.3.9.jar 包,能找到超级POM:maven-model-builder-3.3.9.jar\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven项目继承该配置。

Maven-3.3.9的Super POM内容

<?xml version="1.0" encoding="UTF-8"?>

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<!-- START SNIPPET: superpom -->
<project>
  <modelVersion>4.0.0</modelVersion>

  <repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
  </pluginRepositories>

  <build>
    <directory>${project.basedir}/target</directory>
    <outputDirectory>${project.build.directory}/classes</outputDirectory>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
    <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${project.basedir}/src/test/resources</directory>
      </testResource>
    </testResources>
    <pluginManagement>
      <!-- NOTE: These plugins will be removed from future versions of the super POM -->
      <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
      <plugins>
        <plugin>
          <artifactId>maven-antrun-plugin</artifactId>
          <version>1.3</version>
        </plugin>
        <plugin>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.8</version>
        </plugin>
        <plugin>
          <artifactId>maven-release-plugin</artifactId>
          <version>2.3.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

  <reporting>
    <outputDirectory>${project.build.directory}/site</outputDirectory>
  </reporting>

  <profiles>
    <!-- NOTE: The release profile will be removed from future versions of the super POM -->
    <profile>
      <id>release-profile</id>

      <activation>
        <property>
          <name>performRelease</name>
          <value>true</value>
        </property>
      </activation>

      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-source-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-javadoc-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-javadocs</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
              <updateReleaseInfo>true</updateReleaseInfo>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

</project>
<!-- END SNIPPET: superpom -->

project

  • modelVersion,遵从哪种pom描述版本,使用maven2必须配置为4.0.0
  • parent,父项目的坐标,如果有的话。如果项目中没有规定某个元素的值,那么父项目中的对应值即为默认值。坐标由groupId,artifactId和 version确定。
  • groupId,项目或者组织的唯一标志,并且配置时生成路径也是由此生成,如org.myproject.mojo生成的相对路径为:/org/myproject/mojo
  • artifactId,构建(artifact)的唯一标识,在给定的groupId中必须唯一。
  • version,项目当前版本,格式为:主版本.次版本.增量版本-限定版本号
  • packaging,此项目生成的构建的打包类型,如pom,jar,maven-plugin,ejb,war,ear,rar,par,默认值为jar

注意:对于父子项目, 父项目的打包方式必须是 pom

  • name,项目的名称, Maven产生的文档用,可选
  • url,项目主页的URL, Maven产生的文档用,可选
  • description,项目的详细描述, Maven 产生的文档用,可选
  • prerequisites,描述了这个项目构建环境中的前提条件。
  • modules/module,模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径
  • distributionManagement,项目分发信息,在执行mvn deploy后表示要发布的位置。有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。
  • properties/key=value,在整个pom文件中可引用的属性变量,格式为<name>value</name>
  • dependencyManagement,继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,而是当子项目声明一个依赖(必须描述group ID和artifact ID信息),如果group ID和artifact ID以外的一些信息没有描述,则通过group ID和artifact ID匹配到这里的依赖,并使用这里的依赖信息。
  • dependencies/dependency,该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。
  • repositories/repository,发现依赖和扩展的远程仓库列表。
  • pluginRepositories/pluginRepository,发现插件的远程仓库列表,这些插件用于构建和报表
  • build,构建项目需要的信息
  • profiles/profile,一个或多个构建profile,如果被激活,会修改构建过程

dependencyManagement

dependencyManagement元素用于有子模块的maven项目的顶层POM文件中,通过它元素来管理jar包的版本,让子项目中引用一个依赖而不用显示的列出版本号。Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用在这个dependencyManagement元素中指定的版本号。

这样做的好处:统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,才能保证测试的和发布的是相同的成果,因此,在顶层pom中定义共同的依赖关系。同时可以避免在每个使用的子项目中都声明一个版本号,这样想升级或者切换到另一个版本时,只需要在父类容器里更新,不需要任何一个子项目的修改;如果某个子项目需要另外一个版本号时,只需要在dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。

顶层pom中的dependencies与dependencyManagement中的dependencies的区别
dependencyManagement 中的 dependencies 元素只表明依赖项版本的优先选择,并不影响项目的依赖项;而 dependencies 元素则影响项目的依赖项。
dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

相对于dependencyManagement,所有声明在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。即父项目dependencies中声明的依赖项,即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)


distributionManagement

项目分发信息,主要用于artifact或site的部署参数配置。即在执行mvn deploy后要部署到的位置。有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。

  • repository,部署项目产生的构件到远程仓库需要的信息
  • snapshotRepository,构件的快照部署到哪里?如果没有配置该元素,默认部署到repository元素配置的仓库
  • site,部署项目的网站需要的信息
  • downloadUrl,项目下载页面的URL。如果没有该元素,用户应该参考主页。使用该元素的原因是:帮助定位那些不在仓库里的构件(由于license限制)。
  • relocation,如果构件有了新的group ID和artifact ID(构件移到了新的位置),这里列出构件的重定位信息。
  • status,给出该构件在远程仓库的状态。不得在本地项目中设置该元素,因为这是工具自动更新的。有效的值有:none(默认),converted(仓库管理员从Maven 1 POM转换过来),partner(直接从伙伴Maven 2仓库同步过来),deployed(从Maven 2实例部署),verified(被核实时正确的和最终的)。

例如部署到nexus私有库:

<distributionManagement>
    <repository>
        <id>pro-release</id>
        <name>Proj Release Repository</name>
        <url>http://172.27.19.161:8081/nexus/content/repositories/releases/</url>
    </repository>
    <snapshotRepository>
        <id>pro-snapshot</id>
        <name>Proj Snapshot Repository</name>
        <url>http://172.27.19.161:8081/nexus/content/repositories/snapshots/</url>
    </snapshotRepository>
</distributionManagement>

parent

父项目的坐标,如果有的话。如果项目中没有规定某个元素的值,那么父项目中的对应值即为默认值。坐标由groupId,artifactId和 version确定。

  • groupId,父项目的groupId
  • artifactId,父项目的artifactId
  • version,父项目的version
  • relativePath,父项目的pom.xml文件的相对路径。相对路径允许你选择一个不同的路径。默认值是../pom.xml。Maven首先在构建当前项目的地方寻找父项目的pom,其次在文件系统的这个位置(relativePath位置),然后在本地仓库,最后在远程仓库寻找父项目的pom。

parent.relativePath

parent.relativePath
默认值为 ../pom.xml
设定一个空值将始终从仓库中获取,不从本地路径获取,如 <relativePath />

maven 会从依次以下3个地方寻找 parent,查找顺序:relativePath元素中的地址–本地仓库–远程仓库

  • parent.relativePath, 默认值是 ../pom.xml, maven检查当前module的上级目录中是否有pom.xml文件,并且此pom文件的坐标和当前module的parent声明相同,如果是的话,就把此pom文件当做parent
  • local repository
  • remote repositories

Maven complaining about parent relative path
https://stackoverflow.com/questions/37062491/maven-complaining-about-parent-relative-path


repositories/repository

在repositories元素下,可以使用repository子元素声明一个或者多个远程仓库。

  • uniqueVersion,是分配给快照一个唯一的版本号(由时间戳和构建流水号),还是每次都使用相同的版本号。默认值为true
  • releases,如何处理远程仓库里发布版本的下载
  • snapshots,如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的策略。例如,可能有人会决定只为开发目的开启对快照版本下载的支持。
  • id,远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库
  • name,用户定义的仓库名称
  • url,远程仓库URL,按protocol://hostname/path形式
  • layout,用于定位和存储构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。

releases

如何处理远程仓库里发布版本的下载

  • enabled,该仓库是否为下载某种类型构件(发布版,快照版)开启。默认值为true
  • updatePolicy,该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。
  • checksumPolicy,当Maven验证构件校验文件失败时该怎么做:ignore(忽略),fail(失败),或者warn(警告)。默认为warn

snapshotRepository

部署到的snapshot远程仓库配置

  • id,repository的唯一标识,用来匹配settings.xml中配置的repository
  • name,用户定义的仓库名称
  • url,仓库url,格式为protocol://hostname/path

snapshots

用于repository的配置,表示如何处理从此库中的snapshots下载

  • enabled,该仓库是否为下载某种类型构件(发布版,快照版)开启。默认值为true
  • updatePolicy,该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。
  • checksumPolicy,当Maven验证构件校验文件失败时该怎么做:ignore(忽略),fail(失败),或者warn(警告)。默认为warn

pluginRepositories/pluginRepository

发现插件的远程仓库列表,这些插件用于构建和报表


dependency

dependency表示项目中一项依赖的配置信息

  • groupId,依赖的group ID,例如org.apache.maven
  • artifactId,依赖的artifact ID,即依赖的项目名
  • version,依赖的版本号。 在Maven 2里, 也可以配置成版本号的范围。
  • type,依赖类型,默认类型是jar。它通常表示依赖的文件的扩展名,但也有例外。一个类型可以被映射成另外一个扩展名或分类器。类型经常和使用的打包方式对应,尽管这也有例外。一些类型的例子:jar,war,ejb-client和test-jar。如果设置extensions为 true,就可以在plugin里定义新的类型。所以前面的类型的例子不完整。
  • classifier,依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。分类器名被附加到文件名的版本号后面。例如,如果你想要构建两个单独的构件成JAR,一个使用Java 1.4编译器,另一个使用Java 6编译器,你就可以使用分类器来生成两个单独的JAR构件。
  • scope,依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来。
  • exclusions/exclusion,当计算传递依赖时,需要从依赖列表里被排除的依赖构件集。即告诉maven你只依赖指定的项目,不依赖此项目的依赖。此元素主要用于解决版本冲突问题
  • optional,可选依赖,如果你在项目B中把C依赖声明为可选,你就需要在依赖于B的项目(例如项目A)中显式的引用对C的依赖。可选依赖阻断依赖的传递性。默认值为false。

scope依赖范围配置(默认compile)

依赖范围配置用于限制一个依赖的传递性,也会影响编译、测试等阶段所使用的classpath路径,以及决定哪个artifact会被包含在项目的发布版本中。
有6中可用的范围:

  • compile, 编译范围,默认为compile范围
    compile 是默认的范围;如果没有提供一个范围,那该依赖的范围就是编译范围。编译范围依赖在所有的 classpath 中可用,同时它们也会被传递和打包。
    对于 scope=compile 的情况(默认scope),也就是说这个项目在编译,测试,运行阶段都需要这个 artifact 对应的 jar 包在 classpath 中。
    compile 表示被依赖项目需要参与当前项目的编译,包括后续的测试,运行周期也参与其中,同时打包的时候也会包含进去。是最常用的,所以也是默认的。

  • provided, 已提供范围
    provided 依赖在编译和测试的时候有效,在执行(mvn package)进行打包成war、jar包的时候不会加入
    provided 依赖只有在当 JDK 或者一个容器已提供该依赖之后才使用。例如,如果你开发了一个 web 应用,你可能在编译 classpath 中需要可用的 Servlet API 来编译一个 servlet, 但是你不会想要在打包好的 WAR 中包含这个 Servlet API,因为这个 Servlet API JAR 已经由你的应用服务器或者 servlet 容器提供。已提供范围的依赖在编译 classpath(不是运行时)可用。

provided 依赖是不传递性的,也不会被打包
对于 scope=provided 的情况,则可以认为这个 provided 是目标容器已经 provide 这个 artifact. 换句话说,它只影响到编译,测试阶段。在编译测试阶段,我们需要这个 artifact 对应的 jar 包在 classpath 中,而在运行阶段,假定目标的容器(比如我们这里的liferay容器)已经提供了这个jar包,所以无需我们这个artifact对应的jar包了。

  • runtime, 运行时范围
    runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要。
    runtime 范围表示被依赖项目无需参与项目的编译,不过后期的测试和运行周期需要其参与。与 compile 相比,跳过编译而已。
    数据库的驱动包一般都是 runtime 依赖,因为在我们在编码时只会使用 JDK 提供的 jdbc 接口,而具体的实现是有对应的厂商提供的驱动(如mysql驱动),实在运行时生效的,所以这类jar包无需参与项目的编译。

  • test, 测试范围
    test 范围依赖 在一般的 编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。
    test 表示只会在测试阶段使用,在 src/main/java 里面的代码是无法使用这些api的,并且项目打包时,也不会将”test”标记的打入”jar”包或者”war”包。

  • system, 系统范围
    system 依赖不从maven仓库获取,而是本地的jar包,因此必须配合 <systemPath>${basedir}/lib/xx.jar</systemPath> 标签来指定本地的jar包所在全路径。这类jar包默认会参与编译、测试、运行,但是不会被参与打包阶段。如果也想打包进去的话,需要在插件里做配置 <includeSystemScope>true</includeSystemScope>
    注意该范围是不推荐使用的(你应该一直尽量去从公共或定制的Maven仓库中引用依赖)。

  • import, 导入范围,Maven 2.0.9及以上版本才有
    import 比较特殊,他的作用是将其他模块定义好的 dependencyManagement 导入当前 Maven 项目 pom 的 dependencyManagement 中,都是配合 <type>pom</type> 来进行的。所以import作用的是pom类型,不是jar包。

Introduction to the Dependency Mechanism
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

maven dependency中scope=compile 和 provided区别
http://blog.csdn.net/u013704227/article/details/46460913

Maven学习详解(13)——Maven常用命令大全与pom文件讲解
http://blog.csdn.net/u012562943/article/details/50461166

test和provided依赖不会传递

scope 为 test 或 provided 的依赖不会传递。

比如我们以 provided 范围引入的 lombok 的话,是不会传递到引用方的。

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
    <scope>provided</scope>
</dependency>

还有比如以 test 范围引入的 h2 数据库,也不会传递到引用方:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.195</version>
    <scope>test</scope>
</dependency>

依赖的传递/冲突/排除

依赖传递

假如项目 A 依赖 B,B 依赖 C,即 A->B->C,默认情况下(optional=false) maven 会自动在项目 A 中导入 C,这就是依赖的传递性。

optional=true 阻断依赖传递

如果我的当前项目是 project1,project1 依赖 project2 的配置中加上 <optional>true</optional> ,表示依赖可选,可选阻断 project2 从 project1 中向外传递。

<dependency>
    <groupId>com.projecct</groupId>
    <artifactId>project2</artifactId>
    <version>1.0</version>
    <scope>compile</scope>
    <optional>true</optional>
</dependency>

那么以后所有声明依赖 project1 的项目如果也依赖 project2,就必须写手动声明。比如 project3 依赖 project1 和 project2,如果 project3 只声明了对 project1 的依赖,那么 project2 不会自动加入依赖,需要重新声明对 project2 的依赖。

什么时候需要把引入的依赖标为 <optional>true</optional> 呢?
一个场景是,比如我有个 user 项目,我打出了一个 user-client 包给别人用,如果我的 user-client 引了一个很重的第三方包,则我需要把这个第三方包标为 <optional>true</optional> ,否则直接会导致使用我的 user-client 的项目也莫名其妙的引入了一个很重的包。假如这个包中有自动启动的定时任务啊、Configuration配置啊,可能直接给别的项目带来性能问题。

依赖冲突

依赖冲突:一个项目 A,通过不同依赖传递路径依赖于 X,若在不同路径下传递过来的 X 版本不同,那么 A 应该导入哪个版本的 X 包呢?
冲突解决方案:
1、如果依赖路径的长度不同,则最短路径优先
A->B->C->D->E->X(version 0.0.1)
A->F->X(version 0.0.2)
则A依赖于X(version 0.0.2)。

2、依赖路径长度相同情况下,则先声明优先
A->E->X(version 0.0.1)
A->F->X(version 0.0.2)
则在项目A的<dependencies></dependencies>中,E,F哪个在先则A依赖哪条路径的X。

exclusion依赖排除

A->B->C(1.0)
此时在A项目中,不想使用C(1.0),而使用C(2.0)
则需要使用exclusion排除B对C(1.0)的依赖。并在A中引入C(2.0).
pom.xml中配置:

<!--排除B对C的依赖-->
<dependency>
    <groupId>B</groupId>
    <artifactId>B</artifactId>
    <version>0.1</version>
    <exclusions>
         <exclusion>
            <groupId>C</groupId>
            <artifactId>C</artifactId><!--无需指定要排除项目的版本号-->
         </exclusion>
    </exclusions>
</dependency>

<!---在A中引入C(2.0)-->
<dependency>
    <groupId>C</groupId>
    <artifactId>C</artifactId>
    <version>2.0</version>
</dependency>

循环依赖导致 Could not resolve dependencies for

问题:
通过 mvn versions:set -DnewVersion=1.0.1-SNAPSHOT -DgenerateBackupPoms=false 修改 app1 版本为 1.0.1
之后编译报错:

[ERROR] Failed to execute goal on project app1-common: Could not resolve dependencies for project com.xx:app1-common:jar:1.0.1-SNAPSHOT: The following artifacts could not be resolved: com.xxx:app1-common:jar:1.0.1-SNAPSHOT (absent): Could not find artifact com.xxx:app1-common:jar:1.0.1-SNAPSHOT in public (http://maven.xxx.com:8081/nexus/content/groups/public/) -> [Help 1]

原因:
app1-common 中引用了 app2-common,app2-common 中又引用了 app1-common,所以编译 app1-common 时需要循环去 nexus 下载自己,下载不到导致报错

解决:
引用 app2-common 时,从 app2-common 中排除 app1-common,消除循环依赖

<dependency>
    <groupId>com.xxx</groupId>
    <artifactId>app2-common</artifactId>
    <version>1.0.1</version>
    <exclusions>
        <exclusion>
            <groupId>com.xxx</groupId>
            <artifactId>app1-common</artifactId>
        </exclusion>
    </exclusions>
</dependency>

maven强制更新依赖(-U)

mvn clean install -e -U
-e 详细异常,-U 强制更新


依赖包没更新导致java.lang.NoSuchMethodError

开发中多次遇到这个问题,场景如下:
common包中更新了方法签名,比如原来是 setValue(long v) 改为 setValue(Long v)
install安装common包到本地.m2库中,引用common包的地方也用使用了修改后的代码,但允许时出现 java.lang.NoSuchMethodError 错误提示没有这个方法。

原因:target中的common包没更新

解决方法:
1、mvn clean 删除target目录
2、再 mvn install 重新引入一下,或 Idea 中在pom文件上右键 Maven -> Reimport

或者直接强制更新依赖。
mvn clean install -e -U

The POM for xxx is invalid, transitive dependencies (if any) will not be available

mvn install -N

https://stackoverflow.com/questions/23581194/the-pom-for-name-is-invalid-transitive-dependencies-if-any-will-not-be-avai


build

构建项目需要的信息,默认值已在Super POM中配置。

  • sourceDirectory,该元素设置了项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。默认值为src/main/java
  • scriptSourceDirectory,该元素设置了项目脚本源码目录,该目录和源码目录不同:绝大多数情况下,该目录下的内容会被拷贝到输出目录(因为脚本是被解释的,而不是被编译的)。默认值为src/main/scripts
  • testSourceDirectory,该元素设置了项目单元测试使用的源码目录,当测试项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。默认值为src/test/java
  • outputDirectory,被编译过的应用class文件存放的目录。默认值为target/classes
  • testOutputDirectory,被编译过的测试class文件存放的目录。默认值为target/test-classes
  • extensions/extension,该项目使用的一系列构建扩展
  • defaultGoal,当项目没有规定目标(Maven2 叫做阶段)时的默认值
  • resources/resource 这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。默认值为src/main/resources
  • testResources/testResource,这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。默认值为src/test/resources
  • directory,构建产生的所有文件存放的目录,默认值为target
  • finalName,产生的构件的文件名,默认值是${artifactId}-${version}
  • filters/filter,当filtering开关打开时,使用到的过滤器属性文件列表
  • pluginManagement,该项目的子项目可以引用的默认插件信息。该插件配置项直到被引用时才会被解析或绑定到生命周期。给定插件的任何本地配置都会覆盖这里的配置
  • plugins/plugin,使用的插件列表

extension

描述使用到的构建扩展

  • groupId,构建扩展的groupId
  • artifactId,构建扩展的artifactId
  • version,构建扩展的版本

resource

这个元素描述了项目相关或单元测试相关的所有资源路径

  • targetPath,描述了资源的目标路径。该路径相对target/classes目录(例如${project.build.outputDirectory})。举个例子,如果你想资源在特定的包里(org.apache.maven.messages),你就必须该元素设置为org/apache/maven/messages。然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。
  • filtering,是否使用参数值代替参数名。参数值取自properties元素或者文件里配置的属性,文件在filters元素里列出。
  • directory,描述存放资源的目录,该路径相对POM路径
  • includes/include,包含的模式列表,例如**/*.xml
  • excludes/exclude,排除的模式列表,例如**/*.xml

resource详解

主要用于打包资源文件,默认情况下maven只打包 src/main/resource 下的资源,通过:
1、设置 <build><resources><resource>
2、使用 build-helper-maven-plugin 插件
3、使用 maven-resources-plugin 插件
都可以自定义要打包的资源

一般情况下,我们用到的资源文件(各种xml,properties,xsd文件)都放在src/main/resources下面,利用maven打包时,maven能把这些资源文件打包到相应的jar或者war里。

有时候,比如mybatis的mapper.xml文件,我们习惯把它和Mapper.java放在一起,都在src/main/java下面,这样利用maven打包时,就需要修改pom.xml文件,来吧mapper.xml文件一起打包进jar或者war里了,否则,这些文件不会被打包的。(maven认为src/main/java只是java的源代码路径)。

示例,下面的 resources 配置意思是:
先通过第一个 resource 将 src/main/resources 中的 application*.properties 排除掉
再通过第二个 resource 将 src/main/resources 中的 application.properties 和 application-${profile.active}.properties 引入,其中 profile.active 是打包时的 profile 变量

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <excludes>
        <exclude>application*.properties</exclude>
      </excludes>
    </resource>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
      <includes>
        <include>application.properties</include>
        <include>application-${profile.active}.properties</include>
      </includes>
    </resource>
  </resources>
</build>

plugin

plugin 元素包含描述插件所需要的信息。

每一个插件可以定义插件的groupId与artifactId,以及要执行的 executions, executions 下可以定义一大堆的 execution 用来定义具体的任务,其中又包括目标、绑定的阶段、配置等参数。

  • groupId,插件在仓库里的group ID,默认值为org.apache.maven.plugins
  • artifactId,插件在仓库里的artifact ID
  • version,被使用的插件的版本(或版本范围)
  • extensions,是否从该插件下载Maven扩展(例如打包和类型处理器),由于性能原因,只有在真需要下载时,该元素才被设置成enabled。默认值为false
  • executions/execution 在构建生命周期中执行一组目标(goals)的配置。每个目标可能有不同的配置。
  • dependencies/dependency,项目引入插件所需要的额外依赖
  • inherited,任何配置是否被传播到子项目,默认值为true
  • configuration,专属此插件的配置信息

execution

execution元素包含了插件执行需要的信息

  • id,执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标
  • phase,绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到插件里配置的默认阶段
  • goals/goal,配置的执行目标
  • inherited,配置是否被传播到子POM,默认值为true
  • configuration,作为DOM对象的配置

profile

profile 定义一个构建配置,可根据环境参数或命令行参数激活不同的构建配置

  • id,构建配置的唯一标识符。即用于命令行激活,也用于在继承时合并具有相同标识符的profile
  • activation,自动触发profile的条件逻辑。Activation是profile的开启钥匙。profile的力量来自于它能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。activation元素并不是激活profile的唯一方式。
  • build,构建项目所需要的信息。
  • modules/module,模块(有时称作子项目)被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径
  • distributionManagement,项目分发信息,在执行mvn deploy后表示要发布的位置。有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。
  • properties/key=value,在整个pom文件中可引用的属性变量,格式为<name>value</name>
  • dependencyManagement,继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,而是当子项目声明一个依赖(必须描述group ID和artifact ID信息),如果group ID和artifact ID以外的一些信息没有描述,则通过group ID和artifact ID匹配到这里的依赖,并使用这里的依赖信息。
  • dependencies/dependency,该元素描述了项目相关的所有依赖。
  • repositories/repository,发现依赖和扩展的远程仓库列表。
  • pluginRepositories/pluginRepository,发现插件的远程仓库列表,这些插件用于构建和报表

activation

  • activeByDefault,profile默认是否激活的标志,默认值为false,如果设为true此profile将被激活,除非此pom中另一个profile被命令行参数-P指定。
  • jdk,当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,而!1.4激活所有版本不是以1.4开头的JDK。支持区间值,[1.5,)匹配jdk1.5及以上版本。
  • os,当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。
  • property,如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活。如果值字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段
  • file,如果指定的文件存在,则激活profile。

os

当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。

  • name,激活profile的操作系统的名字
  • family,激活profile的操作系统所属家族(如windows或linux)
  • arch,激活profile的操作系统体系结构,如x86
  • version,激活profile的操作系统版本

property

如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活。如果值字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段

  • name,激活profile的属性的名称
  • value,激活profile的属性的值

file

提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活profile。另一方面,exists则会检查文件是否存在,如果存在则激活profile。

  • missing,如果指定的文件不存在,则激活profile。
  • exists,如果指定的文件存在,则激活profile。

使用maven profile实现多环境可移植构建
http://blog.csdn.net/mhmyqn/article/details/24501281

Maven简介(三)——profile介绍
http://elim.iteye.com/blog/1900568


scm

版本控制配置,指定项目的 git/svn/cvs 地址,可以屏蔽不用版本控制工具的差异, maven-release-plugin 插件需要读此配置。

<project>
  ...
  <scm>
    <connection>scm:git:ssh://git@github.com:masikkk/madaimeng_backup.git</connection>
    <developerConnection>scm:git:ssh://git@github.com:masikkk/madaimeng_backup.git</developerConnection>
    <tag>HEAD</tag>
    <url>https://github.com/masikkk/madaimeng_backup</url>
  </scm>
  ...
</project>

connection 有读权限的git项目地址,可以用SSH也可以用HTTPS的,例如 scm:git:ssh://git@github.com:masikkk/madaimeng_backup.git scm:svn:https://127.0.0.1/svn/my-project
developerConnection 有写权限的git项目地址,可以用SSH也可以用 HTTPS的
url git项目浏览器里的地址
tag 默认为HEAD


Maven plugin

maven-compiler-plugin

如果我们不告诉 maven 使用什么样的jdk版本编译的话,它就会用 maven-compiler-plugin 默认的 jdk 版本来进行处理,这样就容易出现版本不匹配,以至于可能导致编译不通过的问题。
maven的默认编译使用的jdk版本貌似很低,使用maven-compiler-plugin插件可以指定项目源码的jdk版本,编译后的jdk版本,以及编码。

<plugin>
    <!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 -->
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <!-- 一般而言,target与source是保持一致的,但是,有时候为了让程序能在其他版本的jdk中运行(对于低版本目标jdk,源代码中不能使用低版本jdk中不支持的语法),会存在target不同于source的情况 -->
        <source>1.8</source> <!-- 源代码使用的JDK版本 -->
        <target>1.8</target> <!-- 需要生成的目标class文件的编译版本 -->
        <encoding>UTF-8</encoding><!-- 字符集编码 -->
        <skipTests>true</skipTests><!-- 跳过测试 -->
        <verbose>true</verbose>
        <showWarnings>true</showWarnings>
        <fork>true</fork><!-- 要使compilerVersion标签生效,还需要将fork设为true,用于明确表示编译版本配置的可用 -->
        <executable><!-- path-to-javac --></executable><!-- 使用指定的javac命令,例如:<executable>${JAVA_1_4_HOME}/bin/javac</executable> -->
        <compilerVersion>1.3</compilerVersion><!-- 指定插件将使用的编译器的版本 -->
        <meminitial>128m</meminitial><!-- 编译器使用的初始内存 -->
        <maxmem>512m</maxmem><!-- 编译器使用的最大内存 -->
        <compilerArgument>-verbose -bootclasspath ${java.home}\lib\rt.jar</compilerArgument><!-- 这个选项用来传递编译器自身不包含但是却支持的参数选项 -->
    </configuration>
</plugin>

Java 21 项目里编译兼容 Java 17 的版本

IDEA -> Project Settings -> SDK 还是 Java 21 不变,
注意代码里不能有只在 Java 21 里可用、不兼容 Java 17 的新特性,否则编译报错

方式1,将 maven-compiler-plugin 插件的 source 和 target 都改为 17,编译、deploy 到 maven 仓库

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>17</source>
        <target>17</target>
    </configuration>
</plugin>

方式2,如果没有显式配置 maven-compiler-plugin 插件,修改下面的 properties(经测试这种方式不生效)

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
    </properties>

maven-resources-plugin

Maven Resources Plugin 是 Apache Maven 团队提供的官方核心插件,能够将 Maven 项目中的各种资源文件复制到指定的输出目录中。

在 Maven 项目中的资源可以分为两类

  • main资源,指位于 src/main/resources 路径下的资源文件
  • test资源,指位于 src/test/resources 路径下的资源文件

Apache Maven Resources Plugin 提供的 Goals
1、resources:resources
将 main 资源文件复制到输出目录,默认已经加入到 Maven 的 process-resources 生命周期阶段。
<project><build><resources> 指定要复制的main资源文件,默认位于 src/main/resources 路径
<project><build><outputDirectory> 指定main资源的输出目录,默认位于 target/classes/ 路径

2、resources:testResources
将 test 资源文件复制到输出目录,默认已经加入到 Maven 的 process-test-resources 生命周期阶段。
<project><build><testResources> 指定要复制的test资源文件,默认位于 src/test/resources 路径
<project><build><testOutputDirectory> 指定test资源的输出目录,默认位于 target/test-classes/ 路径

3、resources:copy-resources
对于非main资源或非test资源,又没有在pom.xml的 <build><resources>...</build></resources> 配置的资源,在构建过程中不会输出到项目的 target/classes/ 目录下。
这时,可以通过 maven-resources-plugin 的 <configuration> 给出要复制的任何资源,并给出target下的输出目录

将其他模块 src/main/resources 中资源打包到 classpath

例1、假如当前模块 xx-server 引用了 common 模块,希望将 common 模块的 src/main/resources 中的资源拷贝到当前模块的编译输出目录 classpath 下
配置如下,使用 copy-resources 目标,在编译阶段 compile phase 完成文件拷贝,打包时将这些文件打包进生成的 JAR 包中

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-resources-plugin</artifactId>
  <version>3.2.0</version>
  <executions>
    <execution>
      <id>copy-resource</id>
      <phase>compile</phase>
      <goals>
        <goal>copy-resources</goal>
      </goals>
      <configuration>
        <outputDirectory>
          ${project.build.outputDirectory}
        </outputDirectory>
        <resources>
          <resource>
            <!-- 将 common 模块 src/main/resources 中的资源拷贝到默认输出目录 -->
            <directory>../common/src/main/resources</directory>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

../common 表示从当前模块用相对路径找到 common 模块。

还可以通过 <include>/<excludes> 指定具体要拷贝或排除的文件
例如,将 common 模块 src/main/resources 下的资源拷贝到默认输出目录下的 tesseract-traineddata 子目录,排除 libtesseract.dylib

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-resources-plugin</artifactId>
  <version>3.2.0</version>
  <executions>
    <execution>
      <id>copy-resource</id>
      <phase>compile</phase>
      <goals>
        <goal>copy-resources</goal>
      </goals>
      <configuration>
        <outputDirectory>
          ${project.build.outputDirectory}/tesseract-traineddata
        </outputDirectory>
        <resources>
          <resource>
            <!-- 将 common 模块 src/main/resources 下的全部资源拷贝到默认输出目录,排除 libtesseract.dylib -->
            <directory>../common/src/main/resources</directory>
            <excludes>
              <!-- 指定具体要排除的文件 -->
              <exclude>libtesseract.dylib</exclude>
            </excludes>
            <includes>
              <!-- 指定具体要拷贝的文件 -->
            </includes>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

maven-help-plugin

https://maven.apache.org/plugins/maven-help-plugin/

mvn help:describe 获取插件的目标goal信息

查看 git-commit-id-plugin 插件有哪些 goal

mvn help:describe -Dplugin=pl.project13.maven:git-commit-id-plugin:4.9.10 -Ddetail

Name: Git Commit Id Maven Plugin
Group Id: pl.project13.maven
Artifact Id: git-commit-id-plugin
Version: 4.9.10
Goal Prefix: git-commit-id

This plugin has 2 goals:

git-commit-id:revision
  Description: Puts git build-time information into property files or maven's
    properties.
  Implementation: pl.project13.maven.git.GitCommitIdMojo
  Language: java
  Bound to phase: initialize

  Available parameters:

git-commit-id:validateRevision
  Description: (no description available)
  Implementation: pl.project13.maven.validation.ValidationMojo
  Language: java
  Bound to phase: verify

  Available parameters:

maven-deploy-plugin

用于将构建出的构件直接部署到POM配置的远程库中

默认该插件已经配置在 Maven 的 deploy 阶段使用,而且该插件也没有配置参数,所以无需在项目的POM中配置该插件,直接执行如下命令即可。
mvn deploy

Deploy插件提供的goals: deploy:deploy, Maven项目的部署。从Maven项目的POM文件中读取必须信息,发布该Maven项目相关的所有构件(Maven项目的POM和各种构件)到远程库。该goal仅支持Maven项目。

deploy:deploy 的用法
对于正式的发布,在POM中配置 <distributionManagement/> 给出远程库 <repository/> 的url;
对于非正式的发布,还可以在POM中配置<distributionManagement/>给出远程库<snapshotRepository/>的url;
如果要发布Maven项目的网站,还可以在POM中配置<distributionManagement/>给出<site/>的url;
项目的POM中配置<distributionManagement/>只给出了远程库的url,要配置访问远程库的username/password,还需要在settings.xml中配置<server>
直接执行 mvn deploy 命令即可。

多模块项目deploy时忽略某个module

在不需要 deploy 的子 module pom 中配置

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-deploy-plugin</artifactId>
  <version>X.Y</version>
  <configuration>
    <skip>true</skip>
  </configuration>
</plugin>

https://maven.apache.org/plugins/maven-deploy-plugin/faq.html


maven-surefire-plugin

如果你执行过 mvn test 或者执行其他 maven 命令时跑了测试用例,你就已经用过 maven-surefire-plugin 了。
maven-surefire-plugin 是 maven 里执行测试用例的插件,不显示配置就会用默认配置。这个插件的 surefire:test 命令会默认绑定 maven 执行的 test 阶段。

surefire 跳过测试

跳过测试用例的几个方法:
1、在插件的 configuration 配置中声明跳过测试用例 -DskipTests=true

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19</version>
    <configuration>
        <skipTests>true</skipTests>
    </configuration>
</plugin>

-Dmaven.test.skip=true

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <skip>true</skip>
    </configuration>
</plugin>

2、在properties配置中声明跳过测试用例 -Dmaven.test.skip=true

<properties>
    <maven.test.skip>true</maven.test.skip>
</properties>

-DskipTests=true

<properties>
    <skipTests>true</skipTests>
</properties>

3、在执行maven命令时可以声明跳过测试用例
mvn test -Dmaven.test.skip=true

mvn test -DskipTests=true

maven.test.skip和skipTests的区别

-DskipTests,不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下
-Dmaven.test.skip=true,不执行测试用例,也不编译测试用例类。


maven-release-plugin

https://maven.apache.org/maven-release/maven-release-plugin/
maven-release-plugin 插件是 Maven 官方提供的插件,提供发布release包、升级pom版本,打tag并提交到SCM等功能。

maven-release-plugin 主要有三个目标 goals, 他们分别为:

mvn release:prepare

release:prepare 准备版本发布,依次执行下列操作:

release:prepare 流程:

  • 生成release.properties文件
  • 检查本地项目代码中是否有未提交的modifications
    [INFO] Verifying that there are no local modifications...
    
  • 检查项目的POM依赖或插件是否有SNAPSHOT版本
    [INFO] Checking dependencies and plugins for snapshots ...
    
  • 更新POM,将项目的version从*-SNAPSHOT改为用户输入的发布版本(参数配置或提示用户输入)
    [INFO] Checking in modified POMs...
    
  • 确定项目tag(tag名提示用户输入)
    默认tag格式为 @{project.artifactId}-@{project.version},也可以配置<tagNameFormat>以设置tag格式。
  • 更新POM,转换POM中的SCM信息,包括更新tag
  • 执行<preparationGoals>设置的goals, 默认为clean verify,即执行mvn clean verify,也可以配置<preparationGoals>
    <configuration>
      <preparationGoals>clean verify</preparationGoals>
    </configuration>
    
    执行期间,对项目代码进行单元测试(要跳过单元测试,则 mvn -Darguments="-DskipTests" …)。
  • 验证成功,第一次提交POM修改,并push到Git库的refs/heads/master
  • 为当前项目打tag,并push到Git库的refs/tags/my_tag_name
  • 为项目的version产生一个新的开发版本*-SNAPSHOT(参数配置或提示用户输入)
  • 更新POM为开发版本,并将更新后的POM再次提交到Git库

release:prepare的可配置的参数:

  • arguments 传给mvn命令的额外参数,空格分隔
    如果需要跳过单元测试,可以加入参数 -Darguments="-DskipTests" ,直接使用-Dmaven.test.skip=true是无效的。

  • autoVersionSubmodules, 默认值false,提示为各个子模块输入版本;如果值true,表示所有子模块采用与父模块相同的版本, maven-release-plugin就会自动为所有子模块使用与父模块一致的发布版本和新的SNAPSHOT版本
    mvn release:prepare -DautoVersionSubmodules=true

  • releaseVersion, 要发布的版本

  • developmentVersion, 本地工作目录的下一个开发版本

  • tag, 要写入版本控制的标签

例如,发布 3.5.1 release 版本,并设置 pom 下一个开发版本号为 3.5.2-SNAPSHOT

mvn release:prepare -DreleaseVersion=3.5.1 -DdevelopmentVersion=3.5.2-SNAPSHOT -Dtag=v3.5.1
mvn release:perform

mvn release:rollback

release:rollback 回退 release:prepare 所执行的操作。
将POM回退至release:prepare之前的状态,并提交。需要注意的是,该步骤不会删除release:prepare生成的标签,因此用户需要手动删除。

mvn release:perform

release:perform 执行版本发布。
签出release:prepare生成的标签中的源代码,并在此基础上执行mvn deploy命令打包并部署构件至仓库。

基本过程:

  • 依赖于release:prepare阶段生成的release.properties文件
  • 基于SCM的URL检出prepare阶段刚刚打标签的代码,
  • 执行指定的Maven goals, 默认为deploy site-deploy,将项目代码发布到SCM库中。
    <configuration>
      <goals>deploy</goals>
    </configuration>
    
  • 引用release:clean,删除release.properties等发布过程文件

maven-release-plugin相关配置

要使用 maven-release-plugin 插件,必须先为项目配置正确的 scm 版本控制信息。
因为 maven-release-plugin 需要知道版本控制系统的主干,标签等地址信息后才能执行相关的操作。
例如:

<project>
  ...
  <scm>
    <connection>scm:git:ssh://git@github.com:masikkk/madaimeng_backup.git</connection>
    <developerConnection>scm:git:ssh://git@github.com:masikkk/madaimeng_backup.git</developerConnection>
    <tag>HEAD</tag>
    <url>https://github.com/masikkk/madaimeng_backup</url>
  </scm>
  ...
  <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-release-plugin</artifactId>
            <configuration>
                <useReleaseProfile>false</useReleaseProfile>
                <tagNameFormat>v@{project.version}</tagNameFormat>
                <localCheckout>true</localCheckout>
                <pushChanges>false</pushChanges>
            </configuration>
        </plugin>
    </plugins>
  </build>
  ...
</project>

useReleaseProfile, 默认情况下Release插件会将源码和javadoc进行打包,如果想自己控制的话需要在插件的configuration中设置useReleaseProfile为false,这样跟直接使用mvn deploy进行项目发布的情况一致了。
https://maven.apache.org/maven-release/maven-release-plugin/perform-mojo.html#useReleaseProfile

pushChanges, 是否执行 git push 推送 pom 修改到 upstream, 默认 true
https://maven.apache.org/maven-release/maven-release-plugin/prepare-mojo.html#pushChanges

localCheckout, 使用本地 checkout 代替从 remote/upstream 远程拉取代码,默认 false。
经常把这个设为 true 是因为,release之前肯定刚刚从 remote 拉取最新代码到本地,所以不需要再次 pull 直接使用本地的就行。
https://maven.apache.org/maven-release/maven-release-plugin/perform-mojo.html#localCheckout

tagNameFormat, tag 格式, 默认值 @{project.artifactId}-@{project.version}
可用变量
groupId or project.groupId - The groupId of the root project.
artifactId or project.artifactId - The artifactId of the root project.
version or project.version - The release version of the root project.
https://maven.apache.org/maven-release/maven-release-plugin/prepare-mojo.html#tagNameFormat

Apache Maven Release Plugin插件详解
https://blog.csdn.net/taiyangdao/article/details/82658799


spring-boot-maven-plugin

spring-boot-maven-plugin 插件是将 springboot 的应用程序打包成 fat jar 的插件。
fat jar 比普通 jar 包包含的东西更多,普通 jar 只是将 .class 文件以及 resources 目录下的东西打包进去,但 fat jar 还将应用所依赖的 jar 包也包含进去,也就是 jar 包中有 jar 包。
所以,spring boot 借助 spring-boot-maven-plugin 将所有应用启动运行所需要的 jar 都包含进来,从逻辑上将具备了独立运行的条件。

将普通插件 maven-jar-plugin 生成的包和 spring-boot-maven-plugin 生成的包解压后对比,发现使用 spring-boot-maven-plugin 生成的 jar 中主要增加了两部分,第一部分是 lib 目录,这里存放的是应用的 Maven 依赖的 jar 包文件,第二部分是 spring boot loader 相关的类。

所以,只有在需要独立打成jar包 run 的模块的 pom 里才需要 spring-boot-maven-plugin 插件,不要在 parent 项目里包含这个插件


maven-assembly-plugin

maven-assembly-plugin 从其他仓库下载镜像

构建时 maven-assembly-plugin 偶尔会从没配置的 repository 下载 jar 包
https://issues.apache.org/jira/browse/MASSEMBLY-951

解决:
降级为 2.4.1 解决


versions-maven-plugin

http://www.mojohaus.org/versions-maven-plugin/

可以通过 maven 的插件方式来升级整个项目的版本号。

在项目顶层 pom 中添加 version 插件

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>versions-maven-plugin</artifactId>
  <version>2.3</version>
  <configuration>
   <generateBackupPoms>false</generateBackupPoms>
  </configuration>
</plugin>

一、批量修改版本号
1、修改所有 pom 模块版本号为 1.2.0-SNAPSHOT
mvn versions:set -DnewVersion=1.2.0-SNAPSHOT
默认 generateBackupPoms 参数为 true,修改后会产生 pom.xml.versionsBackup 备份文件

2、回退版本号
mvn versions:revert 回退到 set 之前的版本,回退是根据 pom.xml.versionsBackup 备份文件回退的。

3、确认修改过的版本号
mvn versions:commit 该命令会删除修改版本号时生成的 pom.xml.versionsBackup 备份文件。

二、或者可以不经过确认直接一次性修改,将 generateBackupPoms 设为 false 即可
mvn versions:set -DnewVersion=1.2.0-SNAPSHOT -DgenerateBackupPoms=false

versions-maven-plugin插件批量修改版本号
https://www.jianshu.com/p/88da01804d3c

多模块maven项目如何管理版本号?

子项目中通过 ${project.version} 引用父项目的版本,只在父项目中维护一个版本号。

Properties in parent definition are prohibited

maven 子模块中引用父模块的版本号时 ${project.version} 时 idea 报这个错,这个是 idea 的问题,不影响我们使用,但是就是看起来不舒服。

解决方法:
CMD+, 打开 idea 配置,搜索 prohibited 关键字,找到 Inspections -> Usage of properties in parent description 配置项,去掉勾选即可。


flyway-maven-plugin

https://flywaydb.org/documentation/maven/

<build>
  <plugins>
    <!-- flyway 数据库版本管理 -->
    <plugin>
      <groupId>org.flywaydb</groupId>
      <artifactId>flyway-maven-plugin</artifactId>
      <version>6.0.8</version>
      <!-- 配置flyway使用的数据库驱动 -->
      <dependencies>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.15</version>
        </dependency>
      </dependencies>
      <configuration>
        <!-- 配置目标数据库连接 -->
        <user>development</user>
        <password>development</password>
        <url>jdbc:mysql://localhost/blog</url>
        <!-- 配置数据库脚本位置 -->
        <locations>
          <location>filesystem:src/main/sql</location>
        </locations>
      </configuration>
    </plugin>
  </plugins>
</build>

mvn flyway:init (初始化Flyway metadata )
mvn flyway:migrate 执行Flyway 升级操作,即执行.sql脚本,第一次执行时如果发现没有 schema_version 表(新版本是 flyway_schema_history 表)会提示先执行 mvn flyway:baseline
Failed to execute goal org.flywaydb:flyway-maven-plugin:4.0.3:migrate (default-cli) on project user-server: org.flywaydb.core.api.FlywayException: Found non-empty schema blog without metadata table! Use baseline() or set baselineOnMigrate to true to initialize the metadata table.

mvn flyway:validate (校验Flyway 数据正确性)
mvn clean install flyway:migrate(清理,打包编译project)


git-commit-id-plugin

git-commit-id / git-commit-id-maven-plugin
https://github.com/git-commit-id/git-commit-id-maven-plugin

Injecting Git Information Into Spring
https://www.baeldung.com/spring-git-information

这个插件一共有2个目标(goal):
git-commit-id:revision:将构建时的信息保存到指定文件中或 maven 的属性中,默认绑定生命周期的阶段(phase):initialize
git-commit-id:validateRevision:校验属性是否符合预期值,默认绑定阶段:verify

1、配置示例
在编译输出目录中生成 git 信息文件 git.properties

<plugin>
    <groupId>pl.project13.maven</groupId>
    <artifactId>git-commit-id-plugin</artifactId>
    <version>4.9.10</version>
    <executions>
        <execution>
            <id>get-the-git-infos</id>
            <!-- 默认绑定阶段initialize -->
            <phase>initialize</phase>
            <goals>
                <!-- 目标:revision -->
                <goal>revision</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- 检查的仓库根目录,${project.basedir}:项目根目录,即包含pom.xml文件的目录 -->
        <dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
        <!-- false:扫描路径时不打印更多信息,默认值false,可以不配置 -->
        <verbose>true</verbose>
        <!-- 定义插件中所有时间格式,默认值:yyyy-MM-dd’T’HH:mm:ssZ -->
        <dateFormat>yyyy-MM-dd HH:mm:ss</dateFormat>
        <!-- git属性文件中各属性前缀,默认值git,可以不配置 -->
        <prefix>git</prefix>
        <!-- 生成git属性文件,默认false:不生成 -->
        <generateGitPropertiesFile>true</generateGitPropertiesFile>
        <!-- 生成git属性文件路径及文件名,默认${project.build.outputDirectory}/git.properties -->
        <generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
        <!-- 生成git属性文件格式,默认值properties -->
        <format>json</format>
    </configuration>
</plugin>

Unable to find commits until some tag

执行报错;

Failed to execute goal pl.project13.maven:git-commit-id-plugin:2.2.5:revision (get-the-git-infos) on project my-app: Could not complete Mojo execution... Unable to find commits until some tag: Walk failure.

原因:
ci-cd 中使用 git clone –depth=1 浅克隆下载的代码,没有 tag 信息,导致 git describe 报错

解决:
去掉 gitDescribe 配置项,不执行 git describe 即可


maven 仓库

概述

在Maven中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。
Maven在某个统一的位置存储所有项目的共享的构件,这个统一的位置,我们就称之为仓库,即仓库就是存放依赖和插件的地方
Maven仓库分为两大类:1.本地仓库 2.远程仓库,远程仓库又可分为3种:中央仓库、私服、其它公共库


构件存储路径解析

任何的构件都有唯一的坐标,Maven根据这个坐标定义了构件在仓库中的唯一存储路径。
以构件jms-spring-api

<dependency>
    <groupId>com.masikkk.jms</groupId>
    <artifactId>jms-spring-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <classifier>jdk17</classifier>
</dependency>

为例,存储路径解析算法如下:

  • 1、基于groupId准备路径,将句点分隔符转成路径分隔符,就是将”.”转换成”/“,例如:com.masikkk.jms解析为com/masikkk/jms
  • 2、基于artifactId准备路径,将artifactId连接到后面:com/masikkk/jms/jms-spring-api
  • 3、使用version准备路径,将version连接到后面:com/masikkk/jms/jms-spring-api/0.0.1-SNAPSHOT
  • 4、将artifactId和version以分隔符连字号连接到后面:com/masikkk/jms/jms-spring-api/0.0.1-SNAPSHOT/jms-spring-api-0.0.1-SNAPSHOT
  • 5、判断如果构件有classifier,就要在第4项后增加分隔符连字号,再加上classifier:com/masikkk/jms/jms-spring-api/0.0.1-SNAPSHOT/jms-spring-api-0.0.1-SNAPSHOT-jdk17
  • 6、检查构件的extension,如果extension存在,则加上句点分隔符和extension,而extension是由packaging决定的,默认packaging方式为jar则:com/masikkk/jms/jms-spring-api/0.0.1-SNAPSHOT/jms-spring-api-0.0.1-SNAPSHOT-jdk17.jar

SNAPSHOT版本

Maven版本可以包含一个字符串字面量来表示项目正处于活动的开发状态。如果一个版本包含字符串“SNAPSHOT”,Maven就会在安装或发布这个组件的时候将该符号展开为一个日期和时间值,转换为UTC(协调世界时)。SNAPSHOT版本在项目活动的开发过程中使用。如果你的项目依赖的一个组件正处于开发过程中,你可以依赖于一个SNAPSHOT版本,在你运行构建的时候Maven会定期的从仓库下载最新的snapshot。作为一个默认设置,Maven不会从远程仓库检查SNAPSHOT版本,要依赖于SNAPSHOT版本,用户必须在POM中使用repository和pluginRepository元素显式的开启下载snapshot的功能当发布一个项目的时候,你需要解析所有对SNAPSHOT版本的依赖至正式发布的版本。如果一个项目依赖于SNAPSHOT,那么这个依赖很不稳定,它随时可能变化。发布到非snapshot的Maven仓库(如http://repo1.maven.org/maven2)的构件不能依赖于任何SNAPSHOT版本,因为Maven的超级POM对于中央仓库关闭了snapshot。SNAPSHOT版本只用于开发过程。

有时pom.xml中的版本号version的值会有-SNAPSHOT后缀,SNAPSHOT表示开发分支上的最新代码,SNAPSHOT版本不保证代码的稳定性和不变性;相反,release版本(即任何不带-SNAPSHOT后缀的版本)的代码是不变的。
也就是说,SNAPSHOT版本是release版之前的开发版,SNAPSHOT版的代码比它的release版“旧”。
在release过程中,版本号x.y-SNAPSHOT变为x.y,同时,release过程还会将开发版的版本号改为x.(y+1)-SNAPSHOT。例如,版本1.0-SNAPSHOT发布(release)后变为版本1.0,同时新的开发版本号变为1.1-SNAPSHOT.

What is a SNAPSHOT version?
https://maven.apache.org/guides/getting-started/index.html#What_is_a_SNAPSHOT_version


Maven本地仓库及配置

本地仓库,顾名思义,就是Maven在本地存储构件的地方。
注:Maven的本地仓库在安装maven后并不会创建,它是在第一次执行maven命令的时候才被创建
Maven本地仓库的默认位置:无论是Windows还是Linux,在用户家目录下都有一个.m2/repository/目录,这就是Maven仓库的默认位置,即~/.m2/repository,使用过程中这个目录里的文件会比较多,占用空间越来越大。

用户范围settings.xml配置

在~/.m2/目录下创建settings.xml文件(拷贝Maven安装目录中的conf/settings.xml),,使用<localRepository>配置项配置本地仓库位置:

<localRepository>D:\.m2\repository</localRepository>

例如上面配置,就把默认的本地仓库更改到D:.m2\repository这个目录(这个目录结构需要自己创建好)。同时还需要把这个settings.xml文件复制一份到D:.m2\目录下,即保证settings.xml和repository并列放在同层目录下

全局范围settings.xml配置

编辑maven安装目录/conf下的settings.xml配置文件可对所有用户产生影响,配置方法同用户settings.xml配置。


Maven 远程仓库

中央仓库

中央仓库是默认的远程仓库,maven在安装的时候自带中央仓库配置,地址为:http://repo.maven.apache.org/maven2
在Super POM中可以看到中央仓库的配置:

<repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>http://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
</repositories>

中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到。


私服仓库

私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。我们还可以把一些无法从外部仓库下载到的构件上传到私服上。

Maven私服的特性:

  • 1、节省自己的外网带宽:减少重复请求造成的外网带宽消耗
  • 2、加速Maven构件:如果项目配置了很多外部远程仓库的时候,构建速度就会大大降低
  • 3、部署第三方构件:有些构件无法从外部仓库获得的时候,我们可以把这些构件部署到内部仓库(私服)中,供内部maven项目使用
  • 4、提高稳定性,增强控制:Internet不稳定的时候,maven构建也会变的不稳定,一些私服软件还提供了其他的功能
  • 5、降低中央仓库的负荷:maven中央仓库被请求的数量是巨大的,配置私服也可以大大降低中央仓库的压力

当前主流的maven私服:

  • 1、Apache的Archiva
  • 2、JFrog的Artifactory
  • 3、Sonatype的Nexus

Nexus 仓库

搭建Nexus私服:
Maven 私有库 Nexus的安装
http://www.cnblogs.com/hujihon/p/5679618.html

Maven学习总结(9)——使用Nexus搭建Maven私服
http://blog.csdn.net/u012562943/article/details/49782855

400:does not allow updating assets

出现: Return code is: 400, ReasonPhrase: Repository does not allow updating assets: maven-releases.

解决办法:在 nexus admin 管理界面的 maven-releases 设置为 Allow redeploy(可重复提交)即可(不建议这样,一般release应该设置为不可覆盖的。)

Blocked mirror for repositories

从 maven 3.8.1 版本开始默认配置文件中增加了一组标签,如果仓库镜像是 http 而不是 https 就会被拦截禁止访问,报错

Could not transfer artifact xxx from/to maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories: [public (http://blocked-repo/nexus/content/groups/public/, default, releases+snapshots), public-snapshots (http://blocked-repo/nexus/content/groups/public/, default, releases+snapshots)]

解决方法:
1、降级 maven 版本到 3.8.1 以下
2、将 nexus 仓库改为 https
3、注释掉 $MAVEN_HOME/conf/settings.xml 中的拦截标签:

<mirror>
    <id>maven-default-http-blocker</id>
    <mirrorOf>external:http:*</mirrorOf>
    <name>Pseudo repository to mirror external repositories initially using HTTP.</name>
    <url>http://0.0.0.0/</url>
    <blocked>false</blocked>
</mirror>

但如果使用的是 IDEA 内置 maven,无法编辑这个配置。

4、在 ~/.m2/setttings.xml 中添加同名mirror,然后指定这个mirror不对任何仓库生效

<mirror>
    <id>maven-default-http-blocker</id>
    <mirrorOf>!*</mirrorOf>
    <url>http://0.0.0.0/</url>
</mirror>

禁用nexus的redeploy

官方也建议禁用 redeploy
Nexus Tips: Disable Redeployment in Nexus
https://blog.sonatype.com/2009/11/nexus-tips-disable-redeployment-in-nexus/


添加Maven远程仓库

前面我们看到Super POM中配置了ID为central的远程仓库,我们也可以在POM中配置其它的远程仓库。这样做的原因有很多,比如你有一个局域网的私服仓库,使用该仓库能大大提高下载速度,继而提高构建速度,也有可能你依赖的一个jar在central中找不到,它只存在于某个特定的公共仓库(比如中央仓库中就没有javax.jms:jms-1.1.jar这个包,需要额外配上JBoss远程仓库),这样你也不得不添加那个远程仓库的配置。

Maven中添加远程仓库有两种配置方法:

  • 1、在项目的pom.xml中添加<repositories>/<repository>配置,这只针对具体的某一个项目。
  • 2、在Maven的settings.xml中添加<profiles>/<profile>/<repositories>/<repository>配置,可对所有项目起作用。

在项目pom.xml中配置远程仓库

例如在项目的pom.xml中添加JBoss远程仓库:

<project>
... ...
<!-- 配置JBoss远程仓库 -->
<repositories>
    <repository>
        <id>jboss</id>
        <name>JBoss Repository</name>
        <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
        <releases>
            <enabled>true</enabled>
            <updatePolicy>daily</updatePolicy>
            <checksumPolicy>warn</checksumPolicy>
        </releases>
        <snapshots>
            <enabled>false</enabled>
            <checksumPolicy>warn</checksumPolicy>
        </snapshots>
        <layout>default</layout>
    </repository>
</repositories>
... ...
</project>
  • repository:在repositories元素下,可以使用repository子元素声明一个或者多个远程仓库。
  • id:仓库声明的唯一id,尤其需要注意的是,Maven自带的中央仓库使用的id为central,如果其他仓库声明也使用该id,就会覆盖中央仓库的配置。
  • name:仓库的名称,让我们直观方便的知道仓库是哪个,暂时没发现其他太大的含义。
  • url:指向了仓库的地址,一般来说,该地址都基于http协议,Maven用户都可以在浏览器中打开仓库地址浏览构件。
  • releases和snapshots:用来控制Maven对于发布版构件和快照版构件的下载权限。需要注意的是enabled子元素,该例中releases的enabled值为true,表示开启JBoss仓库的发布版本下载支持,而snapshots的enabled值为false,表示关闭JBoss仓库的快照版本的下载支持。根据该配置,Maven只会从JBoss仓库下载发布版的构件,而不会下载快照版的构件。
  • layout:元素值default表示仓库的布局是Maven2及Maven3的默认布局,而不是Maven1的布局。基本不会用到Maven1的布局。
  • 其他:对于releases和snapshots来说,除了enabled,它们还包含另外两个子元素updatePolicy和checksumPolicy。
  • 元素updatePolicy用来配置Maven从远处仓库检查更新的频率,默认值是daily,表示Maven每天检查一次。其他可用的值包括:never-从不检查更新;always-每次构建都检查更新;interval:X-每隔X分钟检查一次更新(X为任意整数)。
  • 元素checksumPolicy用来配置Maven检查校验和文件的策略。当构建被部署到Maven仓库中时,会同时部署对应的检验和文件。在下载构件的时候,Maven会验证校验和文件,如果校验和验证失败,当checksumPolicy的值为默认的warn时,Maven会在执行构建时输出警告信息,其他可用的值包括:fail-Maven遇到校验和错误就让构建失败;ignore-使Maven完全忽略校验和错误。

在settings.xml中配置远程仓库

settings.xml中不直接支持<repositories>配置项,需要放在<profile>中,并使用<activeProfiles>元素激活该profile,例如在settings.xml中添加JBoss远程仓库:

<settings>
  ...
  <profiles>
    ...
    <profile>
      <id>jboss-public-repository</id>
        <repositories>
            <repository>
                <id>jboss</id>
                <name>JBoss Repository</name>
                <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
                <releases>
                    <enabled>true</enabled>
                    <updatePolicy>daily</updatePolicy>
                    <checksumPolicy>warn</checksumPolicy>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                    <checksumPolicy>warn</checksumPolicy>
                </snapshots>
                <layout>default</layout>
            </repository>
        </repositories>
    </profile>
    ...
  </profiles>

  <!-- 激活profile-->
  <activeProfiles>
    <activeProfile>jboss-public-repository</activeProfile>
  </activeProfiles>
  ...
</settings>

远程仓库认证

大部分公共的远程仓库无须认证就可以直接访问,但我们在平时的开发中往往会架设自己的Maven远程仓库,出于安全方面的考虑,我们需要提供认证信息才能访问这样的远程仓库。
配置认证信息和配置远程仓库不同,远程仓库可以直接在pom.xml中配置,但是认证信息必须配置在settings.xml文件中。这是因为pom往往是被提交到代码仓库中供所有成员访问的,而settings.xml一般只存在于本机。因此,在settings.xml中配置认证信息更为安全。
例如:

<settings>
  ...
    <servers>
        <server>
            <id>pro-snapshot</id>
            <username>admin</username>
            <password>admin123</password>
        </server>
        <server>
            <id>pro-release</id>
            <username>admin</username>
            <password>admin123</password>
        </server>
    </servers>
  ...
</settings>

上面代码我们配置了2个远程仓库认证信息,一个id为pro-snapshot,另一个id为pro-release。Maven使用settings.xml文件中的<servers>元素及其子元素<server>配置仓库认证信息。认证用户名为admin,认证密码为admin123。这里的关键是id元素,settings.xml中<server>元素的id必须与pom.xml中需要认证的<repository>元素的id完全一致,正是这个id将认证信息与仓库配置联系在了一起


配置远程仓库的镜像 Mirror

如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。换句话说,任何一个可以从仓库Y获得的构件,都能够从它的镜像中获取。
举个例子,阿里云maven仓库 http://maven.aliyun.com/nexus/content/groups/public/ 是中央仓库 https://repo.maven.apache.org/maven2 在中国的镜像,由于地理位置的因素,该镜像往往能够提供比中央仓库更快的服务。因此,可以配置Maven使用该镜像来替代中央仓库。编辑settings.xml,代码如下:

<mirrors>
    <mirror>
        <id>nexus-aliyun</id>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        <mirrorOf>central</mirrorOf>
    </mirror>
</mirrors>

该例中,<mirrorOf> 的值为central,表示该配置为中央仓库的镜像,任何对于中央仓库的请求都会转至该镜像,用户也可以使用同样的方法配置其他仓库的镜像。id表示镜像的唯一标识符,name表示镜像的名称,url表示镜像的地址。

关于镜像的一个更为常见的用法是结合私服。由于私服可以代理任何外部的公共仓库(包括中央仓库),因此,对于组织内部的Maven用户来说,使用一个私服地址就等于使用了所有需要的外部仓库,这可以将配置集中到私服,从而简化Maven本身的配置。在这种情况下,任何需要的构件都可以从私服获得,私服就是所有仓库的镜像。这时,可以配置这样的一个镜像:

<!--配置私服镜像-->
<mirrors>
    <mirror>
        <id>nexus</id>
        <name>internal nexus repository</name>
        <url>http://172.27.19.161:8081/nexus/content/groups/public/</url>
        <mirrorOf>*</mirrorOf>
    </mirror>
</mirrors>

该例中 <mirrorOf> 的值为星号,表示该配置是所有Maven仓库的镜像,任何对于远程仓库的请求都会被转至此nexus私服。如果该镜像仓库需要认证,则配置一个id为nexus的认证信息即可。

为了满足一些复杂的需求,Maven还支持更高级的镜像配置:

  • <mirrorOf>*</mirrorOf> 匹配所有远程仓库
  • <mirrorOf>external:*</mirrorOf> 匹配所有远程仓库,使用localhost的除外,使用file://协议的除外。也就是说,匹配所有不在本机上的远程仓库。
  • <mirrorOf>repo1,repo2</mirrorOf> 匹配仓库repo1和repo2,使用逗号分隔多个远程仓库。
  • <mirrorOf>*,!repo1</miiroOf> 匹配所有远程仓库,repo1除外,使用感叹号将仓库从匹配中排除。
  • <mirrorOf>central</mirrorOf> 匹配 Maven 中央仓库(Central Repository)的镜像

需要注意的是,由于镜像仓库完全屏蔽了被镜像仓库,当镜像仓库不稳定或者停止服务的时候,Maven仍将无法访问被镜像仓库,因而将无法下载构件


部署构件至远程仓库

我们使用自己的远程仓库的目的就是在远程仓库中部署我们自己项目的构件以及一些无法从外部仓库直接获取的构件。这样才能在开发时,供其他对团队成员使用。

Maven除了能对项目进行编译、测试、打包之外,还能将项目生成的构件部署到远程仓库中。首先,需要编辑项目的pom.xml文件。配置<distributionManagement>元素,例如:

<project>
    <distributionManagement>
        <repository>
            <id>pro-release</id>
            <name>Proj Release Repository</name>
            <url>http://172.27.19.161:8081/nexus/content/repositories/releases/</url>
        </repository>

        <snapshotRepository>
            <id>pro-snapshot</id>
            <name>Proj Snapshot Repository</name>
            <url>http://172.27.19.161:8081/nexus/content/repositories/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>
</project>

<distributionManagement>包含<repository><snapshotRepository>子元素,前者表示发布版本(稳定版本)构件的仓库,后者表示快照版本(开发测试版本)的仓库。这两个元素都需要配置id、name和url,id为远程仓库的唯一标识,name是为了方便人阅读,关键的url表示该仓库的地址。
往远程仓库部署构件的时候,往往需要认证,配置认证的方式同上。
配置正确后,运行命令mvn clean deploy,Maven就会将项目构建输出的构件部署到配置对应的远程仓库,如果项目当前的版本是快照版本,则部署到快照版本的仓库地址,否则就部署到发布版本的仓库地址。


maven源码

maven源码下载报错Cannot reconnect

IDEA 中外部代码点 Download Sources 下载源码时报错:

java.lang.RuntimeException: Cannot reconnect.
    at org.jetbrains.idea.maven.server.RemoteObjectWrapper.perform(RemoteObjectWrapper.java:82)
Caused by: java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
    java.net.ConnectException: Connection refused (Connection refused)
Caused by: java.net.ConnectException: Connection refused (Connection refused)
    at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)

解决:
IDEA配置: Build, Execution, Deployment | Build Tools | Maven | Importing
发现 JDK for Importer 成 Java 11 了,改为 Java 8 就好了

Intellij Idea Maven ‘cannot reconnect’ error
https://stackoverflow.com/questions/30615067/intellij-idea-maven-cannot-reconnect-error


参考


Maven Archetype

Archetype是maven的一个插件,用来生成项目框架(骨架,模版),例如maven-archetype-quickstart就是最简单的Maven项目模板,只需提供基本的元素,如groupId,artifactId,version等,它就能生成项目的基本结构及POM文件。


常用Archetype

maven-archetype-quickstart:默认的Archetype,基本内容包括:

  • 一个包含junit依赖声明的pom.xml
  • src/main/java主代码目录及一个名为App的类
  • src/test/java测试代码目录及一个名为AppTest的测试用例

maven-archetype-webapp:一个最简单的Maven war项目模板,当需要快速创建一个Web应用的时候可以使用它。生成的项目内容包括:

  • 一个packaging为war且带有junit依赖声明的pom.xml
  • src/main/webapp/目录
  • src/main/webapp/index.jsp文件
  • src/main/webapp/WEB-INF/web.xml文件

交互模式创建工程

使用archetype创建project包括3个步骤:

  • 选择archetype
    输入命令mvn archetype:generate后,Archetype插件会列出一个Archetype列表供用户选择,选择想要使用的Archetype,输入对应编号,或输入filter过滤器筛选archetype。
    命令行会提供一个默认的编号,其对应的Archetype为maven-archetype-quickstart,提示Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 15:中的15即maven-archetype-quickstart的编号。
  • 配置archetype
    选择archetype后,按照提示输入一些基本参数,包括groupId,artifactId(工程名),version,package等
  • 创建工程
    输入archetype配置信息后,Archetype插件就会在当前目录下创建工程框架,下载依赖包

使用过滤器filter筛选archetype列表

mvn archetype:generate命令列出的archetype列表太长,不容易找到想要的archetype,可以使用过滤器filter来筛选archetype,格式为:[groupId:]artifactId,如果不加冒号,只匹配artifactId。过滤器是大小写敏感的。

有两种使用filter的方式:

  • 在命令参数中指定:例如mvn archetype:generate -Dfilter=org.apache:struts
  • 在交互式提示符中指定:输入mvn archetype:generate命令列出archetype列表后,会提示Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 15:,在此提示符后输入过滤器:org.apache:struts

交互模式创建archetype工程实例

例如创建maven-archetype-quickstart工程,groupId为com.company,artifactId为project,version为1.0,package为com.company.project

$ mvn archetype:generate
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [archetype:create] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Preparing archetype:generate
[INFO] No goals needed for project - skipping
[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
[INFO] Setting property: velocimacro.messages.on => 'false'.
[INFO] Setting property: resource.loader => 'classpath'.
[INFO] Setting property: resource.manager.logwhenfound => 'false'.
[INFO] [archetype:generate]
Choose archetype:
1: internal -> org.appfuse.archetypes:appfuse-basic-jsf (AppFuse archetype for creating a web application with Hibernate, Spring and JSF)
... ...
10: internal -> org.apache.maven.archetypes:maven-archetype-j2ee-simple (A simple J2EE Java application)
... ...
15: internal -> org.apache.maven.archetypes:maven-archetype-quickstart ()
16: internal -> org.apache.maven.archetypes:maven-archetype-site-simple (A simple site generation project)
17: internal -> org.apache.maven.archetypes:maven-archetype-site (A more complex site project)
18: internal -> org.apache.maven.archetypes:maven-archetype-webapp (A simple Java web application)
19: internal -> org.apache.struts:struts2-archetype-starter (A starter Struts 2 application with Sitemesh, DWR, and Spring)
... ...
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 15:
Choose org.apache.maven.archetypes:maven-archetype-quickstart version:
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
Choose a number: 6:
Define value for groupId: : com.company
Define value for artifactId: : project
Define value for version: : 1.0
Define value for package: : com.company.project
Confirm properties configuration:
groupId: com.company
artifactId: project
version: 1.0
package: com.company.project
 Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating OldArchetype: maven-archetype-quickstart:RELEASE
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.company
[INFO] Parameter: packageName, Value: com.company.project
[INFO] Parameter: package, Value: com.company.project
[INFO] Parameter: artifactId, Value: project
[INFO] Parameter: basedir, Value: /home/local/rafale/projects/tmp
[INFO] Parameter: version, Value: 1.0
[INFO] OldArchetype created in dir: /home/local/rafale/projects/tmp/project
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 54 seconds
[INFO] Finished at: Fri Aug 26 23:01:01 GMT 2011
[INFO] Final Memory: 10M/25M
[INFO] ------------------------------------------------------------------------

创建完后项目project的目录树

$ tree project
project
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- company
    |               `-- project
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- company
                    `-- project
                        `-- AppTest.java

11 directories, 3 files

命令模式创建工程

mvn archetype:generate命令加-B参数可禁用交互模式,同时需提供如下参数:
选择archetype需要的archetypeGroupId,archetypeArtifactId,以及archetypeVersion参数
配置archetype需要的groupId,artifactId,version,package参数

例如:mvn archetype:generate -B -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.1 -DgroupId=com.company -DartifactId=project -Dversion=1.0-SNAPSHOT -Dpackage=com.company.project

$ mvn archetype:generate -B -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.1 -DgroupId=com.company -DartifactId=project -Dversion=1.0-SNAPSHOT -Dpackage=com.company.project
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] Archetype repository missing. Using the one from [org.apache.maven.archetypes:maven-archetype-quickstart:1.1] found in catalog remote
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.company
[INFO] Parameter: packageName, Value: com.company.project
[INFO] Parameter: package, Value: com.company.project
[INFO] Parameter: artifactId, Value: project
[INFO] Parameter: basedir, Value: /Users/maven/dev
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/maven/dev/project
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.184s
[INFO] Finished at: Mon Feb 04 11:53:24 CET 2013
[INFO] Final Memory: 9M/265M
[INFO] ------------------------------------------------------------------------

其中多数参数有默认值可不指定:
mvn archetype:generate -B -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=com.mycompany.app -DartifactId=my-app-simple -Dversion=1.0


参考


上一篇 XShell

下一篇 Hexo博客(10)部署并备份到Coding

阅读
评论
25.6k
阅读预计110分钟
创建日期 2016-09-15
修改日期 2024-06-11
类别
目录
  1. Maven 基础
    1. Maven 核心概念
      1. 构建生命周期、阶段和目标
        1. 生命周期(Lifecycle)
        2. 构建阶段(Phase)由插件目标(Goal)构成
      2. 依赖和仓库
      3. 插件plugins
      4. 配置文件profiles
    2. 安装配置
      1. Mac Brew 安装 maven
      2. Windows下安装及配置maven
      3. CentOS7安装maven3
        1. 安装maven yum源
        2. yum安装maven最新版
    3. Maven Wrapper(mvnw)
      1. mvnw脚本
    4. Maven命令
      1. -Pprofile 指定不同profile
      2. -pl/-am/-amd 构建指定模块
      3. mvn -U 强制更新snapshot依赖
      4. -Dmaven.test.skip=true 跳过测试
      5. -Dmaven.source.skip=true 跳过源码jar
      6. mvn -T 并发线程数
      7. mvn dependency:tree 查看依赖树
      8. mvn help:describe -Dcmd=phase 列出phase的全部goal
    5. BOM
  2. Maven POM
    1. 概述
    2. Properties属性
      1. 自定义属性
      2. POM属性
      3. settings.xml文件属性
      4. Java系统属性
      5. 环境变量属性
    3. Super POM
      1. 查看Super POM
      2. Maven-3.3.9的Super POM内容
    4. project
      1. dependencyManagement
      2. distributionManagement
    5. parent
      1. parent.relativePath
    6. repositories/repository
      1. releases
      2. snapshotRepository
      3. snapshots
    7. pluginRepositories/pluginRepository
    8. dependency
      1. scope依赖范围配置(默认compile)
        1. test和provided依赖不会传递
      2. 依赖的传递/冲突/排除
        1. 依赖传递
        2. optional=true 阻断依赖传递
        3. 依赖冲突
        4. exclusion依赖排除
        5. 循环依赖导致 Could not resolve dependencies for
      3. maven强制更新依赖(-U)
      4. 依赖包没更新导致java.lang.NoSuchMethodError
      5. The POM for xxx is invalid, transitive dependencies (if any) will not be available
    9. build
      1. extension
      2. resource
        1. resource详解
      3. plugin
      4. execution
    10. profile
      1. activation
      2. os
      3. property
      4. file
    11. scm
  3. Maven plugin
    1. maven-compiler-plugin
      1. Java 21 项目里编译兼容 Java 17 的版本
    2. maven-resources-plugin
      1. 将其他模块 src/main/resources 中资源打包到 classpath
    3. maven-help-plugin
      1. mvn help:describe 获取插件的目标goal信息
    4. maven-deploy-plugin
      1. 多模块项目deploy时忽略某个module
    5. maven-surefire-plugin
      1. surefire 跳过测试
      2. maven.test.skip和skipTests的区别
    6. maven-release-plugin
      1. mvn release:prepare
      2. mvn release:rollback
      3. mvn release:perform
      4. maven-release-plugin相关配置
    7. spring-boot-maven-plugin
    8. maven-assembly-plugin
      1. maven-assembly-plugin 从其他仓库下载镜像
    9. versions-maven-plugin
      1. 多模块maven项目如何管理版本号?
      2. Properties in parent definition are prohibited
    10. flyway-maven-plugin
    11. git-commit-id-plugin
      1. Unable to find commits until some tag
  4. maven 仓库
    1. 概述
    2. 构件存储路径解析
      1. SNAPSHOT版本
    3. Maven本地仓库及配置
      1. 用户范围settings.xml配置
      2. 全局范围settings.xml配置
    4. Maven 远程仓库
      1. 中央仓库
      2. 私服仓库
    5. Nexus 仓库
      1. 400:does not allow updating assets
      2. Blocked mirror for repositories
      3. 禁用nexus的redeploy
    6. 添加Maven远程仓库
      1. 在项目pom.xml中配置远程仓库
      2. 在settings.xml中配置远程仓库
    7. 远程仓库认证
    8. 配置远程仓库的镜像 Mirror
    9. 部署构件至远程仓库
    10. maven源码
      1. maven源码下载报错Cannot reconnect
    11. 参考
  5. Maven Archetype
    1. 常用Archetype
    2. 交互模式创建工程
      1. 使用过滤器filter筛选archetype列表
      2. 交互模式创建archetype工程实例
    3. 命令模式创建工程
    4. 参考

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论