# Maven
Maven是一个口语化的词,代表专家内行。Apache Maven项目是一个项目管理工具,主要服务于Java平台的项目构建,依赖管理和项目信息管理,它包含了:
- 项目对象模型(POM:Project Object Model)
- 项目生命周期(Project Lifecycle)
- 依赖管理系统(Dependency Management System)
- 中间件仓库,根据坐标即可找到
我们一直在不停地寻找避免重复的方法,设计的重复,编码的重复,文档的重复,构建的重复。Maven最大化地消除了构建的重复,抽象了构建生命周期,为绝大部分的构建任务提供了已实现的插件,将项目过程规范化,自动化,高效化,并具有扩展性。
使用Maven不用再在本地拷贝jar包,在Maven管理配置中配置好所需构件的坐标,Maven会去本地仓库查找,如果没有会去中央仓库下载。
# Maven安装
- 从官方下载安装包,解压到本地,将该路径加入到Path中。一般设置Maven的环境变量为maven_home。
- 配置本地仓库位置,在conf/settings.xml中配置<localRepository>/path/to/local/repo</localRepository>
# 安装目录
Maven安装目录结构如下:
- bin:mvn运行脚本,其中m2.conf是classworlds配置文件。
- boot:该目录只包含一个文件,它是一个类加载器框架,相对于默认的Java类加载器,它的语法更丰富,Maven使用该加载器来加载自己类库。
- conf:settings.xml文件能全局定制Maven行为。
- lib:包含Maven运行时需要的Java类库。
# 项目目录
Maven管理的项目目录结构如下:
目录 | 说明 |
---|---|
src/main/java | 核心代码部分 |
src/main/resources | 资源文件部分 |
src/main/webapp | 页面资源,js,css,图片 |
src/test/java | 测试代码部分 |
src/test/resources | 测试配置文件部分 |
pom.xml | pom文件 |
# 系统安装
- 设置环境变量M2_HOME到Maven目录结构。
- 然后在path中添加%M2_HOME%\bin。
# IntelliJ集成
- 在configure->settings->Build,Execution,Deployment->BuildTools->Maven处设置。
- 如果希望使用离线本地仓库,在不联网的时候也能使用,可在Runner中的VM Options输入:-DarchetypeCatalog=internal。
- 使用骨架创建工程:
- Java项目:maven-archetype-quikstart。
- web项目:maven-archetype-webapp。
- 添加资源目录:在Project Structure->Modules->Web Resource Directories。
# Eclipse集成
问题1:在Eclipse中更改Maven
- 在Windows->Preferences->Maven->Installations中添加新的maven工具并更改。
问题2:Eclipse中的maven,无法自动下载相应的jar包
- 在Windows->Preferences->Maven处取消勾选Do not automatically update dependencies from remote repositories.
- 如果上面操作后还不下载,需要清除下本地缓存,在Run->run configurations –>Maven Build –>选择报错的项目,在Goals处填写clean install -U,然后右键->Maven->Update Project即可。
# Maven启动tomcat
maven可以使用tomcat的插件然后将项目运行在服务器中,在pom.xml中设置:
<build>
<!--maven插件-->
<plugins>
<!--jdk编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<!-- tomcat7的插件, 不同tomcat版本这个也不一样 -->
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- 通过maven tomcat7:run运行项目时,访问项目的端口号 -->
<port>80</port>
<!-- 项目访问路径 本例:localhost:9090, 如果配置的aa, 则访问路径为localhost:9090/aa-->
<path>/travel</path>
</configuration>
</plugin>
</plugins>
</build>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
使用maven命令运行:
mvn tomcat7:run
# 设置代理
在Maven安装目录下conf->setting.xml文件中设置:
<proxies>
<!-- proxy
| Specification for one proxy, to be used in connecting to the network.
|-->
<proxy>
<id>quickq</id>
<active>true</active>
<protocol>http</protocol>
<!-- <username>proxyuser</username>
<password>proxypass</password> -->
<host>127.0.0.1</host>
<port>11000</port>
<nonProxyHosts>localhost</nonProxyHosts>
</proxy>
</proxies>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Maven设置镜像源
Maven也可以设置其他镜像源,比如阿里云Maven (opens new window)。在conf->setting.xml文件中设置:
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
2
3
4
5
6
如果查找Maven包的坐标可以去阿里云云效Maven (opens new window)
# 基本操作
Maven中的基本操作对应相应的生命周期阶段,一个规范化的构建流程有:
- 清理
- 编译
- 测试
- 报告
- 打包
- 部署
它们基本上分为:
- clean生命周期:在进行真正的构建之前进行一些清理工作
- pre-clean:执行一些需要在clean之前完成的工作
- clean:移除所有上一次构建生成的文件
- post-clean:执行一些需要在clean之后立刻完成的工作
- default生命周期:构建的核心部分,编译、测试、打包、安装、部署等等
- validate:验证工程是否正确,所有需要的资源是否可用。
- compile:编译项目的源代码。
- test:使用合适的单元测试框架来测试已编译的源代码。这些测试不需要已打包和布署。
- package:把已编译的代码打包成可发布的格式,比如jar。
- integration-test:如有需要,将包处理和发布到一个能够进行集成测试的环境。
- verify:运行所有检查,验证包是否有效且达到质量标准。
- install:把包安装到maven本地仓库,可以被其他工程作为依赖来使用。
- deploy:在集成或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。
- site生命周期:生成项目报告,站点,发布站点
- pre-site:生成项目站点之前需要完成的工作
- site:生成项目站点文档
- post-site:生成项目站点之后需要完成的工作
- site-deploy:将项目站点发布到服务器
常用的命令如下:
阶段 | 命令 | 描述 |
---|---|---|
clean | mvn clean | 清除target目录 |
compile | mvn compile | 编译 |
test | mvn test | 编译src和test下代码 |
package | mvn package | 打包的格式可在pom.xml中packaging设置 |
install | mvn install | 打包,并安装到本地仓库 |
deploy | mvn deploy | 打包,并把包拷贝到远程仓库 |
# 仓库分类
Maven的仓库只分为两类:本地仓库和远程仓库。Maven根据坐标寻找构件的时候首先会查看本地仓库,如果没有会去远程仓库查找。有一种特殊远程仓库是中央仓库,Maven自带的仓库,当本地仓库没有时就会默认查找这个仓库,此外还可以自己搭建私服,来代理外部的远程仓库。
# 概念模型
Maven的概念模型如下:
Maven主要的功能是:
- 构件依赖管理
- 构件生命周期管理
- 项目构建管理
# POM文件
POM是Project Object Model(项目对象模型)的缩写,该文件中包含了依赖关系、构建目录、源目录、测试源目录、插件、目标等项目信息和配置信息。Maven读取该文件,然后执行构建目标。
# 基本元素
元素 | 含义 |
---|---|
project | pom文件根元素,表示一个项目 |
modelVersion | project元素的子元素,指定modelVersion版本号,应该设置为4.0.0 |
groupId | project元素的子元素,指定项目所属的group |
artifactId | project元素的子元素,项目交付件ID,项目交付件是指项目的最终交付文件,如jar、zip、war等 |
version | project元素的子元素,项目(交付件)的版本号 |
其中groupId,artifactId,version构成了一个构件的坐标,来唯一标识一个构件。
# 常用元素
元素 | 含义 |
---|---|
packaging | 定义打包类型,如jar, war |
name | 指定项目名称 |
url | 指定项目url |
dependencies | 表示项目依赖项列表 |
dependency | 表示单个依赖项,这个元素是依赖项列表元素的子元素 |
scope | 单个依赖项的作用域,作用域可以是compile、test、runtime、provided、system之一,作用域的意图是限定该依赖项作用范围,如test,则表明依赖项只在test时起作用 |
# 依赖管理
Maven 一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。Maven 通过读取项目文件(pom.xml),找出它们项目之间的依赖关系。我们需要做的只是在每个项目的 pom 中定义好直接的依赖关系。
# 依赖范围
添加坐标时需要指定依赖范围,它包括:
- compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-core,在编译、测试和运行的时候都需要使用该依赖。
- test:测试依赖范围。使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子是JUnit,它只有在编译测试代码及运行测试的时候才需要。
- provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试class-path有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于Tomcat等容器已经提供,就不需要Maven重复地引入一遍。
- runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行class-path有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
- system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建。
依赖范围由弱到强是:test->runtime->provided->compile。
总结就是:
依赖范围 | 对于编译classpath有效 | 对于测试classpath有效 | 对于运行时classpath有效 | 例子 |
---|---|---|---|---|
compile | Y | Y | Y | spring-core |
test | N | Y | N | Junit |
provided | Y | Y | N | servlet-api,jsp-api |
runtime | N | Y | Y | JDBC驱动 |
system | Y | Y | N | 本地的,Maven仓库之外的类库 |
# 示例
下面是一个在Intellij中的pom.xml,为了避免和Intellij中tomcat的类库冲突,scope设置为provided。
<?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.test</groupId>
<artifactId>maven_web</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!--放置的都是项目运行所依赖的jar包-->
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8888</port>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>1.8</target>
<source>1.8</source>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
因为是tomcat中也有servlet-api包,如果默认为compile,即项目在编译,测试,运行阶段都需要这个artifact对应的jar包在classpath中,那么在使用tomcat运行时就会发生了冲突,由于provided只影响编译和测试阶段,在编译测试阶段,我们需要这个artifact对应的jar包在classpath中,而在运行阶段,假定目标的容器(比如我们这里的tomcat容器)已经提供了这个jar包,所以无需我们这个artifact对应的jar包了,那么在实际发布时会默认使用第三方web服务器中提供的jar包,而不会使用本jar包。注意这些声明没有传递性,间接依赖不起作用。
# 实例
# mvn创建
使用命令创建一个项目:
mvn archetype:generate -DgroupId=com.xie.com -DartifactId=xie-maven-web -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
项目打包:
mvn package
# IDE创建
在Intellij或者Eclipse中生成Maven项目,可以在创建项目处选择Maven,然后根据提示进行即可。
# 常见问题
# 不支持发行版本5
在IDEA使用Maven构建项目提示总提示 Error:java: 错误: 不支持发行版本 5,是因为Intellij IDEA用Maven来构建项目,若pom.xml没有指定版本,总是默认Language level 5 与 Java Compiler 1.5。
解决办法就是修改pom.xml:
添加properties节点:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!--修改Language level--> <maven.compiler.source>1.8</maven.compiler.source> <!--修改Java Compiler--> <maven.compiler.target>1.8</maven.compiler.target> </properties>
1
2
3
4
5
6
7pom.xml中添加build节点:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
1
2
3
4
5
6
7
8
9
10
11
12