一、为什么学习maven
1、分模块管理
如果项目非常庞大,就不适合使用package来划分模块,最好是每一个模块
对应一个工程,利于分工协作,借助于maven就可以将一个项目拆分成多个工程。
2、依赖管理
实际开发中项目肯定有多个,相同的jar包重复出现在不同的工程中,之前的做法是需要将jar文件粘贴复制到各个项目中;借助于maven,可以将jar包都存放到“仓库”中,需要的时候只要使用引用即可。
3、统一下载jar
jar包需要的时候每次都要自己准备好或官网下载,借助于maven可以使用统一
的规范方式下载jar包。
4、解决版本冲突
不同的项目在使用jar包的时候,有可能会导致各个项目的jar包版本不一致,导致
未执行错误,借助于maven,所有的jar包都放在仓库中,所有的项目都使用仓库的一份jar包。
5、自动导入依赖包
一个jar包依赖其他的jar包需要自己手动加入项目中,例如FileUpload组件–>IO组件,commons-fileupload-1.3.jar依赖于commons-io-2.0.1.jar,这样极大的浪费了我们导入包的时间成本,也极大的增加了学习成本。借助于maven,它会自动的将依赖的jar包导入进来。
二、maven是什么
1、概念: Maven是一个采用纯Java编写的开源项目管理工具,简化和标准化项目建设过程;maven采用了POM概念来管理项目,所有的项目配置信息都被定义pom.xml文件中;maven可以用于构建工程,管理jar包,编译代码,还可以部署项目,生成web站点。
2、 优点
- 简化了项目依赖管理
- 易于上手
- 便于项目升级,无论是项目本身升级还是项目使用的依赖升级。
- 有助于多模块项目的开发,一个模块开发好后,发布到仓库,依赖该模块时可以直接从仓库更新,不用手动去编译。
- Maven有很多插件,便于功能扩展,比如生产站点,自动发布版本等。
3、缺点
- Maven是一个庞大的构建系统,学习难度大。
- Maven采用约定优于配置的策略,虽然上手容易,但是出现问题难于调试。
- 中国的网络环境差,很多repository无法访问,比如google code, jboss 仓库无法访问等。
三、maven下载及安装
1、下载 Maven
官网地址 http://maven.apache.org/release-notes-all.html , 这里使用版本3.6.0
2、配置环境变量
注:配置maven环境前提是配置jdk,此处使用jdk1.8,附
JDK安装与JAVA_HOME环境配置
-
添加系统变量,变量值为下载maven后解压的目录位置,配置如图
-
在path环境变量最后附加上 %MAVEN_HOME%\bin ,如图
3、检测配置是否成功
-
进入命令行(DOS窗口)模式,输入 echo %MAVEN_HOME% 如果能显示 D:\apache-maven-3.6.0 说明环境变量配置正确,如图
-
输入 mvn -version,正常情况下会显示maven及jdk的版本号,如图
四、理解“仓库”
- 首次运行完mvn -version后,会在用户目录下创建一个.m2的目录(比如:C:\Users\当前用户名.m2),这个目录是maven的“本地仓库”,仓库是maven中一个很重要的概念。如图
试想一下,我们会在工作中同时创建很多项目,每个项目可能都会引用一些公用的jar包(.NET中是dll文件),一种作法是每个项目里,都复制一份这些依赖的jar包(或dll文件),这样显然不好,相同的文件在硬盘上保存了多份,太占用空间,而且这些依赖的jar包(或dll文件)的版本也不太好管理(比如某个公用的jar包,从1.0升级到2.0,如果所有引用这个jar包的项目都需要更新,必须一个个项目的修改)。
maven的仓库则很好的解决了这些问题,它在每台机器上创建一个本机仓库,把本机上所有maven项目依赖的jar包统一管理起来,而且这些jar包用“坐标”来唯一标识(注:坐标是另一个重要的概念,后面还会讲到,这里只要简单理解成“唯一识别某个jar包文件名、版本号”的标识即可),这样所有maven项目就不需要再象以前那样把jar包复制到lib目录中,整个maven项目看起来十分清爽。
也可以不使用默认仓库,自行创建
仓库的分类
(1)本地仓库:当前电脑上的仓库
(2)远程仓库:
-
私服:搭建在局域网中,一般公司都会有私服,私服一般使用nexus搭建。
-
中央仓库:架设在Internet上,例如上面的springframework就是在中央仓库上。
五、理解“坐标”
Maven的一个核心作用就是管理项目的依赖,引入我们所需的各种jar包等。
为了自动化的解析任何一个Java构件,Maven必须将这些jar包或者其他资源进行进唯一标识,这是管理项目的依赖的基础,也就是我们要说的坐标。
Maven中有非常多的Java构件,而使用坐标对每一个构件进行唯一标识。
Maven的坐标元素包括groupId、artifactId、version、packaging、classfier。
只要提供正确的坐标元素,Maven就能找到对应的构件,首先去本地仓库查找,若
没有再去远程仓库下载。如果没有配置远程仓库,会默认从中央仓库地址(http://repo1.maven.org/maven2)下载构件,该中央仓库包含了世界上大部分流行的开源项目构件。
例如:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
坐标元素详解:
-
groupId:定义当前maven项目隶属于的实际项目。Maven项目与实际项目不一定是一对一的关系。SpringFrameWork这一实际项目,其对应的Maven项目会有很多,如spring-core,spring-context等。这是由于Maven中模块的概念,因此,一个实际项目往往会被划分成很多模块。groupId的表示方式与Java包名的表达方式类似,通常与域名反向一一对应。
-
artifactId:该元素定义当前实际项目中的一个Maven项目(模块),推荐的做法
是使用实际项目名称作为artifactId前缀。例如以上的junit,junit就是实际项目的名称。在默认情况下,maven生成的构件,会以artifactId作为文件头,如junit-3.8.1.jar。使用实际项目名称作为前缀,就能方便的从本地仓库找到某个项目的构件。 -
version:该元素定义了使用构件的版本,如上例中的junit版本是4.11。
-
packaging:定义Maven项目打包的方式,使用构件的什么包。打包方式通常与所生成构件的文件扩展名对应,如上例中没有packaging,则默认jar包,也可以打包成war包等。
-
classifier:该元素用来帮助定义构件输出的一些附件。附属构件与主构件对应,如上例中的主构件为junit-4.11.jar,该项目可能还会通过一些插件生成如junit-4.11-javadoc.jar,junit-4.11-sources.jar, 这样附属构件也就拥有了自己唯一的坐标。
注: 上述5个元素中,groupId、artifactId、version是必须定义的,packaging是可选的,默认为jar,而classifier是不能直接定义的,需要结合插件使用。
六、使用命令行创建第一个maven项目
1、创建maven
打开dos命令,cd进入项目存放的路径
输入命令 mvn archetype:generate ,命令执行后需要等一会,此时正在联网加载项目模板,加载完成后如图:
系统提示输入序号选择一个模板类型,这里推荐使用1328,接下来我们输入1328
输入后提示选择版本,输入8,提示输入groupId、artifactId等,上文对这些属性已经介绍过了,version那里直接回车使用默认即可
此时显示创建的maven项目的信息,并提示是否确认创建,输入回车或Y确认,maven项目创建成功,如图 会提示BUILD SUCCESS
接下里我们去创建目录里查看,可以看到项目已经生成
整个maven项目结构如下
注:
- 注意上面带
*
符号的目录名,maven项目采用“约定优于配置”的原则,src/main/java约定存放源代码,src/main/test用于存放单元测试代码,src/target用于存放编译。打包后的输出文件。这是全世界maven项目的通用约定,目录结构固定。 - 从生成的maven项目文件夹中可以看到有个pom.xml文件
pom.xml:Project Object Model 项目对象模型。
它是maven的核心配置文件,所有的构建的配置都在这里设置。
<?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>cn.mavendemo</groupId>
<artifactId>mavendemo01</artifactId>
<version>1.0-SNAPSHOT</version>
<name>mavendemo01</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
七、maven常用命令
- mvn clean 清理
- mvn compile 编译主程序
- mvn test-compile 编译测试程序
- mvn test 执行测试
- mvn package 打包
- mvn install 安装
注:执行maven命令必须进入到pom.xml的目录中进行执行,此处列举几个常用的命令,进入其他命令
八、编译maven项目
刚才只是创建好了一个基本的maven项目 ,现在对项目进行编译及一系列后续操作
-
编译
进入刚才项目的目录cd D:\mavendemo01,
然后执行mvn clean compile命令,编译成功如下图所示
-
测试
输入命令mvn clean test
如果单元测试不通过,会提示出错信息,注意看输出。
注:从输出上可以发现,test前,会先执行compile,即先编译,再执行单元测试 -
项目打包
mvn clean package
运行完后,会在target目录下生成jar包
注:从输出 可以发现,package前,会先执行compile,再执行test,最后才是package打包
- 运行
该项目中的AppTest.java中有main方法,可以直接运行,常规方式下,我们如果想直接运行class文件,得敲一段很长的命令,maven中不必这么复杂,先用记事本打开项目根目录下的pom.xml文件,增加以下代码内容:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath>
</classpath>
<argument>cn.mavendemo.App</argument>
</arguments>
</configuration>
</plugin>
注:<argument>
元素对应为自己命名的package值
然后输入命令mvn exec:exec,打印输入Hello World!
- 项目部署
如果是web项目,使用命令 mvn clean jboss-as:deploy 就能自动将web项目部署到jboss中(前提是jboss web server已经成功启动)。
注:若项目只是一个类库,只是封装一些方法供其他项目使用,对于这种项目,
可以使用 mvn clean install 把生成的jar包安装到本地仓库中,这样本机其他项目需要使用该jar时,只要在pom里配置依赖项即可,不用把jar包复制到项目中。
去本地仓库中查看生成的jar文件
九、maven的生命周期
Maven有三套相互独立的生命周期,请注意这里说的是“三套”,而且“相互独立”。三套生命周期如下。
1、Clean Lifecycle:在进行真正的构建之前进行一些清理工作。
Clean生命周期共包含三个阶段
- pre-clean 执行一些需要在clean之前完成的工作
- clean 移除所有上一次构件生成的文件
- post-clean 执行一些需要在clean之后立刻完成的工作
2、Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等
(1)validate
(2)generate-sources
(3)process-sources
(4)generate-resources
(5)process-resources 复制并处理资源文件,至目标目录,准备打包
(6)compile 编译项目的源代码
(7)process-classes
(8)generate-test-sources
(9)process-test-sources
(10)generate-test-resources
(11)process-test-resources 复制并处理资源文件,至目标测试目录
(12)test-compile 编译测试源代码
(13)process-test-classes
(14)test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署
(15)prepare-package
(16)package 接受编译好的代码,打包成可发布的格式,如 JAR
(17)pre-integration-test
(18)integration-test
(19)post-integration-test
(20)verify
(21)install 将包安装至本地仓库,以让其它项目依赖。
(22)deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享
注:不论你要执行生命周期的哪一个阶段,maven都是从这个生命周期的开始执行
3、Site Lifecycle 生成项目报告,站点,发布站点
- pre-site: 执行一些需要在生成站点文档之前完成的工作
- site: 生成项目的站点文档
- post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy: 将生成的站点文档部署到特定的服务器上
十、maven的依赖范围及依赖原则
1、依赖范围:坐标中的标签就是依赖的范围,取值如下:
-
compile:默认值。表示被依赖项目需要参与当前项目的编译,还有后续的测试,
运行周期也参与其中,是一个比较强的依赖。打包的时候通常需要包含进去。 -
test:依赖项目仅仅参与测试的工作,包括测试代码的编译和执行,不会被打包,也就是不会随项目发布,例如junit。
-
runtime:只能运行时使用,如JDBC驱动,适用运行和测试阶段。
-
provided:只在开发、测试阶段使用,目的是不让Servlet容器和你本地仓库中的jar冲突,如servlet.jar。
-
system:从参与度来说,和provided相同,不过被依赖项不会从maven仓库下载,而是从本地文件系统拿。需要添加systemPath的属性来定义路径。
2、依赖传递
A项目依赖B,B项目依赖C
当C增加了一个spring-core.jar 包后,会发现依赖的两个项目都自动增加了这个jar包,这就是依赖的传递性。非compile范围的依赖是不能传递的。
3、 依赖可选
pom.xml文件中, <optional>
标签表示该依赖是否可选,默认是false。如果为true,则表示该依赖不会传递下去,如果为false,则会传递下去。
4、 依赖排除
在某些情况下我们可能需要依赖某个a.jar,但又不想间接依赖这个a.jar所依赖的jar包,这时我们可以采用exclusion 来排除某个依赖。
例如:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.6.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
5、依赖原则
-
路径最短者优先原则
A项目依赖B,B项目依赖C
C项目的log4j的版本是1.2.7版本,B排除了此包的依赖,自己加了一个Log4j的1.2.9的版本,那么A项目遵守路径最短优先原则,Log4j的版本和B项目的版本一致。 -
路径相同先声明优先原则
A项目------依赖------》B项目------依赖-------》log4j.1.2.9.jar
A项目------依赖------》C项目------依赖-------》log4j.1.2.7.jar
以上情况则:谁在WebMavenDemo的pom.xml中先声明的,依赖就用谁的版本。 -
覆写优先
子pom内声明的优先于父pom中的依赖。
十一、build配置
<build>
<!-- 项目的名字 -->
<finalName>WebMavenDemo</finalName>
<!-- 描述项目中资源的位置 -->
<resources>
<!-- 自定义资源1 -->
<resource>
<!-- 资源目录 -->
<directory>src/main/java</directory>
<!-- 包括哪些文件参与打包 -->
<includes>
<include>**/*.xml</include>
</includes>
<!-- 排除哪些文件不参与打包 -->
<excludes>
<exclude>**/*.txt</exclude>
<exclude>**/*.doc</exclude>
</excludes>
</resource>
</resources>
<!-- 设置构建时候的插件 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- 源代码编译版本 -->
<source>1.8</source>
<!-- 目标平台编译版本 -->
<target>1.8</target>
</configuration>
</plugin>
<!-- 资源插件(资源的插件) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- war插件(将项目打成war包) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- war包名字 -->
<warName>WebMavenDemo1</warName>
</configuration>
</plugin>
</plugins>
</build>
注:配置好build后,执行mvn package之后,在maven工程指定的target目录里war包和文件都按照配置的生成了。
下一篇讲解如何使用idea集成maven