轻松聊 Maven 的全面学习

一、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 文件夹NewDirectory
在这里插入图片描述

创建一个新的文件夹命名为 java
在这里插入图片描述
点击 OK 后,在新的文件夹 java 上右键Make Directory asSources 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 工程中,符合上边表格所示,查看下图红色框内所示:
在这里插入图片描述


如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客

猜你喜欢

转载自blog.csdn.net/weixin_45606067/article/details/107687843