一、Maven介绍
1.什么是maven
Maven 是一个项目管理工具,它包含了一个 项目对象模型 (POM:Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
2.maven能解决什么问题
- 比较大的工程引用的ar包太多,还需要手动引入工程,经常出现jar冲突,版本冲突等问题。
- 导入jar的项目太过于庞大,不易于管理。
所以我们使用maven来构建项目,易于管理,项目轻巧可重用等。
3.maven的两个主要作用
- Maven 的依赖管理
- 项目的一键构建
二、Maven的安装及配置
1.安装Maven
为了使用 Maven 管理工具,我们首先要到官网去下载它的安装软件。通过百度搜索“Maven“如下:
点击 Download 链接,就可以直接进入到 Maven 软件的下载页面:
下载地址:http://maven.apache.org/download.cgi
Maven 下载后,将 Maven 解压到一个没有中文没有空格的路径下,比如 D:\develop\my_maven下面。
解压后目录结构说明:
bin:存放了 maven 的命令,比如我们前面用到的mvn tomcat:run
boot:存放了一些 maven 本身的引导程序,如类加载器等
conf:存放了 maven 的一些配置文件,如 setting.xml 文件
lib:存放了 maven 本身运行所需的一些 jar 包
至此我们的 maven 软件就可以使用了,前提是你的电脑上已经安装并配置好了 JDK。
测试Maven是否可以使用
找开 cmd 命令,输入 mvn –v命令。
发现 maven 的版本,及 jdk 的版本符合要求,这样我们的 maven 软件安装就成功了。
2.本地仓库的配置
- 将 “repository.rar”解压到自己的电脑上(放在没有中文及空格的目录下)比如解压到:D:\develop\my_maven\maven_repository
- 找到maven 的安装目录的文件中配置本地仓库位置(比如: D:\develop\my_maven\apache-maven-3.5.2\conf\settings.xml )
- 打开 settings.xml文件,找到
<localRepository>
标签,配置如下:
如果需要Maven 在任何下都可访问 ,还可以配置环境变量即可。
3.Maven仓库的分类
- 本地仓库 :用来存储从远程仓库或中央仓库下载的插件和 jar 包,项目使用一些插件或 jar 包,优先从本地仓库查找。
- 远程仓库(私服):如果本地需要插件或者 jar 包,本地仓库没有,默认去远程仓库下载。远程仓库可以在互联网内也可以在局域网内。
- 中央仓库 :在 maven 软件中内置一个远程仓库地址
http://repo1.maven.org/maven2
,它是中央仓库,服务于整个互联网,它是由 Maven 团队自己维护,里面存储了非常全的 jar 包,它包含了世界上大部分流行的开源项目构件。
三、Maven工程的认识
1.Maven 工程的目录结构
作为一个 maven 工程,它的 src目录和 pom.xml 是必备的。
进入 src目录后,我们发现它里面的目录结构如下:
src/main/java —— 存放项目的.java 文件
src/main/resources —— 存放项目资源文件,如 spring, hibernate 配置文件
src/test/java —— 存放所有单元测试.java 文件,如 JUnit 测试类
src/test/resources —— 测试资源文件
target —— 项目输出位置,编译后的class 文件会输出到此目录
pom.xml——maven 项目核心配置文件
注意:如果是普通的 java 项目,那么就没有webapp 目录。
2.Maven 常用命令
我们可以在cmd 中通过一系列的 maven 命令来对我们的 maven-helloworld 工程进行编译、测试、运行、打包、安装、部署。
- compile
compile 是 maven 工程的编译命令,作用是将 src/main/java 下的文件编译为 class 文件输出到 target目录下。
- test
test 是 maven 工程的测试命令 mvn test,会执行src/test/java下的单元测试类。
- clean
clean 是 maven 工程的清理命令,执行 clean 会删除 target 目录及内容。
- package
package 是 maven 工程的打包命令,对于 java 工程执行 package 打成 jar 包,对于web 工程打成war包。
- install
install 是 maven 工程的安装命令,执行 install 将 maven 打成 jar 包或 war 包发布到本地仓库。
从运行结果中,可以看出:当后面的命令执行时,前面的操作过程也都会自动执行。
3.Maven 指令的生命周期
Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。
Site Lifecycle 生成项目报告,站点,发布站点。
maven 的概念模型
4.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">
<!--指定了当前pom的版本-->
<modelVersion>4.0.0</modelVersion>
<!--项目名称,定义为组织名+项目名,类似包名-->
<groupId>com.kuang</groupId>
<!-- 模块名称 -->
<artifactId>hello_maven</artifactId>
<!-- 当前项目版本号,snapshot 为快照版本即非正式版本,release为正式发布版本 -->
<version>0.0.1-SNAPSHOT</version>
<!--打包方式:默认是jar,可选war、zip、pom-->
<packaging>jar</packaging>
<!--指定编码格式-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 依赖关系 -->
<dependencies>
<!-- 此项目运行使用 junit,所以此项目依赖 junit -->
<dependency>
<!-- junit 的项目名称 -->
<groupId>junit</groupId>
<!-- junit 的模块名称 -->
<artifactId>junit</artifactId>
<!-- junit 版本 -->
<version>4.9</version>
<!-- 依赖范围:单元测试时使用 junit -->
<scope>test</scope>
</dependency>
5.jdk版本全局修改
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
四、idea 开发 maven 项目
1.idea的maven 配置
依据图片指示,选择本地 maven 安装目录,指定 maven 安装目录下conf文件夹中 settings 配置文件。
2.idea 中创建一个 maven 的 web 工程
点击 Next选择项目所在目录
点击 Finish后开始创建工程,耐心等待,直到出现如下界面。
手动添加 src/main/java 目录,如下图右键 main 文件夹NewDirectory
创建一个新的文件夹命名为 java
点击 OK 后,在新的文件夹 java 上右键Make Directory asSources Root
此时项目已经maven项目已经创建好了。
之后在编写程序之前,先在pom.xml文件中引用需要的坐标,之后编写业务即可。
坐标的来源方式:http://mvnrepository.com/
示例:
3.依赖范围
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依赖不推荐使用。
在 maven-web 工程中测试各各 scop。
测试总结:
- 默认引入 的 jar 包 ------- compile 【默认范围 可以不写】(编译、测试、运行 都有效 )
- servlet-api 、jsp-api ------- provided (编译、测试 有效, 运行时无效 防止和 tomcat 下 jar 冲突)
- jdbc 驱动 jar 包 ---- runtime (测试、运行 有效 )
- junit ----- test (测试有效)
依赖范围由强到弱的顺序是:compile>provided>runtime>test
4.设置 jdk 编译版本
需要设置编译版本为 1.8,这里需要使用 maven 的插件来设置。
在 pom.xml 中加入:
<build>
<plugins>
<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>
</plugins>
</build>
5.添加 tomcat7 插件
在 pom 文件中添加如下内容:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>8080</path>
<path>/</path>
</configuration>
</plugin>
此时点击 idea最右侧 Maven Projects,
就可以看到我们新添加的tomcat7 插件
双击 tomcat7插件下tomcat7:run 命令直接运行项目
也可以直接点击如图按钮,手动输入 tomc7:run 命令运行项目
点击后弹出如下图窗口
运行即可。
6.什么是依赖传递
我们以springmvc的核心坐标为例:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
会发现出现除了 spring-webmvc 以外的其他 jar。因为我们的项目依赖spring-webmv.jar,而spring-webmv.jar 会依赖spring-beans.jar 等等,所以 spring-beans.jar 这些 jar 包也出现在了我们的 maven 工程中,这种现象我们称为依赖传递。从下图中可看到他们的关系:(请注意spring-beans 的版本)
7.依赖冲突的解决
接着添加一个依赖
我们会发现这两个 jar 包同时都依赖了 spring-beans
但是spring-webmvc 依赖 spirng-beans-4.2.4,spring-context 依赖 spring-beans-5.0.2,但是发现spirng-beans-4.2.4 加入到工程中,而我们希望 spring-beans-5.0.2 加入工程。这就造成了依赖冲突。解决依赖冲突有以下原则:
1.依赖调解原则
1 、第一声明者优先原则
在 pom 文件定义依赖,先声明的依赖为准。
测试:
如果将上边 spring-webmvc 和 spring-context 顺序颠倒,系统将导入 spring-beans-5.0.2。
分析:
由于 spring-webmvc 在前边以 spring-webmvc 依赖的 spring-beans-5.0.2 为准,所以最终spring-beans-5.0.2 添加到了工程中。
2 、路径近者优先原则
例如:还是上述情况,spring-contex 和 spring-webmvc 都会传递过来 spirng-beans,那如果直接把 spring-beans 的依赖直接写到 pom 文件中,那么项目就不会再使用其他依赖传递来的 spring-beans,因为自己直接在 pom 中定义 spring-beans要比其他依赖传递过来的路径要近。
2.锁定版本
面对众多的依赖,有一种方法不用考虑依赖路径、声明优化等因素可以采用直接锁定版本的方法确定依赖构件的版本,版本锁定后则不考虑依赖的声明顺序或依赖的路径,以锁定的版本的为准添加到工程中,此方法在企业开发中常用。
如下的配置是锁定了 spring-beans 和 spring-context 的版本:
还可以把版本号提取出来,使用标签设置成变量。
注意:在工程中锁定依赖的版本并不代表在工程中添加了依赖,如果工程需要添加锁定版本
的依赖则需要单独添加<dependencies></dependencies>
标签
五、分模块构建工程
继承:创建一个 parent 工程将所需的依赖都配置在 pom 中
聚合:聚合多个模块运行。
1.需求
将 SSM 工程拆分为多个模块开发:ssm_dao、ssm_service、ssm_web
2.理解继承和聚合
通常继承和聚合同时使用。
何为继承?
继承是为了消除重复,如果将 dao、service、web 分开创建独立的工程则每个工程的 pom.xml文件中的内容存在重复,比如:设置编译版本、锁定 spring的版本的等,可以将这些重复的配置提取出来在父工程的 pom.xml 中定义。
何为聚合?
项目开发通常是分组分模块开发,每个模块开发完成要运行整个工程需要将每个模块聚合在一起运行,比如:dao、service、web 三个工程最终会打一个独立的war 运行。
3.步骤
创建父工程
首先我们先创建一个maven-parent 父模块。
在父工程中导入各个模块中都能用到的依赖的jar坐标,以及后续子模块的依赖坐标即可。
注意: 父工程中打包方式用pom。
创建子工程
1. 创建ssm_dao 子模块
在ssm_dao子工程中需要继承父模块,以及导入mybatis 和 spring 的整合相关依赖。
用到的mybatis 和 spring 相关配置文件及代码也在此工程中写。
此时,打包方式是 jar
2. 创建ssm_service 子工程
在ssm_service 模块的 pom 文件中需要继承父模块,ssm_service 依赖 ssm_dao 模块,同时添加业务层需要的坐标。
在ssm_service工程下编写业务相关的代码及其配置文件。
此时,打包方式是 jar
3.ssm_web 子 模块
ssm_web 模块的 pom文件中需要继承父模块,ssm_web 依赖 ssm_service 模块,和springmvc 的依赖。
此时,打包方式是 war
4.依赖范围对传递依赖的影响
是因为依赖会有依赖范围,依赖范围对传递依赖也有影响,例如有 A、B、C,A 依赖 B、B依赖 C,C可能是 A的传递依赖,如下图:
最左边一列为直接依赖,理解为 A 依赖 B 的范围,最顶层一行为传递依赖,理解为 B依赖 C 的范围,行与列的交叉即为 A传递依赖 C的范围。
举例 1:
比如 A 对 B 有 compile 依赖,B 对 C 有 runtime 依赖,那么根据表格所示 A 对 C 有runtime 依赖。
ssm_dao依赖 junit,scop为 test
ssm_service 依赖 ssm_dao.
查看下图红色框内所示传递依赖范围:
所以 ssm_dao工程所依赖的 junit 的 jar 没有加入到 ssm_service 工程。
举例 2:
如果修改 ssm_dao 工程依赖 junit 的 scop 为 compile,ssm_dao 工程所依赖的 junit的 jar 包会加入到 ssm_service 工程中,符合上边表格所示,查看下图红色框内所示:
如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客