20221106 Maven - 尚硅谷(1-8)

1. Maven 概述

Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供 构建依赖管理 支持的工具。

Maven 的作用:

  • Maven 作为依赖管理工具

  • Maven 作为构建管理工具

构建过程包含的主要的环节:

  • 清理:删除上一次构建的结果,为下一次构建做好准备

  • 编译:Java 源程序编译成 *.class 字节码文件

  • 测试:运行提前准备好的测试程序

  • 报告:针对刚才测试的结果生成一个全面的信息

  • 打包

    • Java工程:jar包

    • Web工程:war包

  • 安装:把一个 Maven 工程经过打包操作生成的 jar 包或 war 包存入 Maven 仓库

  • 部署

    • 部署 jar 包:把一个 jar 包部署到 Nexus 私服服务器上

    • 部署 war 包:借助相关 Maven 插件(例如 cargo),将 war 包部署到 Tomcat 服务器上

依赖管理中要解决的具体问题:

  • jar 包的下载:使用 Maven 之后,jar 包会从规范的远程仓库下载到本地

  • jar 包之间的依赖:通过依赖的传递性自动完成

  • jar 包之间的冲突:通过对依赖的配置进行调整,让某些jar包不会被导入

Maven 的工作机制

2. Maven 安装

Maven 官网

核心程序压缩包:apache-maven-3.8.6-bin.zip,解压到非中文、没有空格的目录

着重关注 Maven 的核心配置文件:conf/settings.xml

配置 Maven 核心程序

指定本地仓库

本地仓库默认值:用户家目录/.m2/repository

可以修改 conf/settings.xml 改变默认位置,本地仓库本身也需要使用一个非中文、没有空格的目录

<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>D:\maven-repository</localRepository>

配置阿里云的镜像仓库

参考 阿里云Maven指南

Maven下载jar包默认访问境外的中央仓库,而国外网站速度很慢。改成阿里云提供的镜像仓库,访问国内网站,可以让 Maven下载jar包的时候速度更快。

先注释原来的 mirror 标签配置

将下面 mirror 标签整体复制到 settings.xml 文件的 mirrors 标签的内部

<mirror>
    <id>aliyunmaven</id>
    <mirrorOf>*</mirrorOf>
    <name>阿里云公共仓库</name>
    <url>https://maven.aliyun.com/repository/public</url>
</mirror>rror>

配置 Maven 工程的基础 JDK 版本

配置 JDK 1.8 版本

修改配置的方式是:将 profile 标签整个复制到 settings.xml 文件的 profiles 标签内。

<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>

配置环境变量

检查 JAVA_HOME 配置是否正确

echo %JAVA_HOME%

java -version

配置 MAVEN_HOME

配置 PATH

%MAVEN_HOME%\bin

验证

mvn -v

3. 使用 Maven :命令行环境

Maven 中的坐标

使用三个『向量』在『Maven的仓库』中唯一的定位到一个『jar』包。

  • groupId:公司或组织域名的倒序,通常也会加上项目名称

    • 例如:com.atguigu.maven
  • artifactId:模块的名称,将来作为 Maven 工程的工程名

  • version:模块的版本号,根据自己的需要设定

    • 例如:SNAPSHOT 表示快照版本,正在迭代过程中,不稳定的版本

    • 例如:RELEASE 表示正式版本

坐标和仓库中 jar 包的存储路径之间的对应关系

<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>

对应位置:

Maven本地仓库根目录\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar

使用命令生成Maven工程

mvn archetype:generate

自动生成的 pom.xml 解读

<!-- 根标签,表示对当前工程进行配置、管理 -->
<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">
  <!-- 从 Maven 2 开始固定式 4.0.0 -->
  <!-- 代表当前 pom.xml 所采用的标签结构 -->
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.atguigu.maven</groupId>
  <artifactId>pro01-maven-java</artifactId>
  <version>1.0-SNAPSHOT</version>

  <!-- 当前Maven工程的打包方式,可选值有下面三种: -->
  <!-- jar:表示这个工程是一个Java工程 -->
  <!-- war:表示这个工程是一个Web工程 -->
  <!-- pom:表示这个工程是“管理其他工程”的工程 -->
  <packaging>jar</packaging>

  <name>pro01-maven-java</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Maven核心概念:POM

POM:Project Object Model,项目对象模型。和 POM 类似的是:DOM(Document Object Model),文档对象模型。它们都是模型化思想的具体体现。

POM 理念集中体现在 Maven 工程根目录下 pom.xml 这个配置文件中。所以这个 pom.xml 配置文件就是 Maven 工程的核心配置文件。其实学习 Maven 就是学这个文件怎么配置,各个配置有什么用。

Maven核心概念:约定的目录结构

目前开发领域的技术发展趋势就是:约定大于配置,配置大于编码

还有一个 target 目录专门存放构建操作输出的结果

Maven 的构建命令

清理
mvn clean
效果:删除 target 目录
编译
主程序编译:mvn compile
测试程序编译:mvn test-compile
主体程序编译结果存放的目录:target/classes
测试程序编译结果存放的目录:target/test-classes
测试
mvn test
测试的报告存放的目录:target/surefire-reports
打包
mvn package
打包的结果——jar 包,存放的目录:target
安装
mvn install

安装的效果是将本地构建过程中生成的 jar 包存入 Maven 本地仓库。这个 jar 包在 Maven 仓库中的路径是根据它的坐标生成的。

安装操作还会将 pom.xml 文件转换为 XXX.pom 文件一起存入本地仓库。所以我们在 Maven 的本地仓库中想看一个 jar 包原始的 pom.xml 文件时,查看对应 XXX.pom 文件即可,它们是名字发生了改变,本质上是同一个文件

创建 Maven 版的 Web 工程

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeVersion=1.4

查看生成的 pom.xml 文件

<packaging>war</packaging>

让 Web 工程依赖 Java 工程

<!-- 配置对Java工程pro01-maven-java的依赖 -->
<!-- 具体的配置方式:在dependency标签内使用坐标实现依赖 -->
<dependency>
    <groupId>com.atguigu.maven</groupId>
    <artifactId>pro01-maven-java</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

查看当前 Web 工程所依赖的 jar 包的列表

列表:mvn dependency:list
树形:mvn dependency:tree

依赖的范围 scope

标签的位置:dependencies/dependency/scope

标签的可选值:compile/test/provided/system/runtime/import

main目录(空间) test目录(空间) 开发过程(时间) 部署到服务器(时间)
compile 有效 有效 有效 有效
test 无效 有效 有效 无效
provided 有效 有效 有效 无效
  • compile:通常使用的第三方框架的 jar 包这样在项目实际运行时真正要用到的 jar 包都是以 compile 范围进行依赖的。比如 SSM 框架所需jar包。

  • test:测试过程中使用的 jar 包,以 test 范围依赖进来。比如 junit。

  • provided:在开发过程中需要用到的“服务器上的 jar 包”通常以 provided 范围依赖进来。比如 servletapi、jsp-api。而这个范围的 jar 包之所以不参与部署、不放进 war 包,就是避免和服务器上已有的同类jar 包产生冲突,同时减轻服务器的负担。说白了就是:“服务器上已经有了,你就别带啦!”

依赖的传递性

在 A 依赖 B,B 依赖 C 的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围。

  • B 依赖 C 时使用 compile 范围:可以传递

  • B 依赖 C 时使用 test 或 provided 范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以。

依赖的排除

配置依赖的排除其实就是阻止某些 jar 包的传递,避免 jar 包之间的冲突

<dependency>
    <groupId>com.atguigu.maven</groupId>
    <artifactId>pro01-maven-java</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>compile</scope>
    <!-- 使用excludes标签配置依赖的排除 -->
    <exclusions>
        <!-- 在exclude标签中配置一个具体的排除 -->
        <exclusion>
            <!-- 指定要排除的依赖的坐标(不需要写version) -->
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

继承

Maven工程之间,A 工程继承 B 工程

  • B 工程:父工程

  • A 工程:子工程

本质上是 A 工程的 pom.xml 中的配置继承了 B 工程中 pom.xml 的配置

在父工程中统一管理项目中的依赖信息,具体来说是管理依赖信息的版本。

它的背景是:

  • 对一个比较大型的项目进行了模块拆分。

  • 一个 project 下面,创建了很多个 module。

  • 每一个 module 都需要配置自己的依赖信息。

通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范、准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力。

操作

创建父工程
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>

<!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom -->
<packaging>pom</packaging>
创建模块工程

模块工程类似于 IDEA 中的 module,所以需要进入 pro03-maven-parent 工程的根目录,然后运行 mvn archetype:generate 命令来创建模块工程

查看被添加新内容的父工程 pom.xml

<modules>
    <module>pro04-maven-module</module>
    <module>pro05-maven-module</module>
    <module>pro06-maven-module</module>
</modules>

子工程的pom.xml

<!-- 使用parent标签指定当前工程的父工程 -->
<parent>
    <!-- 父工程的坐标 -->
    <groupId>com.atguigu.maven</groupId>
    <artifactId>pro03-maven-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>

<!-- 子工程的坐标 -->
<!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略 -->
<!-- <groupId>com.atguigu.maven</groupId> -->
<artifactId>pro04-maven-module</artifactId>
<!-- <version>1.0-SNAPSHOT</version> -->
在父工程中配置依赖的统一管理
<!-- 使用dependencyManagement标签配置对依赖的管理 -->
<!-- 被管理的依赖并没有真正被引入到工程 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.0.0.RELEASE</version>
        </dependency>
    </dependencies>
</dependencyManagement>

子工程中引用那些被父工程管理的依赖

<!-- 子工程引用父工程中的依赖信息时,可以把版本号去掉。 -->
<!-- 把版本号去掉就表示子工程中这个依赖的版本由父工程决定。 -->
<!-- 具体来说是由父工程的dependencyManagement来决定。 -->
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>
</dependencies>
在父工程中声明自定义属性
<!-- 通过自定义属性,统一指定Spring的版本 -->
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- 自定义标签,维护Spring版本数据 -->
    <atguigu.spring.version>4.3.6.RELEASE</atguigu.spring.version>
</properties>

在需要的地方使用 ${} 的形式来引用自定义的属性名:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${atguigu.spring.version}</version>
</dependency>

实际意义

编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间。为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下来。

如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。

聚合

使用一个“总工程”将各个“模块工程”汇集起来,作为一个整体对应完整的项目。

  • 项目:整体

  • 模块:部分

从继承关系角度来看:

  • 父工程

  • 子工程

从聚合关系角度来看:

  • 总工程

  • 模块工程

好处

  • 一键执行 Maven 命令:很多构建命令都可以在“总工程”中一键执行

    • 假设父模块E,模块A依赖B,B依赖C,先安装父模块E,然后是被依赖的模块C、B,最后是A
  • 配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然

配置

<modules>
    <module>pro04-maven-module</module>
    <module>pro05-maven-module</module>
    <module>pro06-maven-module</module>
</modules>

依赖循环问题

如果 A 工程依赖 B 工程,B 工程依赖 C 工程,C 工程又反过来依赖 A 工程,那么在执行构建操作时会报

下面的错误:

DANGER

[ERROR] [ERROR] The projects in the reactor contain a cyclic reference:

这个错误的含义是:循环引用。

4. 使用 Maven:IDEA 环境

讲解的是基础用法,平时用的太多了,略

5. 其他核心概念

生命周期

为了让构建过程自动化完成,Maven 设定了三个生命周期,生命周期中的每一个环节对应构建过程中的一个操作。

生命周期名称 作用 各个环节
Clean 清理操作相关 pre-clean
clean
post-clean
Site 生成站点相关 pre-site
site
post-site
deploy-site
Default 主要构建过程 validate
generate-sources
process-sources
generate-resources
process
resources 复制并处理资源文件,至目标目录,准备打包。
compile 编译项目 main 目录下的源代码。
process-classes
generate-test-sources
process-test
sources
generate-test-resources
process-test-resources 复制并处理资源文件,至目标测试目录。
test-compile 编译测试源代码。
process-test-classes test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。
prepare-package
package 接受编译好的代码,打包成可发布的格式,如JAR。
pre-integration-test
integration-test
post-integration-test
verify
install 将包安装至本地仓库,以让其它项目依赖。
deploy 将最终的包复制到远程的仓库, 以让其它开发人员共享;或者部署到服务器上运行(需借助插件,例如: cargo)。
  • 三个生命周期彼此是独立的。

  • 在任何一个生命周期内部,执行任何一个具体环节的操作,都是从本周期最初的位置开始执行,直到指定的地方。

插件

Maven 的核心程序仅仅负责宏观调度,不做具体工作。具体工作都是由 Maven 插件完成的。例如:编译就是由 maven-compiler-plugin-3.1.jar 插件来执行的

目标

一个插件可以对应多个目标,而每一个目标都和生命周期中的某一个环节对应。

Default 生命周期中有 compile 和 test-compile 两个和编译相关的环节,这两个环节对应 compile 和 test-compile 两个目标,而这两个目标都是由 maven-compiler-plugin-3.1.jar 插件来执行的。

仓库

  • 本地仓库:在当前电脑上,为电脑上所有 Maven 工程服务

  • 远程仓库:需要联网

  • 局域网:我们自己搭建的 Maven 私服,例如使用 Nexus 技术。

    • Internet

    • 中央仓库

      • 镜像仓库:内容和中央仓库保持一致,但是能够分担中央仓库的负载,同时让用户能够就近访问提高下载速度,例如:Nexus aliyun

建议:不要中央仓库和阿里云镜像混用,否则 jar 包来源不纯,彼此冲突。

6. 单一架构案例

Servlet+Thymeleaf 的一个示例,手搭框架

熟悉一下就好

7. SSM 整合伪分布式案例

Spring MVC+MyBatis+Thymeleaf

8. 微服务架构案例

Spring Cloud + Spring Cloud Alibaba

posted @ 2022-11-29 19:42  流星<。)#)))≦  阅读(38)  评论(0编辑  收藏  举报