Maven
一、为什么使用maven
- 添加第三方jar包
- jar包之间的依赖关系
- 处理jar包之间的冲突
- 获取第三方jar包
- 将项目拆分成多个工程模块
- 实现项目的分布式部署
二、maven简介
Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。
Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目发文时使用 Maven,而且公司项目采用 Maven 的比例在持续增长。
三、maven的使用
1、下载和安装
-
解压:要求目录不要过深、不要有中文和特殊符号
-
必须配置JAVA_HOME环境变量
-
配置环境变量
- MAVEN_HOME 值为Maven的解压路径
- 在path中配置 %MAVEN_HOME%\bin
-
查看安装是否正确:在cmd中通过命令
shellmvn -v
2、配置maven本地仓
-
本地仓位置(下载的jar包放置的位置):在解压路径的conf中的settings.xml,并配置阿里云镜像。
-
在标签中的最后添加本地仓的设置
xml<settings> <localRepository>D:\mavenjar</localRepository> </settings>
-
在标签中配置镜像
xml
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
3、创建指定目录
-
目录结构(手动新建)
project
src
------main
------------java
------------resources
------test
------------java
------------resources
pom.xml
-
目录表示
-
pom.xml文件中编写
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.etime</groupId> <artifactId>maven</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> </project>
-
在src/mian/java/com/etime/maven路径下创建Demo1.java
javapackage com.etime.maven; public class Demo1{ public String sayHello(String name){ return "Hello "+name+"!"; } }
-
在src/test/java/com/etime/maven路径下创建创建TestDemo1.java
javapackage com.etime.maven; import org.junit.Test; public class TestDemo1{ @Test public void t01(){ Demo1 d = new Demo1(); String res = d.sayHello("World!"); System.out.println(res); }
-
在控制台中进入pom.xml文件所在目录
-
执行 mvn compile命令
-
查看根目录变化和仓库的变化(第一次会有点慢,下载指定的jar包,并将main当中的java文件编译成字节码文件)
-
根目录的变化
-
仓库的变化
-
-
cmd 中继续录入mvn clean命令
-
再次查看根目录和仓库的变化(清理之前生成的字节码文件)
-
根目录变化
-
仓库变化
-
-
再次录入 mvn compile命令
-
查看根目录变化(快了很多,只重新生成字节码文件,下载新配置的jar包(如果没有新配置,则不需要下载))
-
根目录变化
-
-
cmd 中录入 mvn test-compile命令,
- 查看target目录的变化(将test中的java文件编译成字节码文件)
-
target目录变化
-
cmd 中录入 mvn test命令,查看target目录变化
-
执行TestDemo1.java的结果:
-
target-test变化02
-
-
cmd 中录入 mvn package命令,查看target目录变化(将项目打包)
- target目录变化
-
cmd 中录入 mvn install命令, 查看本地仓库的目录变化(将项目打包并放到本地仓库当中)
-
注意
- 运行Maven命令时一定要进入pom.xml文件所在的目录!
四、maven核心概念
1、POM
(1) POM:Project Object Model,项目对象模型。
(2) 将Java工程的相关信息封装为对象作为便于操作和管理的模型。
(3) Maven工程的核心配置。
(4) 可以说学习Maven就是学习pom.xml文件中的配置。
2、坐标
(1) maven的坐标
- groupId:公司或组织的域名倒叙(类似于:com.etime)
- artifactId:当前项目的模块名称(类似于:maven)
- version:版本
(2) 举例
xml
<groupId>com.etime</groupId>
<artifactId>maven</artifactId>
<version>1.0-SNAPSHOT</version>
(3) jar包的网站
(4) 通过坐标找到执行的jar包
- 将 groupid、artiactid、version向量链接器得com.etime+maven+1.0 SVNPSHOT
- 根据上方拼接结果作为目录结果在本地仓库中进行查找
- D:\mavenjar\com\etime\maven\1.0-SNAPSHOT\maven-1.0-SNAPSHOT.jar
3、依赖
(1)创建需要引入依赖的项目
-
项目结结构
day02
src
------main
------------java
------------resources
------test
------------java
------------resources
pom.xml
-
在新建项目的pom.xml文件中编写如下代码
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.etime</groupId> <artifactId>demo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>com.etime</groupId> <artifactId>maven</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
-
在新建项目的src/main/java/com/etime/maven2中新建Demo02.java文件
javapackage com.etime.maven1; import com.etime.maven.Demo1; public class Demo2{ public String say(String name){ Demo1 d = new Demo1(); String res = d.sayHello(name)+" I am mary"; return res; } }
-
在新建项目的src/test/java/com/etime/maven2中新建TestDemo02.java文件
javapackage com.etime.maven1; import org.junit.Test; public class TestDemo2{ @Test public void t01(){ Demo2 d = new Demo2(); String res = d.say("jack"); System.out.println(res); } }
-
进入day02项目中pom.xml所在的位置,打开命令窗口分别执行 mvn compile、mvn test-compile、mvn test
-
问题
- 这里project就是我们的第一个Maven工程,现在day02对它有依赖。那么这个依赖能否成功呢?更进一步的问题是:day02工程会到哪里去找project呢
- 回答:本地仓库。任何一个Maven工程会根据坐标到本地仓库中去查找它所依赖的jar包。如果能够找到则可以正常工作,否则就不行。
(2)依赖管理
-
当A jar包需要用到B jar包中的类时,我们就说A对B有依赖。例如:commons-fileupload-1.3.jar依赖于commons-io-2.0.1.jar。
-
通过第二个Maven工程我们已经看到,当前工程会到本地仓库中根据坐标查找它所依赖的jar包。
-
配置的基本形式是使用dependency标签指定目标jar包的坐标。
xml<dependencies> <dependency> <!---坐标 --> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <!-- 依赖的范围 --> <scope>test</scope> </dependency> </dependencies>
-
依赖的范围
- compile
- main目录下的Java代码可以访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时要放在WEB-INF的lib目录下
- 例如:对Demo1的依赖。主程序、测试程序和服务器运行时都需要用到。
- test
- main目录下的Java代码不能访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
- 对junit的依赖。仅仅是测试程序部分需要。
- provided
- main目录下的Java代码可以访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
- servlet-api在服务器上运行时,Servlet容器会提供相关API,所以部署的时候不需要。
- 其他:runtime、import、system等。
(3)依赖的传递性
- 如果A依赖B,B依赖C,那么A→B和B→C都是直接依赖,而A→C是间接依赖
- 当存在间接依赖的情况时,主工程对间接依赖的jar可以访问吗?这要看间接依赖的jar包引入时的依赖范围------只有依赖范围为compile时可以访问。
(4)依赖的原则:解决jar包冲突
- 路径最短者优先
- 路径相同时先声明者优先
- 这里"声明"的先后顺序指的是dependency标签配置的先后顺序。
(5)依赖的排除
- 当前工程为public,直接依赖environment。environment依赖commons-logging的1.1.1对于public来说是间接依赖。
- 当前工程public直接依赖commons-logging的1.1.2加入exclusions配置后可以在依赖environment的时候排除版本为1.1.1的commons-logging的间接依赖。
xml
Environment工程:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
当前工程:
<dependency>
<groupId>com.etime.maven</groupId>
<artifactId>Environment</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 依赖排除 -->
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.2</version>
</dependency>
(6)统一管理目标jar包的版本
-
以对Spring的jar包依赖为例:
- Spring的每一个版本中都包含spring-core、spring-context等jar包。我们应该导入版本一致的Spring jar包,而不是使用4.0.0的spring-core的同时使用4.1.1的spring-context。
xml<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>4.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.0.RELEASE</version> </dependency>
-
问题是如果我们想要将这些jar包的版本统一升级为4.1.1,是不是要手动一个个修改呢?显然,我们有统一配置的方式:
xml<properties> <spring.version>4.1.1.RELEASE</spring.version> </properties> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency>
4、仓库
(1) 本地仓库
- 为当前本机电脑上的所有Maven工程服务。
(2) 远程仓库
- 私服:架设在当前局域网环境下,为当前局域网范围内的所有Maven工程服务。
- 中央仓库:架设在Internet上,为全世界所有Maven工程服务。
- 中央仓库的镜像:架设在各个大洲,为中央仓库分担流量。减轻中央仓库的压力,同时更快的响应用户请求。
(3) 仓库中文件
- Maven的插件
- 我们自己开发的项目的模块
- 第三方框架或工具的jar包
- 注意:不管是什么样的jar包,在仓库中都是按照坐标生成目录结构,所以可以通过统一的方式查询或依赖。
5、生命周期
(1)maven的生命周期
- Maven生命周期定义了各个构建环节的执行顺序,有了这个清单,Maven就可以自动化的执行构建命令了。
- maven有三套相互独立的生命周期
- Clean Lifecycle在进行真正的构建之前进行一些清理工作。
- Default Lifecycle构建的核心部分,编译,测试,打包,安装,部署等等。
- Site Lifecycle生成项目报告,站点,发布站点。
- 它们是相互独立的,你可以仅仅调用clean来清理工作目录,仅仅调用site来生成站点。当然你也可以直接运行 mvn clean install site 运行所有这三套生命周期。
- 生命周期分类
- clean生命周期:Clean Lifecycle 在进行真正的构建之前进行一些清理工作。Clean生命周期一共包含了三个阶段
- pre-clean 执行一些需要在clean之前完成的工作
- clean 移除所有上一次构建生成的文件
- post-clean 执行一些需要在clean之后立刻完成的工作
- Default生命周期:是构建的核心部分,编译,测试,打包,部署等等,Default生命周期是Maven生命周期中最重要的一个,绝大部分工作都发生在这个生命周期中。
- compile 编译项目的源代码
- install 将包安装至本地仓库,以让其它项目依赖。
- deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享
- process-test-resources 复制并处理资源文件,至目标测试目录
- process-resources 复制并处理资源文件,至目标目录,准备打包
- test-compile 编译测试源代码
- test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署
- package 接受编译好的代码,打包成可发布的格式,如 JAR,war
- Site生命周期(Site Lifecycle):生成项目报告,站点,发布站点,站点的文档(站点信息,依赖...)。
- pre-site 执行一些需要在生成站点文档之前完成的工作
- site 生成项目的站点文档
- post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy 将生成的站点文档部署到特定的服务器上
- clean生命周期:Clean Lifecycle 在进行真正的构建之前进行一些清理工作。Clean生命周期一共包含了三个阶段
7、继承
(1)继承机制
- 由于非compile范围的依赖信息是不能在"依赖链"中传递的,所以有需要的工程只能单独配置。此时如果项目需要将各个模块的junit版本统一为4.9,那么到各个工程中手动修改无疑是非常不可取的。使用继承机制就可以将这样的依赖信息统一提取到父工程模块中进行统一管理。
(2)继承项目创建
-
创建父工程
-
创建子模块
- 在父工程中new - module 创建子模块(Java工程或者JavaWeb工程)
-
创建父工程和创建一般的Java工程操作一致,唯一需要注意的是:打包方式处要设置为pom。
-
在子模块中引用父工程
xml<parent> <!-- 父工程坐标 --> <groupId>...</groupId> <artifactId>...</artifactId> <version>...</version> <relativePath>从当前目录到父项目的pom.xml文件的相对路径</relativePath> </parent>
五、IDEA整合maven
1、创建Maven项目
2、创建Maven的JavaWeb项目
3、Maven配置
4、简单测试
-
pom.xml文件
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> <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> </properties> <packaging>war</packaging> <groupId>com.etime</groupId> <artifactId>day02</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- DBUtils --> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency> <!-- 数据库相关 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <!--c3p0--> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </project>
-
Demo.java
javapackage com.etime.demo; import org.apache.commons.dbutils.QueryRunner; import org.junit.Test; import java.sql.SQLException; public class StudentDemo { @Test public void t01() { //删除学号为1的学生 QueryRunner queryRunner = new QueryRunner(C3P0Util.getDataSource()); String sql = "delete from student where sid=2"; try { int rows = queryRunner.update(sql); System.out.println(rows); } catch (SQLException e) { e.printStackTrace(); } } }
-
注意:c3p0的配置文件需要放到test中的resources文件夹中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OiYbFKb0-1692059360442)(F:\Java语言\课程笔记\第六阶段\myself\maven\img\testc3p0.png)]
-
.demo;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import java.sql.SQLException;
public class StudentDemo {
@Test
public void t01() {
//删除学号为1的学生
QueryRunner queryRunner = new QueryRunner(C3P0Util.getDataSource());
String sql = "delete from student where sid=2";
try {
int rows = queryRunner.update(sql);
System.out.println(rows);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
- 注意:c3p0的配置文件需要放到test中的resources文件夹中