Maven入门
1、Maven介绍
1.1、什么是Maven
Maven在美国是一个口语化的词语,代表专家、内行的意思。一个对Maven比较正式的定义是这么说的:Maven是一个项目管理工具,它包含了一个项目对象模型(POM,Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
1.2、Maven能解决什么问题
可以用更通俗的方式来说明,我们直到,项目开发不仅仅是写代码而已,期间会伴随着各种必不可少的事情要做,下面列举几个感受一下:
- 我们需要引用各种jar包,尤其是比较大的工程,引用的jar包往往有几十个乃至上百个,每用到一种jar包,都需要手动引入工程目录,而且经常遇到各种jar包冲突,版本冲突。
- 我们辛辛苦苦写好了Java文件,可是只懂0和1的白痴电脑却完全读不懂,需要将它编译成二进制字节码,好歹现在这项工作可以由各种集成开发工具帮我们完成,Eclipse、IDEA等都可以将代码即时编译。
- 世界上没有不存在bug的代码,为了追求减少bug,因此写完了代码,我们还要写一些单元测试,然后一个个地运行来检验代码质量。
- 再优雅的代码也是要出来卖的,我们后面还需要把代码与各种配置文件、资源整合到一起,定型打包,如果是web项目,还需要将其发布到服务器。
试想,如果现在有一种工具,可以把你从上面地繁琐工作中解放出来,能帮你构建工程,管理jar包,编译代码,还能帮你自动运行单元测试,打包,生成报表,甚至能帮你部署项目,生成Web站点,你会心动吗?Maven就可以解决上面所提到的这些问题。
2、Maven的安装
下载地址:Maven – Download Apache Maven
下载解压后,配置环境变量,依次点击 此电脑 -> 属性 -> 高级 -> 环境变量 -> 在系统变量栏下点击新建 -> 变量名为 MAVEN_HOME ,变量值为:D:\apache-maven-3.8.4 -> 确定 -> 在系统变量栏中找到 Path 并选中 -> 编辑 -> 新建 -> 输入 %MAVEN_HOME%\bin -> 依次点击确定即可。
检查是否安装成功:在cmd中输入:mvn -v ,如果出现Maven相关信息,则说明安装成功。
3、Maven仓库
3.1、Maven仓库的分类
maven的工作需要从仓库下载一些jar包,本地的项目A、项目B等都会通过maven软件从远程仓库(可以理解为互联网上的仓库)下载jar包并保存在本地仓库,本地仓库,就是本地文件夹,当第二次需要此jar包时则不再从远程仓库下载,因为本地仓库已经存在了,可以将本地仓库理解为缓存,有了本地仓库就不用每次从远程仓库下载了。
本地仓库:用来存储从远程仓库或中央仓库下载的插件和jar包,项目使用一些插件或jar包,优先从本地仓库查找。默认本地仓库位置在 ${user.dir}/.m2/responsitory,${user.dir}表示windows用户目录。
远程仓库:如果本地需要插件或者jar包,本地仓库没有,默认去远程仓库下载。远程仓库可以在互联网也可以在局域网内。
中央仓库:在maven软件中内置一个远程仓库地址 http://repo1.maven.org/maven2 ,它是中央仓库,服务于整个互联网,它是由Maven团队自己维护,里面存储了非常全的jar包,它包含了世界上大部分流行的开源项目构建。
3.2、Maven本地仓库的配置
conf目录下的settings.xml:
<?xml version="1.0" encoding="UTF-8"?>
..
<!--本地仓库位置-->
<localRepository>D:/apache-maven-3.8.4/mvn_repository</localRepository>
..
<!--远程仓库-->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
..
4、Maven工程的目录结构
项目的根目录下:
.settings目录:工具生成的文件
src目录:源代码(必备)
main目录:主工程代码
java:放入项目的源码
resources:放入配置文件
webapp:web项目的资源目录(jsp/html/WEB-INF)
test目录:测试代码
java:测试的源码
resources:测试的配置文件
target目录:编译生成的文件
.classpath文件
.project文件
.tern-project文件
pom.xml文件:maven工程的核心配置文件,如坐标信息。(必备)
5、Maven命令
5.1、Maven常用命令
5.1.1、compile命令
compile是maven工程的编译命令,作用是将 src/main/java 下的文件编译为class文件输出到target目录下。
cmd中执行 mvn compile 。
5.1.2、clean命令
删除target目录。
5.1.3、package命令
5.1.4、install命令
将项目安装到本地仓库中。
5.2、Maven指令的生命周期
maven对项目构建过程分为三套相互独立的生命周期,这三套生命周期分别是:
- Clean Lifecycle:在进行真正的构建之前进行一些清理工作。
- Default Lifecycle:构建的核心部分。编译(compile),测试(test),打包(package),部署(install)等等。
- Site Lifecycle:生成项目报告,站点,发布站点。
同一套生命周期中,执行后边的操作,会自动执行前边的所有操作。
6、Maven的概念模型
Maven包含了一个项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
7、Maven坐标
坐标:被Maven管理的资源的唯一标识。
一个坐标由以下组成:
- groupId:组织名称
- atifactId:模块名称
- version:版本号
8、IDEA开发Maven项目
8.1、IDEA的Maven配置
打开IDEA -> File -> Settings 配置 Maven:
最后点击ok即可。
8.2、IDEA创建Maven的Java项目(方式1:不使用骨架)
打开IDEA,依次点击File -> New -> Project。
注:在test目录下创建resources资源文件夹方法:在test目录下创建一个resources文件夹,然后对该文件夹右键 -> Mark Directory as -> Test Resources Root 即可。
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.clp</groupId>
<artifactId>MavenProject</artifactId>
<version>1.0-SNAPSHOT</version>
<!--
打包方式:
1、jar:java项目默认值。
2、war:web项目。
3、pom
-->
<packaging>jar</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
8.3、IDEA创建Maven的Java项目(方式2:使用骨架)
打开IDEA,依次点击File -> New -> Project。
后面的设置参照不使用骨架情形即可。
初次使用骨架会进行一系列下载,等待下载完成即可。(出现BUILD SUCCESS说明成功完成)。
8.4、使用依赖导入jar包
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.clp</groupId>
<artifactId>MavenProject</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!--导入依赖的jar包(如junit),百度搜索坐标,输入:junit maven即可搜到-->
<dependencies>
<dependency>
<groupId> </groupId>
<artifactId> </artifactId>
<version> </version>
</dependency>
</dependencies>
<!--添加插件(可按住Alt+Ins提示,需要本地仓库有该插件)-->
<build>
<plugins>
<!--如:添加编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compile-plugin</artifactId>
<version>3.1</version>
<configuration>
<target>1.8</target>
<source>1.8</source>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
8.5、IDEA创建Maven的JavaWeb项目(不使用骨架)
打开IDEA,依次点击 File -> New -> Project 。
设置pom的内容:
...
<groupId>com.clp</groupId>
<artifactId>MevenWeb</artifactId>
<version>1.0-SNAPSHOT</version>
<!--加上这一句-->
<packaging>war</packaging>
...
然后在main目录下创建webapp目录和index.jsp,在webapp目录下创建WEB-INF目录和web.xml文件。
8.6、使用Tomcat插件启动web项目
下载 tomcat 7.0.92 。
在pom.xml中加入:
<build>
...
<plugins>
<!--添加tomcat7插件,可以启动当前web应用-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<!--修改tomcat启动的端口号-->
<port>80</port>
<!--修改tomcat部署当前项目的虚拟目录(项目的访问路径)-->
<path>/MevenWeb</path>
</configuration>
</plugin>
</plugins>
...
</build>
点开右侧的maven侧边栏,找到所在项目,再找到Plugins一栏,找到tomcat7,并双击该项下的tomcat7-run。
注意:通过配置方式启动tomcat方法:依次点击 Run -> Edit Configurations -> 点击+号 -> Maven:
8.7、编写Servlet-依赖范围配置
在pom.xml中添加:
<dependencies>
...
<!-- 添加servlet的依赖jar包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
...
</dependencies>
8.7.1、依赖范围详解
A依赖B,需要在A的pom.xml文件中添加B的坐标,添加坐标时需要指定依赖范围,依赖范围包括:
- compile(默认值):编译范围(写代码的环境),指A在编译时依赖B,此范围为默认依赖范围。编译范围的依赖会用在编译、测试、运行,由于运行时需要所以编译范围的依赖会被打包。
- provided:provided依赖只有在当JDK或者一个容器已提供该依赖之后才使用,provided依赖在编译和测试时需要,在运行时不需要,比如:servlet api 被 tomcat 容器提供。
- runtime:runtime依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如:jdbc的驱动包,由于运行时需要所以runtime范围的依赖会被打包。
- test:test范围依赖在编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用,比如:junit。由于运行时不需要所以test范围依赖不会被打包。
- system:system范围依赖与provided类似,但是你必须显式地提供一个对于本地系统中JAR文件的路径,需要指定systemPath磁盘路径,system依赖不推荐使用。
在MavenWeb工程中测试各种scope,测试总结:
- 默认引入的jar包 —— compile,默认范围,可以不写,编译、测试、运行都有效。
- servlet-api、jsp-api —— provided,编译、测试有效,运行时无效,防止和tomcat下jar包冲突。
- jdbc驱动jar包 —— runtime,测试、运行有效。
- junit —— test,测试有效。
依赖范围由强到弱的顺序是:compile > provided > runtime > test 。
9、分模块开发与设计
9.1、分模块开发步骤
步骤:
- 创建Maven模块;
- 书写模块代码:分模块开发需要先针对模块功能进行设计,再进行编码。不会先将工程开发完毕,然后进行拆分。
- 通过maven指令安装模块的本地仓库(install指令),因为maven需要通过仓库读取模块。团队内部开发需要发布模块功能到团队内部可共享的仓库中(私服)。
- 添加相应模块的依赖。
10、依赖管理
10.1、依赖添加
依赖指当前项目运行所需的jar包,一个项目可以设置多个依赖。格式:
pom.xml:
...
<!-- 设置当前项目所依赖的所有jar包-->
<dependencies>
<!-- 设置具体的依赖 -->
<dependency>
<!-- 依赖所属群组id -->
<groupId>org.springframework</groupId>
<!-- 依赖所属项目id -->
<artifactId>spring-webmvc</artifactId>
<!-- 依赖版本号 -->
<version>5.2.10.RELEASE</version>
</dependency>
</depedencies>
...
10.2、依赖传递
依赖具有传递性:
- 直接依赖:在当前项目中通过依赖配置建立的依赖关系。
- 间接依赖:当前项目依赖的资源如果依赖其他资源,则该项目间接依赖其他资源。
依赖传递的冲突问题:
- 路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高。
- 声明优先:当相同资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的。
- 特殊优先:当相同层级配置了相同资源的不同版本,后配置的覆盖先配置的。
可选依赖:指对外隐藏当前所依赖的资源——不透明。
pom.xml:
...
<!-- 依赖module_pojo运行 -->
<dependency>
<groupId>com.clp</groupId>
<artifactId>module_pojo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 可选依赖是隐藏当前工程所依赖的资源,隐藏后对应资源将不具有依赖传递性-->
<optional>true</optional>
</dependency>
...
排除依赖:指主动断开依赖的资源,被排除的资源无需指定版本——不需要。排除依赖只需指定groupId和artifactId即可。
pom.xml:
...
<!-- 依赖module_pojo运行 -->
<dependency>
<groupId>com.clp</groupId>
<artifactId>module_pojo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 排除依赖: 排除 module_pojo模块 依赖的 log4j -->
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
...
11、继承与聚合
聚合:将多个模块组织成一个整体,同时进行项目构建的过程。
聚合工程:通常是一个不具有业务功能的“空”工程(有且仅有一个.pom文件)。
作用:使用聚合工程可以将多个工程编组,通过对聚合工程进行构建,实现对所包含的模块进行同步构建。
当工程中某个模块发生更新(变更)时,必须保障工程中与已更新模块关联的模块同步更新,此时可以使用聚合工程来解决批量模块同步构建的问题。
11.1、聚合工程开发
步骤:
- 创建Maven模块,设置打包类型为pom,再设置当前聚合工程所包含的子模块名称。注意:聚合工程中所包含的模块在进行构建时会根据模块间的依赖关系设置构建顺序,与聚合工程中模块的配置书写位置无关,参与聚合的工程无法向上感知是否参与聚合,只能向下配置哪些模块参与本工程的聚合。
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.clp</groupId> <artifactId>module</artifactId> <version>1.0-SNAPSHOT</version> <!-- 指定该工程为聚合工程 --> <packaging>pom</packaging> <!-- 设置管理的模块名称(不区分顺序) --> <modules> <module>../module_dao</module> <module>../module_pojo</module> <module>../module_ssm</module> </modules> </project>
11.2、继承工程开发
继承:继承描述的是两个工程之间的关系,与java中的继承相似,子工程可以继承父工程中的配置信息,常见于依赖关系的继承。
作用:① 简化配置;② 减少版本冲突。
11.2.1、继承开发步骤
- 创建Maven模块,设置打包类型为pom(建议父工程打包方式设置为pom);
pom.xml ... <groupId>com.clp</groupId> <artifactId>module</artifactId> <version>1.0-SNAPSHOT</version> <!-- 指定该工程为聚合工程 --> <packaging>pom</packaging> ...
- 在父工程的pom文件中配置依赖关系(子工程将沿用父工程中的依赖关系)以及子工程中可选的依赖关系;
父工程的pom.xml: ... <dependencies> <!-- 设置具体的依赖 --> <dependency> <!-- 依赖所属群组id --> <groupId>org.springframework</groupId> <!-- 依赖所属项目id --> <artifactId>spring-webmvc</artifactId> <!-- 依赖版本号 --> <version>5.2.10.RELEASE</version> </dependency> ... <!-- 定义依赖管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> ...
- 在子工程中配置当前工程所继承的父工程,并配置使用父工程中可选依赖的坐标。注意:子工程中使用父工程中的可选依赖时,仅需要提供群组id和项目id,无需提供版本,版本由父工程统一提供,避免版本冲突。子工程中还可以定义父工程中没有的依赖关系。
子工程的pom.xml: ... <!-- 配置当前工程继承自parent工程 --> <parent> <groupId>com.clp</groupId> <artifactId>module</artifactId> <version>1.0-SNAPSHOT</version> <!-- 填写父工程的pom文件位置(可以帮助快速定位位置,不写也可以) --> <relativePath>../module/pom.xml</relativePath> </parent> ... <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> ...
11.3、聚合与继承的区别
作用:聚合用于快速构建项目,继承用于快速配置。
相同点:
- 聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中;
- 聚合与继承均属于设计型模块,并无实际的模块内容。
不同点:
- 聚合是在当前模块中中配置关系,聚合可以感知到参与聚合的模块有哪些;
- 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己。
12、属性
12.1、属性配置与使用
步骤:
- 定义属性;
pom.xml: ... <!-- 定义属性 --> <properties> <spring.version>5.2.10.RELEASE</spring.version> <junit.version>4.12</junit.version> <mybatis-spring.version>1.3.0</mybatis-spring.version> </properties> ...
- 引用属性。
pom.xml: ... <!-- 设置具体的依赖 --> <dependency> <!-- 依赖所属群组id --> <groupId>org.springframework</groupId> <!-- 依赖所属项目id --> <artifactId>spring-webmvc</artifactId> <!-- 依赖版本号 --> <version>${spring.version}</version> </dependency> ...
12.2、资源文件引用属性
步骤:
- 定义属性;
pom.xml: ... <!-- 定义属性 --> <properties> <jdbc.url>jdbc:mysql://127.0.0.1:3306/ssmdb</jdbc.url> </properties> ...
- 配置文件中引用属性;
jdbc.properties: jdbc.driver=com.mysql.jdbc.Driver jdbc.url=${jdbc.url} jdbc.username=root jdbc.password=123456
- 开启资源文件目录加载属性的过滤器。
pom.xml: ... <build> <resources> <resource> <directory>${project.basedir}/src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> ...
- 配置maven打war包时,忽略web.xml检查。
pom.xml: ... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.2.3</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> ...
12.3、其他属性(了解)
属性分类 | 引用格式 | 示例 |
---|---|---|
自定义属性 | ${自定义属性名} | ${spring.version} |
内置属性 | ${内置属性名} | ${basedir} 、${version} |
Setting属性 | ${setting.属性名} | ${settings.localRepository} |
Java系统属性 | ${系统属性分类.系统属性名} | ${user.home} |
环境变量属性 | ${env.环境变量属性名} | ${env.JAVA_HOME} |
12.4、版本管理
工程版本:
- SNAPSHOT(快照版本):① 项目开发过程中临时输出的版本,称为快照版本;② 快照版本会随着开发的进展不断更新。
- RELEASE(发布版本):项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件时稳定的,即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本。
发布版本:① alpha版;② beta版;③ 纯数字版。
13、多环境配置与应用
13.1、多环境开发
maven提供配置多种环境的设定,帮助开发者使用过程中快速切换环境。
步骤:
- 定义多环境;
pom.xml: ... <!-- 配置多环境 --> <profiles> <!-- 开发环境 --> <profile> <!-- 环境对应的唯一id --> <id>env_dev</id> <properties> <jdbc.url>jdbc:mysql://127.0.0.1:3306/ssmdb</jdbc.url> </properties> <activation> <!-- 设定是否为默认启动的环境 --> <activeByDefault>true</activeByDefault> </activation> </profile> <!-- 生产环境 --> <profile> <id>env_pro</id> <properties> <jdbc.url>jdbc:mysql://127.0.0.2:3306/ssmdb</jdbc.url> </properties> </profile> <!-- 测试环境 --> <profile> <id>env_test</id> <properties> <jdbc.url>jdbc:mysql://127.0.0.3:3306/ssmdb</jdbc.url> </properties> </profile> </profiles> ...
- 使用多环境(构建过程)。
mvn 指令 -P 环境定义id 例如:mvn install -P pro_env
13.2、跳过测试
应用场景:
- 功能更新中并且没有开发完毕;
- 快速打包;
- ...
配置:
pom.xml:
细粒度控制跳过测试:
...
<!-- 设定测试插件 -->
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<skipTests>false</skipTests>
<!-- 包含指定的测试用例 -->
<includes>
<include>**/User*Test.java</include>
</includes>
<!-- 排除掉不参与测试的内容 -->
<excludes>
<exclude>**/BookServiceTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
...
- 跳过测试
mvn 指令 -D skipTests
范例:mvn install -D skipTests
注意:执行的项目构建指令必须包含测试生命周期,否则无效果。例如执行compile生命周期,不经过test生命周期。
14、私服
私服是一台独立的服务器,用于解决团队内部的资源共享与资源同步的问题。
Nexus是Sonatype公司的一款maven私服产品,下载地址:https://help.sonatype.com/repomanager3/download 。