Maven
一、初识Maven
引用来自maven官网的介绍:
Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information.
Maven 能为我们做什么?
-
我们可以使用 maven 轻松构建项目。
-
我们可以使用 maven 的帮助轻松添加项目的 jar 和其他依赖项。
-
Maven 提供项目信息(日志文档,依赖列表,单元测试报告等)
-
在更新 JAR 和其他依赖项的中央存储库时,Maven 对项目非常有帮助。
-
在 Maven 的帮助下,我们可以将任意数量的项目构建为输出类型,如 JAR,WAR 等,而无需执行任何脚本编写。
-
使用 Maven,我们可以轻松地将我们的项目与源代码控制系统(例如 Subversion 或 Git)集成。
二、安装和配置
此教程以 3.5.4版本进行,后续版本可能会有不同
安装
Windows安装
-
进入下载地址,选择
Binary zip archive
,下载即可。 -
下载完成后解压,会得到一个如下的目录:
-
在系统中配置环境变量
将
/bin
所在目录配置在系统环境变量中,我这里是D:\maven\apache-maven-3.5.4\bin
-
在命令行中验证安装是否成功
打开命令行界面,执行
imagemvn -v
或mvn -version
,出现以下界面即为安装成功,可以看到maven版本号等一系列信息。
Linux安装
- 解压
tar zxvf apache-maven-3.6.0-bin.tar.gz
或
unzip apache-maven-3.6.0-bin.zip
- 设置环境变量
-
maven
依赖于java
的环境变量,所以先确定java
的环境变量。
[root@wangkai-centos maven]# java -version
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
- 在
/etc/profile
中加入:
#maven
M2_HOME=/usr/local/maven/apache-maven-3.6.0
PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin
export PATH JAVA_HOME CLASSPATH M2_HOME
保存,退出。
- 使配置生效:
source /etc/profile
- 验证是否安装成功
验证是否成功,出现下述情况则代表成功:
[root@wangkai-centos maven]# mvn -v
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T02:41:47+08:00)
Maven home: /usr/local/maven/apache-maven-3.6.0
Java version: 1.8.0_192, vendor: Oracle Corporation, runtime: /usr/local/java/jdk1.8/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"
配置
安装成功之后,在回头来看一下maven 的目录结构:
目录-
bin
下面mvn运行的一些脚本 -
boot
下面只有一个文件plexus-classworlds-2.5.2.jar
(不同maven版本此文件版本号可能不同),这是maven的类加载器,一般不用去关心。 -
conf
此目录下有一个setting.xml
,非常重要,它可以直接定制 了maven,需要注意的是,在~/.m2/
这个目录下还有一个setting.xml
。前者是在全局范围内对maven进行配置,后者是在用户范围内。 -
lib
包含了所有maven运行需要的java类库,目录下有一个maven-model-builder-3.5.4.jar
,这是maven的超级pom,里面会有一些maven默认的配置,比如,默认的中央仓库地址。 -
LICENSE
记录了maven使用的软件许可证,Apache License Version 2.0, January 2004 -
NOTICE
记录了maven包含的第三方软件 -
README.txt
对maven做了简单的介绍,安装步骤等
下面重点看一下/setting.xml
。~/.m2
(用户目录下的/.m2)下的setting.xml
与此类似。
进入到/conf
下,有个setting.xml
的文件,便是maven 的配置文件了,我在这里删去了原来文件中的注释,并做了一些修改:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 1.本地仓库 -->
<!-- Default: ${user.home}/.m2/repository -->
<localRepository>D:\maven\local_repository</localRepository>
<!-- maven是否与用户交互 默认:true -->
<!-- interactiveMode
This will determine whether maven prompts you when it needs input. If set to false,
maven will use a sensible default value, perhaps based on some other setting, for
the parameter in question.
-->
<interactiveMode>true</interactiveMode>
<!-- 是否离线模式 -->
<!-- offline
| Determines whether maven should attempt to connect to the network when executing a build.
| This will have an effect on artifact downloads, artifact deployment, and others.
|
| Default: false -->
<offline>false</offline>
<!-- 插件组 -->
<!-- pluginGroups
| This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
| when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
| "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
|-->
<pluginGroups>
<!-- pluginGroup
| Specifies a further group identifier to use for plugin lookup.
<pluginGroup>com.your.plugins</pluginGroup>
-->
</pluginGroups>
<!-- 代理 例如:需要设置http代理才能访问网络 -->
<!-- proxies
| This is a list of proxies which can be used on this machine to connect to the network.
| Unless otherwise specified (by system property or command-line switch), the first proxy
| specification in this list marked as active will be used.
|-->
<proxies>
<!-- proxy
| Specification for one proxy, to be used in connecting to the network.
|
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
-->
</proxies>
<!-- 下载与部署仓库的认证信息 -->
<!-- servers
| This is a list of authentication profiles, keyed by the server-id used within the system.
| Authentication profiles can be used whenever maven must make a connection to a remote server.
|-->
<servers>
<!-- server
| Specifies the authentication information to use when connecting to a particular server, identified by
| a unique name within the system (referred to by the 'id' attribute below).
|
| NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
| used together.
|
<server>
<id>deploymentRepo</id>
<username>repouser</username>
<password>repopwd</password>
</server>
-->
<!-- Another sample, using keys to authenticate.
<server>
<id>siteServer</id>
<privateKey>/path/to/private/key</privateKey>
<passphrase>optional; leave empty if not used.</passphrase>
</server>
-->
</servers>
<!-- 镜像 -->
<mirrors>
<!-- 2. 镜像地址 -->
<mirror>
<id>nexus-aliyun</id>
<name>*</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<!-- 3.多环境 -->
<profiles>
</profiles>
<!-- 激活环境 -->
<!-- activeProfiles
| List of profiles that are active for all builds.
|
-->
<activeProfiles>
<activeProfile>alwaysActiveProfile</activeProfile>
<activeProfile>anotherAlwaysActiveProfile</activeProfile>
</activeProfiles>
</settings>
第1处:本地仓库。默认的本地仓库地址是${user.home}/.m2/repository
,如果需要更改,可以参考如上配置进行更改。
第2处:镜像地址。默认是没有配置的,由于maven的中央仓库在国外,访问会比较缓慢,可以参考如上配置,配置一个国内的镜像地址,此处配置的是aliyun的镜像地址。
第3处:设置多环境配置。这个在以后的文章里会详细总结
三、使用Maven构建一个简单的Java程序
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>maven.demo</groupId>
<artifactId>first-demo</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
- 第一行是
xml
头,指定了该文档的版本和编码格式 - 第二行是
project
标签,声明了一些命名空间和xsd - 接下来是
modelVersion
,当前版本这个值固定为4.0.0
-
groupId
指定了组织或公司名称 ,比如com.google
,com.alibaba
-
artifactId
指定了该项目在group
中的唯一id -
version
指定当前项目的版本号,SNAPSHOT
代表该项目还在开发中,属于不稳定的版本
这是最一个pom.xml
中最基本的元素。
编写主程序
在当前文件夹下创建 src/main/java/wk/learn/maven
目录,在此目录上创建App.java
:
package wk.learn.maven;
public class App {
public String helloWorld(){
return "hello world";
}
public static void main(String[] args) {
System.out.println(new App().helloWorld());
}
}
在命令行中:
F:\idea\learn\maven-demo>mvn clean compile
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< wk.learn:maven-demo >-------------------------
[INFO] Building maven-demo 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-demo ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-demo ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-demo ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
[INFO] Compiling 1 source file to F:\idea\learn\maven-demo\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.220 s
[INFO] Finished at: 2019-04-18T21:22:20+08:00
[INFO] ------------------------------------------------------------------------
这个项目就已经编译成功了。
编写测试
首先需要引入测试所依赖的jar,这里使用JUnit
在pom.xml
中加入:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
然后创建 src/test/java/wk/learn/maven
的目录,在此目录下创建 AppTest.java
:
package wk.learn.maven;
import org.junit.Assert;
import org.junit.Test;
public class AppTest {
@Test
public void helloTest(){
App app = new App();
Assert.assertEquals("hello world",app.helloWorld());
}
}
在命令行中执行:
F:\idea\learn\maven-demo>mvn clean test
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< wk.learn:maven-demo >-------------------------
[INFO] Building maven-demo 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-demo ---
[INFO] Deleting F:\idea\learn\maven-demo\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-demo ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-demo ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
[INFO] Compiling 1 source file to F:\idea\learn\maven-demo\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-demo ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory F:\idea\learn\maven-demo\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-demo ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
[INFO] Compiling 1 source file to F:\idea\learn\maven-demo\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-demo ---
[INFO] Surefire report directory: F:\idea\learn\maven-demo\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running wk.learn.maven.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.088 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.160 s
[INFO] Finished at: 2019-04-18T21:36:41+08:00
[INFO] ------------------------------------------------------------------------
可以看到,已经编译成功并且通过了Test
打包
执行打包命令:
F:\idea\learn\maven-demo>mvn clean test
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< wk.learn:maven-demo >-------------------------
[INFO] Building maven-demo 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-demo ---
[INFO] Deleting F:\idea\learn\maven-demo\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-demo ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-demo ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
[INFO] Compiling 1 source file to F:\idea\learn\maven-demo\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-demo ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory F:\idea\learn\maven-demo\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-demo ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
[INFO] Compiling 1 source file to F:\idea\learn\maven-demo\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-demo ---
[INFO] Surefire report directory: F:\idea\learn\maven-demo\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running wk.learn.maven.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.088 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.160 s
[INFO] Finished at: 2019-04-18T21:36:41+08:00
[INFO] ------------------------------------------------------------------------
F:\idea\learn\maven-demo>mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< wk.learn:maven-demo >-------------------------
[INFO] Building maven-demo 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-demo ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-demo ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-demo ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory F:\idea\learn\maven-demo\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-demo ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-demo ---
[INFO] Surefire report directory: F:\idea\learn\maven-demo\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running wk.learn.maven.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.105 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-demo ---
[INFO] Building jar: F:\idea\learn\maven-demo\target\maven-demo-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.510 s
[INFO] Finished at: 2019-04-18T21:41:13+08:00
[INFO] ------------------------------------------------------------------------
通常还需要将项目安装到本地仓库中,这样别的项目就可以使用这个jar了,安装的命令是: mvn install
现在我们的项目已经成功编译,测试,打包 和安装,主要使用了:
- mvn clean compile
- mvn clean test
- mvn clean package
- mvn clean install
四、在IDEA中使用Maven
通常我们编写代码都会使用到IDE,各个IDE也都很好的集成了maven,这里介绍一下maven在IDEA中的使用和配置。
IDEA中已经默认集成了maven,但我们总想做一些定制:
File->Settings
或者使用快捷键 Ctrl+Alt+s
打开设置,找到 Build,Execution ... -> Build Tools -> Maven
第一处:可以自己指定maven的目录,自己下载的任意版本的maven
第二处:可以自己指定 setting.xml
的位置
第三处:可以自己指定本地仓库的位置
在编辑器的右侧可以打开maven 的插件,如下图,这个插件提供了maven 的生命周期,插件等的使用,非常方便。
image五、坐标和依赖
maven 坐标为各种构件引入了秩序,任何一个构件都必须明确自己的坐标,而一组Maven坐标是通过一些元素定义的,它们是 groupId,artifactId,version,packageing,classifier等
说白了,就是每个jar包在maven的仓库中的坐标都是唯一的,我们需要引入不同的jar包,直接填写其对应的坐标即可。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.1</version>
</dependency>
如上, 分别指定了三个元素, groupId
指的是这个Jar包的公司或组织Id, artifactId
指的是项目名,version
指的就是jar包的版本号了。
Scope
指的是这个Jar包的依赖范围:
- Compile: 编译。如果没有指定,就会默认使用这个。对于 编译,测试,运行三种 classpath 都有效
-
Test: 测试。只对于测试 classpath 有效,在编译主代码和运行项目的时候都无效。比如
Junit
-
Provided: 已经提供。对于 编译和测试的时候有效,但在运行时无效。比如
servelet-api
-
System :系统依赖。与
provided
类似,使用system
时,必须通过systemPath
指定依赖文件的路径 -
Runtime:运行时。 对于测试和运行classpath有效,但在编译主代码时无效。比如
jdbc的驱动实现
-
Import:导入依赖。该依赖范围不会对 3种 classpath 产生实际影响,可以通过与
dependencyManagement
标签的结合来实现依赖版本管理。比如使用spring-boot 或 spring-cloud
的时候往往会引入一个bom
,来管理项目种依赖的各种jar包的版本号。
Scope 依赖范围 | compile classpath | test classpath | runtime classpath | example |
---|---|---|---|---|
complie | Y | Y | Y | spring-core |
test | N | Y | N | Junit |
provided | Y | Y | N | servlet-api |
runtime | N | Y | Y | jdbc驱动实现 |
system | Y | Y | N | 本地的,maven仓库之外的类库文件 |
六、仓库
Repository
是Maven中的一个重要的概念,主要分为 本地仓库
,远程仓库
。
本地仓库
可以通过 seeting.xml
中的 <localRepository>
这个标签项来设置具体路径,比如 <localRepository>D:\maven\local_repository</localRepository>
远程仓库
默认情况下是 maven 的中央仓库,一般企业中会搭建私服来开发,这里只需理解一下远程仓库的概念。
Maven查找依赖的流程是会先去本地仓库中查找,如果没有找到,就会向上去远程仓库拉取,然后将依赖缓存在本地;如果在本地找到了 。就不会再去远程仓库拉取了。
设置阿里云镜像
默认的远程仓库为 maven的中央仓库
,由于中央仓库的服务器在国外,我们平时下载jar包速度会很慢,可以通过 setting.xml
中的 <mirro>
标签来设置镜像提供加速服务。
在 setting.xml
中找到 <mirrors>
标签,这个标签代表的是镜像的集合,在这个标签中添加
<mirror>
<id>nexus-aliyun</id>
<name>*</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
网友评论