day05[Maven]

第一章.Maven介绍与使用

1.为什么使用Maven

  1. 添加第三方jar包
  2. 处理jar包之间的依赖
  3. 处理jar包之间的冲突(最短路径者优先和先声明者优先)
  4. 获取第三方jar包
  5. 将项目拆分成多个工程模块
  6. 实现项目的分布式部署

2.Maven是什么?

2.1.自动化构建工具

  1. Maven是一款自动化构建工具,专注服务于java平台的项目构建和依赖管理

2.2.构建的概念

$01[Maven] - 图1

  1. /*构建就是以我们编写的Java代码、框架配置文件、国际化等其他资源文件、JSP页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。
  2. /

2.3.构建环节

  1. 清理:删除以前的编译结果,为重新编译做好准备。
  2. 编译:将Java源程序编译为字节码文件。
  3. 测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
  4. 报告:在每一次测试后以标准的格式记录和展示测试结果。
  5. 打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web工程对应war包
  6. 安装:在Maven环境下特指将打包的结果——jar包或war包安装到本地仓库中。
  7. 部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行

2.4.自动化构建

  1. /*这是阳光明媚的一天。托马斯向往常一样早早的来到了公司,冲好一杯咖啡,进入了自己的邮箱——很不幸,QA小组发来了一封邮件,报告了他昨天提交的模块的测试结果——有BUG。“好吧,反正也不是第一次”,托马斯摇摇头,进入IDE,运行自己的程序,编译、打包、部署到服务器上,然后按照邮件中的操作路径进行测试。“嗯,没错,这个地方确实有问题”,托马斯说道。于是托马斯开始尝试修复这个BUG,当他差不多有眉目的时候已经到了午饭时间。
  2. 下午继续工作。BUG很快被修正了,接着托马斯对模块重新进行了编译、打包、部署,测试之后确认没有问题了,回复了QA小组的邮件。
  3. 一天就这样过去了,明媚的阳光化作了美丽的晚霞,托马斯却觉得生活并不像晚霞那样美好啊。
  4. /

$01[Maven] - 图2

总结:Maven可以自动的从构建过程的起点一直执行到终点

$01[Maven] - 图3

2.5.Maven核心概念

  1. POM
  2. 约定的目录结构
  3. 坐标
  4. 依赖管理
  5. 仓库管理
  6. 生命周期
  7. 插件和目标
  8. 继承
  9. 聚合

3.Maven如何使用

3.1.安装Maven核心程序

  1. 配置Java_HOME
  2. 配置M2_HOME
  3. 配置path: %M2_HOME%\bin

验证maven是否安装成功

  1. mvn -v

$01[Maven] - 图4

3.2.Maven连网问题

  1. 配置本地仓库
  1. /*1.配置本地仓库
  2. Maven默认的本地仓库:~\.m2\repository目录 ~表示当前用户的家目录
  3. Maven的核心配置文件:E:\apache-maven-3.5.4\conf\settings.xml
  4. 设置方式:<localRepository>以及准备好的仓库位置</localRepository>
  5. /
  1. 设置阿里云镜像
  1. <mirror>
  2. <id>nexus-aliyun</id>
  3. <mirrorOf>central</mirrorOf>
  4. <name>Nexus aliyun</name>
  5. <url>http://maven.aliyun.com/nexus/content/groups/public</url>
  6. </mirror>

3.3.Maven打包插件

Maven本身的打包插件不负责将依赖的jar包一并打入到jar包中。

如果项目所依赖的jar包在服务器环境中提供了还好,如果服务器环境中没有提供,则比较悲惨,运行各种ClassNotFound….你们懂的!

因此需要一款能够将项目所依赖的jar包 一并打入到jar中的插件来解决这些问题

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <artifactId>maven-assembly-plugin</artifactId>
  5. <configuration>
  6. <descriptorRefs>
  7. <descriptorRef>jar-with-dependencies</descriptorRef>
  8. </descriptorRefs>
  9. <archive>
  10. <manifest>
  11. <!-- 指定主类 -->
  12. <mainClass>xxx.xxx.XXX</mainClass>
  13. </manifest>
  14. </archive>
  15. </configuration>
  16. <executions>
  17. <execution>
  18. <id>make-assembly</id>
  19. <phase>package</phase>
  20. <goals>
  21. <goal>single</goal>
  22. </goals>
  23. </execution>
  24. </executions>
  25. </plugin>
  26. </plugins>
  27. </build>

第二章.Maven的核心概念

1.核心概念

  1. POM
  2. 约定的目录结构
  3. 坐标
  4. 依赖
  5. 仓库
  6. 生命周期
  7. 插件和目标
  8. 继承
  9. 聚合

2.POM

Project Object Mode:项目对象模型,将Java工程的相关信息封装为对象作为便于操作和管理的模型.Maven工程的核心配置,可以说学习Maven就是学习pom.xml文件中的配置

3.约定的目录结构

现在JavaEE开发领域普遍认同一个概念:约定>配置>编码,意思就是能用配置解决的问题就不编码,能基于约定的就不进行配置,而Maven正是因为指定了特定文件保存的目录才能够对我们的Java工程进行自动化构建

4.坐标

  1. /*
  2. 1.几何中的坐标
  3. 在一个平面中使用x、y两个向量可以唯一的确定平面中的一个点。
  4. 在空间中使用x、y、z三个向量可以唯一的确定空间中的一个点。
  5. 2.Maven的坐标
  6. 使用如下三个向量在Maven的仓库中唯一的确定一个Maven工程
  7. groupId:公司或组织的域名倒序+当前项目名称
  8. artifactId:当前项目的模块名称
  9. version:当前模块的版本
  10. /
  1. <groupId>com.atguigu.maven</groupId>
  2. <artifactId>Hello</artifactId>
  3. <version>0.0.1-SNAPSHOT</version>

注意:我们自己的Maven工程必须执行安装操作才会进入仓库,安装的命令: mvn install

5.依赖管理

  1. /*
  2. 1.基本概念
  3. 当 A jar包需要用到 B jar包的类时,我们就说A对B有依赖,例如:Commons-fileupload-1.3jar依赖于Commons-io-2.0.1.jar
  4. 2.直接依赖和间接依赖
  5. 如果A依赖B,B依赖C,那么A->B和B->C都是直接依赖,而A->C是间接依赖
  6. /

5.1.依赖的范围

  1. /*
  2. 1.compile
  3. [1]main目录下的Java代码可以访问这个范围的依赖
  4. [2]test目录下的Java代码可以访问这个范围的依赖
  5. [3]部署到Tomcat服务器上运行时要放在WEB-INF的lib目录下
  6. 例如:对Hello的依赖。主程序、测试程序和服务器运行时都需要用到。
  7. 2.test
  8. [1]main目录下的Java代码不能访问这个范围的依赖
  9. [2]test目录下的Java代码可以访问这个范围的依赖
  10. [3]部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
  11. 例如:对junit的依赖。仅仅是测试程序部分需要。
  12. 3.provided
  13. [1]main目录下的Java代码可以访问这个范围的依赖
  14. [2]test目录下的Java代码可以访问这个范围的依赖
  15. [3]部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
  16. 4.其他:runtime,import,system
  17. /

$01[Maven] - 图5

5.2.依赖的传递性

当存在间接依赖的情况时,主工程对间接依赖的jar可以使用吗?这要看间接依赖的jar包引入时的依赖范围—只有依赖范围为compile时可以访问,例如:

$01[Maven] - 图6

5.3.依赖的原则:解决jar包冲突

  1. 路径最短者优先

$01[Maven] - 图7

  1. 路径相同时先声明者优先(这里声明的先后顺序指的是dependency标签配置的先后顺序)

$01[Maven] - 图8

5.4.依赖的排除

  1. /*
  2. 有的时候为了确保程序正确可以将有可能重复的间接依赖排除。请看如下的例子:
  3. 假设当前工程为MakeFriend,直接依赖OurFriends。
  4. OurFriends依赖commons-logging的1.1.1对于MakeFriend来说是间接依赖。
  5. 当前工程MakeFriend直接依赖commons-logging的1.1.2
  6. 加入exclusions配置后可以在依赖OurFriends的时候排除版本为1.1.1的commons-logging的间 接依赖
  7. /
  1. <dependency>
  2. <groupId>com.atguigu.maven</groupId>
  3. <artifactId>OurFriends</artifactId>
  4. <version>1.0-SNAPSHOT</version>
  5. <!--依赖排除-->
  6. <exclusions>
  7. <exclusion>
  8. <groupId>commons-logging</groupId>
  9. <artifactId>commons-logging</artifactId>
  10. </exclusion>
  11. </exclusions>
  12. </dependency>
  13. <dependency>
  14. <groupId>commons-logging</groupId>
  15. <artifactId>commons-logging</artifactId>
  16. <version>1.1.2</version>
  17. </dependency>

5.5统一管理目标jar包的版本

以对Spring的jar包依赖为例:Spring的每一个版本中都包含spring-context,springmvc等jar包。我们应该导入版本一致的Spring jar包,而不是使用4.0.0的spring-context的同时使用4.1.1的springmvc

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-context</artifactId>
  4. <version>4.0.0.RELEASE</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework</groupId>
  8. <artifactId>spring-webmvc</artifactId>
  9. <version>4.0.0.RELEASE</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework</groupId>
  13. <artifactId>spring-jdbc</artifactId>
  14. <version>4.0.0.RELEASE</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework</groupId>
  18. <artifactId>spring-orm</artifactId>
  19. <version>4.0.0.RELEASE</version>
  20. </dependency>

问题是如果我们想要将这些jar包的版本统一升级为4.1.1,是不是要手动一个个修改呢?显然,我们有统一配置的方式

  1. <!--统一管理当前模块的jar包的版本-->
  2. <properties>
  3. <spring.version>4.0.0.RELEASE</spring.version>
  4. </properties>
  5. ........
  6. <dependency>
  7. <groupId>org.springframework</groupId>
  8. <artifactId>spring-context</artifactId>
  9. <version>${spring.version}</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework</groupId>
  13. <artifactId>spring-webmvc</artifactId>
  14. <version>${spring.version}</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework</groupId>
  18. <artifactId>spring-jdbc</artifactId>
  19. <version>${spring.version}</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework</groupId>
  23. <artifactId>spring-orm</artifactId>
  24. <version>${spring.version}</version>
  25. </dependency>

6.仓库

  • 本地仓库:为当前本机电脑上的所有Maven工程服务
  • 远程仓库
  • 私服:架设在当前局域网环境下,为当前局域网范围内的所有Maven工程服务
  • 中央仓库: 架设在Internet上,为全世界所有Maven工程服务
  • 中央仓库的镜像:架设在各个大洲,为中央仓库分担流量,减轻中央仓库的压力,同时更快的响应用户请求
  • 仓库中的文件
  • Maven的插件
  • 我们自己开发的项目的模块
  • 第三方框架或工具的jar包(不管是什么样的jar包,在仓库中都是按照坐标生成目录结构,所以可以通过统一的方式查询和依赖)

7.生命周期

  1. /*
  2. 1.什么是maven的生命周期?
  3. Maven生命周期定义了各个构建环节的执行顺序,有了这个清单,Maven就可以自动化的执行构 建命令了。
  4. Maven有三套相互独立的生命周期,分别是:
  5. Clean Lifecycle在进行真正的构建之前进行一些清理工作。
  6. Default Lifecycle构建的核心部分,编译,测试,打包,安装,部署等等。
  7. Site Lifecycle生成项目报告,站点,发布站点。
  8. 再次强调一下它们是相互独立的,你可以仅仅调用clean来清理工作目录,仅仅调用site来生成站点。当然你也可以直接运行 mvn clean install site 运行所有这三套生命周期。
  9. 每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比如,运行mvn clean,这个clean是Clean生命周期的一个阶段。有Clean生命周期,也有clean阶段。
  10. /

default生命周期(常用阶段)

  • compile 编译项目的源代码
  • test-compile 编译测试源代码
  • test 使用合适的单元测试框架运行测试,这些测试代码不会被打包和部署
  • package 接收编译好的代码,打包成可发布的格式
  • install 将包安装至本地仓库,以让其他项目依赖

运行任何一个阶段的时候,它前面的所有阶段都会被运行

8.插件和目标

  • Maven的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
  • 每个插件都能实现多个功能,每个功能就是一个插件目标
  • Maven的生命周期与插件目标相互绑定,以完成某个具体的构建任务

例如: compile就是插件maven-compiler-plugin的一个功能;pre-clean是插件maven-clean-plugin的一个目标。

9.继承

9.1.为什么需要继承机制

由于非compile范围的依赖信息是不能在“依赖链”中传递的,所以有需要的工程只能单独配置。例如:

$01[Maven] - 图9

9.2.创建父工程

父工程的打包方式为pom

  1. <groupId>com.atguigu.maven</groupId>
  2. <artifactId>Parent</artifactId>
  3. <packaging>pom</packaging>
  4. <version>1.0-SNAPSHOT</version>

父工程只需要保留pom.xml文件即可

9.3.创建子工程

  1. <!--继承-->
  2. <parent>
  3. <groupId>com.atguigu.maven</groupId>
  4. <artifactId>Parent</artifactId>
  5. <version>1.0-SNAPSHOT</version>
  6. <!--指定从当前pom.xml文件出发寻找父工程的pom.xml文件的相对路径-->
  7. <relativePath>../Parent/pom.xml</relativePath>
  8. </parent>

此时如果子工程的groupid和version如果和父工程重复则可以删除

9.4.在父工程中管理依赖

  1. 将Parent项目中的dependencies标签,用dependencyManagement标签括起来
  1. <!--依赖管理-->
  2. <dependencyManagement>
  3. <dependencies>
  4. <dependency>
  5. <groupId>junit</groupId>
  6. <artifactId>junit</artifactId>
  7. <version>4.0</version>
  8. <scope>test</scope>
  9. </dependency>
  10. </dependencies>
  11. </dependencyManagement>
  1. 在子项目中重新指定需要的依赖,删除范围和版本号
  1. <dependency>
  2. <groupId>junit</groupId>
  3. <artifactId>junit</artifactId>
  4. </dependency>

10.聚合

10.1.为什么需要聚合?

将多个工程拆分为模块后,需要手动逐个安装到仓库后依赖才能够生效。修改源码后也需要逐个手动进行clean操作。而使用了聚合之后就可以批量进行Maven工程的安装、清理工作。

10.2.如何配置聚合?

在总的聚合工程中使用modules/module标签组合,指定模块工程的相对路径即可

  1. <!--聚合-->
  2. <modules>
  3. <module>../MakeFriend</module>
  4. <module>../OurFriends</module>
  5. <module>../HelloFriend</module>
  6. <module>../Hello</module>
  7. </modules>

Maven可以根据各个模块的继承和依赖关系自动选择安装的顺序

第三章.Maven酷站

我们可以到http://mvnrepository.com/搜索需要的jar包的依赖信息

http://search.maven.org/

$01[Maven] - 图10