Maven 这个词能够翻译为专家的意思。它是由 Apache 组织的开源,主要服务 Java 平台项目的构建、依赖管理和项目信息管理。php
有了 Maven 咱们只需编写一些配置而后运行一条命令就能够自动完成项目编译、测试、打包、发布等流程。前端
Maven 须要依赖 Java 环境,因此首先要确认安装了 Java,首先去官网下载 Maven,而后就能够把它随便解压到一个文件夹,并把这个文件夹路径设置为 M2_HOME
环境变量,最后将 %M2_HOME%\bin
(Windows)加入到 PATH
,Linux 为 export PATH=$PATH:$M2_HOME/bin
。java
mvn -v # 在命令行运行这条命令,查看 Maven 版本
复制代码
对于升级就是重复上面的流程。node
Maven 安装目录下的 conf
文件下存放着 Maven 的配置 settings.xml
,它的做用域是全局的,咱们能够复制它到 ~/.m2
下,用户目录下的 settings.xml
修改只对当前的用户有做用。Maven 的依赖包仓库放在,~/.m2
文件夹下的 repository
文件夹中。git
由于 Maven 实际上执行的是 Java 命令,咱们能够经过 MAVEN_OPT
环境变量设置它的参数。一般须要设置它的值为 -Xms128m -Xmx512m
由于对于大点的项目可能出现内存不够的错误。github
对于编辑器中的 Maven 咱们能够设置它使用咱们下载的 Maven,这样就能够避免两个 Maven 版本不一致而形成的构建行为不一致。web
对于 Maven 项目,最核心的就是 pom.xml
(Project Object Model) 咱们须要把项目的构建配置信息都写在里面。spring
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello world project</name>
<description>Demo project</description>
</project>
复制代码
第一行是 XML 头,指定了 XML 版本和文件编码。sql
而后就是 project
元素,它是配置文件的根元素,它还声明了 POM 的命名空间。docker
而后就是 modelVersion
对于 Maven2 和 Maven3 它只能是 4.0.0
版本。
groupId
, artifactId
和 version
定义了一个项目的基本坐标。
groupId
定义了项目属于哪一个组,它一般和 Java 中包名命名同样,例如 a
公司启动了一个 myapp
项目,那么他的 groupId
就多是 com.a.myapp
。
artifactId
定义了当前 Maven 项目在组中惟一的 ID,由于一个项目可能有多个子项目或模块。
version
指定了当前项目的版本。SNAPSHOT
为快照版本。
name
给项目更友好的名称,description
是对项目的描述。
上面这些字段定义了项目基本的信息,下面咱们就能够编写项目代码了。
package com.demo.helloworld;
public class HelloWorld {
public String sayHello() {
return "hello world";
}
public static void main(String[] args) {
System.out.println(sayHello());
}
}
复制代码
Maven 采用约定大于配置的方式,在大多数的状况下项目源码应该放在项目文件夹下的 src/main/java
下(Maven 会自动在该目录下搜寻源码),资源放在 src/main/resources
下,测试代码放在 src/test/java
下。
咱们的包名也应该和 groupId
和 artifactId
相吻合。
而后执行
mvn clean compile
复制代码
clean
是让 Maven 清除项目输出 target
目录。compile
任务用来将项目编译到 target/classes
目录下。
而后咱们用 JUnit 编写单元测试,首先须要在 pom.xml
加上 junit 的依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello world project</name>
<description>Demo project</description>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
复制代码
引入一个依赖咱们须要填写它的基本坐标,有了这个坐标,Maven 就会自动取中央仓库下载,这个依赖到 ~/.m2/repository
文件夹下。
scope test
是表示依赖只对测试有效,在主代码中引入 junit 会报错。
package com.demo.helloworld;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class HelloWorldTest {
@Test
public void test() {
HelloWorld helloWorld = new HelloWorld();
assertEquals("hello world", helloWorld.sayHello());
}
}
复制代码
而后咱们须要对 Maven 的编译插件进行一些配置,由于它默认只支持 Java 1.5 因此咱们须要配置它为更高版本的 Java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello world project</name>
<description>Demo project</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 配置源码编码 -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- 配置 Java 版本 -->
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
复制代码
而后执行
mvn clean test
复制代码
它会编译测试文件而后运行测试,最后咱们就可以看到测试经过的输出。
下一步就是对项目打包,由于咱们没有指定项目打包的类型,因此默认就是 jar
。
mvn clean package
复制代码
进行打包以前 Maven 会自动帮咱们编译,测试,经过了就打成 jar
包,放在 target
目录下,名称为 hello-world-0.0.1-SNAPSHOT.jar
它是根据 artifactId
和 version
还有打包类型进行命名。
test
会自动帮咱们执行 compile
, package
会自动帮咱们执行 test
,install
会自动帮咱们执行 package
, install
是将项目安装到仓库中。
咱们还可使用 archetype
插件来生成项目骨架,执行 mvn archetype:generate
命令就能够了,固然也可使用编辑器新建一个 Maven 项目来选择项目模板。
Maven 是经过坐标找到一个依赖的,而一组坐标是经过一些元素定义的。
groupId
一个组织的的一个实际项目artifactId
实际项目中的一个 Maven 项目或模块version
版本packaging
打包方式有 jar
,war
等classifier
用来定义构建输出的附属构建 如 hello-world-1.0.0-javadoc.jar
,它里面包含了 Java 文档,javadoc
就是就是附属构建的 classifier
。前三个必须定义,packaging
默认 jar
,classifier
不能直接定义。
一个项目依赖须要放在 dependencies
中,dependency
有几个子元素。
groupId
, artifactId
和 version
是项目基本坐标。type
依赖类型,默认是 jar
scope
依赖范围optional
是否可选exclusions
用来排除传递依赖其中依赖范围有几个值能够选。依赖范围主要是控制编译
, 测试
和 运行
的 classpath
compile
默认,在编译,测试和运行都有效test
只对测试 classpath 有效,如 junit 它只要在测试的时候能用到就行。provided
对编译和测试有效,好比 servlet-api
,由于运行时容器都会提供,因此无需重复引入。runtime
运行时依赖,对测试和运行时有效,在编译时无效,好比 jdbc 驱动实现,只有在须要运行的时候在须要特定的驱动实现。system
系统依赖范围,它与 provided
依赖范围彻底一致,只是它的依赖必须使用 systemPath
显式的指定依赖路径,它不是经过 Maven 仓库解析。<dependencies>
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
</dependencies>
复制代码
还有一种 import
为导入依赖范围,不会对上面三个依赖范围产生影响。
传递依赖就是好比咱们依赖 spring-core
(compile) 可是 spring-core
依赖 commons-logging
(compile),那么咱们的项目也依赖 commons-logging
(compile)。有了这个机制,咱们就不用考虑 spring
依赖什么,没必要手动安装它的依赖,Maven 会自动将必要的间接依赖引入当前项目。spring boot 的起步依赖就是利用 Maven 的传递依赖。
依赖范围也会对传递依赖产生影响。
左侧表示直接依赖,上面是表明间接依赖,中间就表示传递依赖范围。
好比咱们项目传递依赖中有两个依赖是同样的可是它的版本不同,那么 Maven 就会看谁的路径最短,最短的优先。
若是它们是同样长的,Maven 就查看 POM 中的依赖声明谁在前面谁就优先。
若是咱们项目依赖 A
(compile),A
依赖 B
(compile) 和 C
(compile),可是 B
和 C
定义为可选的,那么依赖就不会被传递。依赖可选能够经过 <optional>true</optional>
指定。
若是咱们想排除一个传递依赖,好比 spring boot 默认是使用的 jackson,若是咱们想用 gson,那么咱们就能够将 jackason 排除,而后显式的引入 gson。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
</dependencies>
复制代码
若是咱们依赖一个项目的不少模块,由于是一个项目因此版本号都是同样的,这样咱们就要给每一个依赖填写同样的版本号,升级的话又要一个一个的改。
这时候咱们就能够声明一个变量,而后其余地方直接使用就好了。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello world project</name>
<description>Demo project</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>2.5.6</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- · · · -->
</dependencies>
</project>
复制代码
${}
能够引入 Maven 的属性。
Maven 中任何一个项目或插件的输出都称为构件。任何构件都会有一个惟一的坐标。为了重用 Maven 的依赖都统一放在仓库中,而不是每一个项目都有个 lib
同样的文件夹来装它的依赖。
Maven 的仓库分为远程仓库和本地仓库,Maven 会首先经过坐标去本地仓库寻找依赖,若是没有就去远程仓库下载依赖,而后在放入本地仓库再使用。若是都没有的话那么就会报错。
咱们能够自定义远程仓库,Maven 自带了一个远程仓库,它包含绝大部分的构件,默认状况都会去这个中央仓库下载构件。
私服是另外一种远程仓库,为了节约宽带和时间,在局域网中搭建一个私有仓库,用其代理外部远程仓库,内部项目还能够安装到私服上供其余项目使用。
除了上面两种还有其余的公开远程仓库。好比 jboss repository 等。
本地仓库默认位置是当前用户目录下的 .m2/repository
文件夹,若是咱们想更改它的位置能够修改 .m2/settings.xml
文件。
<settings>
<localRepository>D:\maven\repository</localRepository>
</settings>
复制代码
若是咱们本地有两个项目 A
和 B
,项目 B
依赖于 A
,那么咱们能够将项目 A
安装到本地仓库,这样咱们就能够在 B
项目中依赖 A
了,咱们能够在 A
项目中执行 mvn clean install
来将 A
项目安装到本地仓库。
Maven 须要知道最少一个远程仓库,这样 Maven 才能下载构件到本地。中央仓库就是默认的远程仓库,全部 Maven 项目 pom.xml
会继承一个超级POM,它就在 Maven 安装目录下的 lib/maven-model-builder-3.6.1.jar\org\apache\maven\model\
文件夹,名为 pom-4.0.0.xml
。
<?xml version="1.0" encoding="UTF-8"?>
<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>
<!-- · · · -->
</project>
复制代码
私服是特殊远程仓库,它代理多个外部远程仓库,咱们使用私服来下载构件,私服上若是没有就会取远程下载,而后缓存起来。
若是咱们须要的构件不在中央仓库而在另一个仓库,咱们就能够在 pom.xml
中配置该仓库。
<repositories>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.org/maven2/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
复制代码
其中 id
必须时惟一的,若是有仓库声明和中央仓库同样的 id 就会覆盖它,url
就是仓库地址,releases
和 snapshots
分别用来控制发布版和快照版构件的下载,enabled
为 true
表示开启下载,false
表示关闭下载。
快照版本是表示开发中的版本,开发中项目会平凡的变化,好比咱们开发一个项目中一个模块,可是它要依赖另外一个模块,咱们就将它安装到本地依赖,这样就能够在咱们项目中使用,可是若是依赖项目变了,可是咱们仍是会使用缓存本地的模块,这时候就要使用 snapshot
版本了,对于快照版本 Maven 每次会去检查当前是否是最新的,若是不是就下载最新的代码。
snapshots
能够设置 Maven 检查更新频率。
<snapshots>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</snapshots>
复制代码
never
从不,always
每次构件都去检查,daily
天天(默认值)。
checksumPolicy
是 Maven 下载构件时会校验构件,默认时 warn
警告,还有 fail
项目构建会失败,ignore
忽略。
对于组织内部的仓库每每须要认证才运行访问,咱们能够在 settings.xml
中设置仓库的帐号和密码。
<servers>
<id>repo</id>
<username>username</username>
<password>password</password>
</servers>
复制代码
其中 id
和咱们定义远程仓库 id
对应。
私服的一个做用就是用来部署第三方构件,Maven 能够帮助咱们将构件部署到仓库中。
<project>
<distributionManagement>
<repository>
<id>id</id>
<name>Release Repository</name>
<url>http://196.0.0.1/path/to/release</url>
</repository>
<snapshotRepository>
<id>snapshot</id>
<name>Snapshot Repository</name>
<url>http://196.0.0.2/path/to/release</url>
</snapshotRepository>
</distributionManagement>
</project>
复制代码
repository
表示发布版的仓库,snapshotRepository
表示快照仓库,id 是惟一标识,咱们能够经过它来设置帐号和密码。
而后咱们能够执行以下命令发布
mvn clean deploy
复制代码
当依赖返回是 system
时 Maven 回去本地寻找。
当是显式版构件时 如 1.2
, 1.3-beta-1
等,Maven 会去全部远程仓库下载到本地。
当依赖版本是 RELEASE
LATEST
和 SNAPSHOT
时会根据更新策略去全部远程仓库搜寻构件元数据,而后和本地的元数据合并,再经过合并后的值取寻找版本。
咱们还能够在 settings.xml
中设置镜像镜像服务器。
<mirrors>
<mirror>
<id>maven.net.cn</id>
<name> maven central mirror</name>
<url>http://maven.net.cn/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
复制代码
咱们上面给中央仓库设置一个镜像,咱们也能够设置 mirrorOf
为 *
表示匹配全部远程仓库。
Maven 有 3 套生命周期,分别是 clean
、default
和 site
,Maven 的生命周期是抽象的存在,就像一个接口,它把实际工做交给个插件。这 3 套生命周期是相互独立的。
每一个生命周期都有一些阶段(phase),如 clean
生命周期有 3 个阶段,pre-clean
, clean
和 post-clean
,阶段是有顺序的,当执行 clean
阶段,会执行它前面的 pre-clean
。
clean
生命周期的阶段一共有
pre-clean
执行清理前须要执行的工做clean
清理上次构件post-clean
清理事后须要执行的操做default
生命周期是最核心的部分,它一共有以下阶段
validate
initialize
generate-sources
process-sources
处理主资源文件,通常是 src/main/resources
目录下的文件。generate-resources
process-resources
compile
编译项目源码。process-classes
generate-test-sources
process-test-sources
处理项目测试资源文件。generate-test-resources
process-test-resources
test-compile
编译测试源码process-test-classes
test
使用单元测试框架运行测试。prepare-package
package
接受编译好的代码,打包成可发布格式。pre-integration-test
integration-test
post-integration-test
verify
install
将包安装到 Maven 本地仓库,供本地其余项目使用deploy
将包复制到远程仓库。site
生命周期目的是创建和发布项目站点。
pre-site
生成站点以前要执行的操做site
生成项目站点文档post-site
执行生成站点以后要完成的工做site-deploy
将站点发布到服务器执行 Maven 任务主要方式就是调用 Maven 的生命周期阶段。
mvn clean
就是执行 clean
生命周期的 clean
阶段
mvn test
就是执行 default
生命周期的 test
阶段
mvn clean install
就是执行 clean
生命周期 clean
阶段和 default
的 install
阶段。
Maven 只是定义了生命周期,然而实际的工做仍是要交给插件。一个插件会有一个或多个目标(goal)每一个目标对应一个功能,如 surefire:test
surefire
是插件名,test
是插件目标,surefire
是 Maven 默认测试插件。
Maven 的生命周期的阶段和插件的目标相互绑定,来完成实际任务。
Maven 默认为主要的生命周期阶段绑定了不少插件目标,当调用生命周期阶段时,相应的插件就会被执行。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
复制代码
上面咱们将 maven-source-plugin
的 jar-no-fork
目标绑定到了 verify
阶段。id 为任务名。
插件也有参数,咱们能够经过命令行或在 pom.xml
设置它的参数。
咱们能够经过 -D参数键=参数值
来设置插件目标参数,如 mvn package -Dmaven.test.skip=true
-D
是 Java 自带的,用来设置 Java 系统属性,Maven 只是重用了该参数。
在 pom.xml
中咱们能够经过 configuration
设置参数。
<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>
复制代码
除了在外层设置插件参数(全局),咱们还能够对一个 execution
设置参数。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>ant-validate</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>lalala</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
复制代码
咱们还能够经过命令行调用插件目标。
mvn [options] [goal<s>] [phase[s]]
复制代码
由于有些插件目标不适合绑定到生命周期阶段执行,因此咱们能够直接在命令行执行插件的目标。
mvn dependency:tree # 查看项目依赖
# 固然咱们将插件的 groupId artifactId version 都写上
复制代码
咱们知道插件有它的基本坐标,Maven 是如何经过 dependency
查到对应的插件呢?
由于 dependency
是 maven-dependency-plugin
插件的前缀,Maven 能够经过前缀查找到对应的 artifactId
。Maven 会经过本地仓库查找插件,若是查不到就会取远程仓库查找。
对于未指定 groupId
的插件,Maven 会默认使用 org.apache.maven.plugins
做为它的 groupId
。Maven 在超级POM 中设定了核心插件的版本,咱们项目中就能够继承到这些版本的设定,而无需本身设置。
若是一个插件既不是核心插件又没有设定版本,那么会检查全部仓库可用版本,而后作出选择。
Maven 还支持多模块开发,咱们一个项目可能有不少的模块,Maven 能够将它们聚合在一块儿。
假如咱们有一个项目 app,它分为 a、b 和 c 三个模块,也就是三个 Maven 项目,由于它们是一个项目因此它们的 groupId
,version
都是同样的。
咱们项目目录可能像下面这样。
|-app
|- a
|- src
|- pom.xml
|- b
|- src
|- pom.xml
|- c
|- src
|- pom.xml
pom.xml
复制代码
咱们最外层有一个 pom.xml
,咱们用它来聚合项目中的模块。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo.app</groupId>
<artifactId>app-aggregator</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>a</module>
<module>b</module>
<module>c</module>
</modules>
</project>
复制代码
须要将 packaging
设置为 pom
,而后设定它要聚合的模块。
module
中是模块的相对路径,若是和其余模块是平行目录则路径就是 ../a
等。
如今咱们就不用一个一个取构件了,咱们在最外层执行 mvn clean install
。Maven 会解析 pom.xml
并计算出模块的构建次序,而后顺序执行。
咱们发现咱们的子模块有不少相同的配置,这时候咱们就可使用继承来消除重复。
咱们能够再建立一个用来作 parent
的 pom.xml
也能够重用咱们上面建立的 aggregator
pom.xml
,若是重用的话咱们就无需修改它,可是须要修改要继承它的模块。
<!-- a 模块 -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<artifactId>app-a</artifactId>
<parent>
<groupId>com.demo.app</groupId>
<artifactId>app-aggregator</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
</project>
复制代码
咱们使用 parent
来指明模块要继承的父级。这里的 relativePath
的默认值就是 ../pom.xml
咱们也能够省略它。
如今咱们继承了父级的 groupId
和 version
,若是咱们须要不一样的值,也能够覆盖它。几乎全部的项目均可以继承父级的。
若是咱们父级声明了一个依赖,那么全部子模块都会继承这个依赖,即便有的模块不须要这个依赖。
Maven 提供了 dependencyManagement
来让子模块不会引入实际依赖,只有子模块声明才会依赖。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<version>2.1.7.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
复制代码
<!-- a 模块 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
</dependencies>
复制代码
有了 dependencyManagement
,咱们子模块不会直接继承,可是若是声明了须要继承就无需填写依赖的版本了。
spring boot 就是利用 Maven 的继承,我许让咱们本身填写依赖的版本。
还有一个 pluginManagement
(在 build
元素下) 它的做用和 dependencyManagement
是同样的,只是它是做用于插件。
Maven 的测试是使用 maven-surefire-plugin
插件。
有时候咱们想跳过测试能够在命令行加入 -DskipTests
,-Dmaven.test.skip=true
不只跳过测试,也会跳过测试代码的编译。
咱们还能够运行指定测试,如 -Dtest=*Tests
表示只运行 Tests
结尾的测试,*
匹配 0 或多个字符。还可使用 ,
分割多个参数,如 -Dtest=*Tests,*IT
。
Maven pom.xml
中可使用 ${}
来注入属性,它一共支持 6 类属性。
${version}
项目版本 和 ${basedir}
项目根目录pom.xml
中的属性,如 ${project.version}
, ${project.build.sourceDirectory}
等properties
中自定义的属性settings.xml
中的属性,如 ${settings.loaclRepository}
。${user.name}
${JAVA_HOME}
咱们项目中开发环境和线上环境不一样每每须要不一样的配置。Maven 中的 Profile
就能够针对环境的不一样使用不一样的配置。
db.url=${db.url}
db.password=${db.password}
复制代码
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault> <!-- 配置默认激活 -->
</activation>
<properties>
<db.url>dev.url</db.url>
<db.password>dev.password</db.password>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<db.url>prod.url</db.url>
<db.password>prod.password</db.password>
</properties>
</profile>
</profiles>
<!-- 须要资源开启过滤,这样上面 properties 文件的 ${} 就能够注入咱们的 properties 中属性了 -->
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
</build>
复制代码
而后咱们就能够在命令行中使用 -Pdev
来激活开发模式的配置,profile
中的配置是当激活当前 profile
才会生效的配置。
有时候咱们须要将前端和后端放在一块儿,咱们就可使用 frontend-maven-plugin , 来帮助咱们安装 node npm 或 yarn 来执行 npm script。
咱们只须要在前端模块中添加这个插件
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<configuration>
<installDirectory>target</installDirectory> <!-- node 安装目录 -->
<nodeVersion>v13.6.0</nodeVersion>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm lint</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>run lint</arguments>
</configuration>
</execution>
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
<execution>
<id>npm run test</id>
<goals>
<goal>npm</goal>
</goals>
<phase>test</phase>
<configuration>
<arguments>run test</arguments>
</configuration>
</execution>
</executions>
</plugin>
复制代码
它会本身安装全新的 node
和 npm
,与全局的 node
隔离。而后咱们使用它的 npm
goal 来执行 npm 命令。 咱们也可使用 clean 插件来清理每次生成的代码。
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven-clean-plugin.version}</version>
<executions>
<execution>
<id>remove existing output</id>
<phase>compile</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>build</directory>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
复制代码
dockerfile-maven-plugin
插件能够帮助咱们构建和发布 docker 镜像,而无需再手动输入命令。
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile-maven-version}</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
</goals>
<configuration>
<contextDirectory>context</contextDirectory> <!-- 上下文目录 默认是当前目录 -->
<dockerfile>not-context/Dockerfile</dockerfile> <!-- Dockerfile 地址,默认是当前目录下的 Dockerfile -->
<buildArgs> <!-- docker build 命令参数 -->
<IMAGE_VERSION>0.0.1</IMAGE_VERSION>
</buildArgs>
</configuration>
</execution>
<execution>
<id>tag</id>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<repository>test/build-tag-version</repository> <!-- image 名称 -->
<tag>${project.version}</tag> <!-- tag 版本 -->
<skip>true</skip> <!-- 若是想跳过能够设置skip 为 true -->
</configuration>
</execution>
</executions>
</plugin>
复制代码
咱们须要一个 Dockerfile 来构建咱们的 image,若是是 spring boot 项目能够简单使用 fat jar 方法来构建。
FROM openjdk:8-jdk-alpine
VOLUME /tmp COPY target/*.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"] 复制代码
更多关于 spring boot docker 能够查看 Spring Boot Docker。