Maven

        一、什么是maven

             maven是apache软件基金组织维护的一款专门为java项目提供构建和依赖管理支持的工具

             1)构建
                java项目开发过程中,构建指的是使用原材料生产产品的过程。
                原材料:java源代码、基于HTML的Thymelef文件、图片、配置文件
                产品:一个可以在服务器上运行的项目

             2)构建过程包含的主要的环节:
                清理:删除上一次构建的结果,为下一次构建做好准备,所有的构建的结果都会放在target目录里面,清理就是把target给删除
                编译:java源程序编译成*.class字节码文件
                测试:运行提前准备好的测试程序
                报告:针对刚才测试的结果生成一个全面的信息
                打包:java工程:jar包  web工程:war包
                安装:把一个maven工程经过打包操作生成的jar包或war包安装到maven仓库
                部署:jar包:把一个jar包部署到Nexus私服服务器上
                          war包:借助相关maven插件(例如cargo),将war包部署到tomcat服务器上

                3)依赖
                如果A工程里面用到B工程的类、接口,配置文件等等这样的资源,那么我们就可以说A依赖B。
                依赖管理中要解决的具体问题:
                jar包的下载:使用maven之后,jar包会从规范的远程仓库下载到本地
                jar包之间的依赖:通过依赖的传递自动完成
                jar包之间的冲突:通过对依赖的配置进行调整,让某些jar包不会被导入

                4)安装、解压、配置setting文件
                安装、解压略
                配置setting文件:
                指定maven仓库:

<!-- 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 下载 jar 包默认访问境外的中央仓库,而国外网站速度很慢。改成阿里云提供的镜像仓库,访问国内网站,可以让 Maven 下载 jar 包的时候速度更快。配置的方式是:

### ①将原有的例子配置注释掉

<!-- <mirror>
  <id>maven-default-http-blocker</id>
  <mirrorOf>external:http:*</mirrorOf>
  <name>Pseudo repository to mirror external repositories initially using HTTP.</name>
  <url>http://0.0.0.0/</url>
  <blocked>true</blocked>
</mirror> -->

### ②加入我们的配置

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

  <mirror>
    <id>nexus-aliyun</id>
    <mirrorOf>central</mirrorOf>
    <name>Nexus aliyun</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
  </mirror>

 配置 Maven 工程的基础 JDK 版本:

如果按照默认配置运行,Java 工程使用的默认 JDK 版本是 1.5,而我们熟悉和常用的是 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>

        5)配置环境变量
         1、检查 JAVA_HOME 配置是否正确

Maven 是一个用 Java 语言开发的程序,它必须基于 JDK 来运行,需要通过 JAVA_HOME 来找到 JDK 的安装位置。

可以使用下面的命令验证:

C:\Users\Administrator>echo %JAVA_HOME%
D:\software\Java

C:\Users\Administrator>java -version
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.141-b15, mixed mode)

## 2、配置 MAVEN_HOME

## 3、配置PATH

## 4、验证

C:\Users\Administrator>mvn -v
Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)
Maven home: D:\software\apache-maven-3.8.4
Java version: 1.8.0_141, vendor: Oracle Corporation, runtime: D:\software\Java\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"


        二、Maven核心概念

                1、坐标
                数学中的坐标:xyz可以确定一个空间中的位置。
                maven中的坐标:也是用三个向量在maven的仓库中定位到一个jar包
                 · groupId:公司或组织的id
                 ` artifacid:一个项目或者是项目中的一个模块的id
                    version: 版本号
                 三个向量的取值方式:
                     groupId:公司或组织域名的倒序,通常也会加上项目名称
                          例如: com.alibaba.nacos
                     artifacId:模块名称,将来作为Maven工程的工程名
                     version:模块的版本号,根据自己的需求设定
                        例如;SNAPSHOT 表示快照版本,正在迭代过程中,不稳定的版本
                        例如:RELFASE 表示正式版本
                2、坐标和仓库中jar包的存储路径之间的对应关系
                       例如:

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

                        上面坐标对应的jar包在Maven本地仓库中的位置:
                MAVEN本地仓库目录:\java\servlet\servlet-api\2.5\servlet-api.jar

                3、创建目录为后面的操作的工作空间
                1)我们有三个目录分别是:
                        Maven核心程序:中军大营
                        Maven本地仓库:兵营
                        本地工作空间:战场
                2)使用命令生成Maven工程:
                        mvn archetype:generate;
                

                  3)自动生成的pom.xml解读:
                        pom.xml是maven生成的核心配置文件, 所有配置都是在pom.xml中做的,实际上学习maven怎么用就是在学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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>redis-demo1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>redis-demo1</name>
    <description>redis-demo1</description>
    <properties>
        <java.version>1.8</java.version>
        <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

        1)根标签:<project></project>表示对当前工程进行配置、管理
         2)<modelVersion>4.0.0</modelVersion> :
                        modelVersion 标签:从maven2开始就是固定的4.0.0,代表当前 pom.xml 所采用的结构,不用管。
        3)        <groupId>org.springframework.boot</groupId>
                     <artifactId>spring-boot-starter-parent</artifactId>
                     <version>2.7.9</version>:
                坐标信息,group 代表 公司或组织开发下的某一个项目,artifactid代表项目下的某一个模块,version:坐标向量之一,代表当前模块的版本
        4)<packaging>jar</packaging>:打包方式,取值jar,生成jar包说明是一个java工程,取值war,打war包,说明这是一个web工程,取值pom说明这个工程是用来管理其他工程的工程。
        5)name:就是当前目录的名字
             url:官网的地址
        6)</properties>可以用来定义属性值

    <properties>
        <java.version>1.8</java.version>
        <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
    </properties>

         里面的标签是属性名,里面的是属性值,属性名可以是maven提供的,也可以是自定义的属性
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>在构建过程中读取源码时使用的字符集
        7)<dependencies> 配置具体依赖信息
        8)<parent> 标签给当前工程配置父工程,通过找到父工程的坐标找到父工程。
              子工程的groupId如果和父工程一样,则可以省略,子工程的version如果和父工程一样则可以省略。省略groupId和version后,子工程自己的坐标只保留artfactID.

     

        4、Maven核心概念:POM
        1)含义:POM:Project Object Model :项目对象模型 和POM类似的是:DOM Document Object Model,文档对象模型,他们都是模型化思想的具体体现。
        2)模型化思想:略
        3)对应的配置文件,pom.xml配置文件就是maven工程的核心配置文件,其实就是学这个文件怎么配,各个配置有什么 用
        4)Maven核心概念:约定的目录结构:
        

                意义: Maven为了让构建过程尽可能自动化完成,所以必须约定目录结构,因为要到指定文件目录做指定的事情
                 约定大于配置,配置大于编码,约定就是默认的配置。

                5、Maven的构建命令
                1)maven clean:删除target目录
                2)mvn complie:主程序编译, 主体程序编译结果存放的目录:terget/classes
                     mvn test-compile : 测试程序编译,测试程序编译结果存放的目录:target/test-classes
                3)  maven test :测试操作,测试test包中的程序,测试的报告存放在目录:target/surefire-reports
                4)mvn package:打包操作,打包的结果-jar包,存放的目录:target
                5)mvn install:暗转操作,安装的效果是将本地构建过程中生成的jar包存入Maven本地仓库,这个jar包在maven仓库中的路径是根据它的坐标生成的。,另外,安装操作还会将pom.xml文件转换为xxx.pom文件一起存入本地仓库,所以我们在maven的本地仓库中想看一个jar包原始的pom.xml文件时,查看对应xxx.pom文件,即可,他们的名字发生了改变,本质上是同一个文件。
                6)mvn dependency:tree,查看依赖树形结构
                

                 6、依赖范围
                1)依赖的标签的位置:dependence/dependency/scope
                2)标签的可选值:compile、test、provided、system、runtime、import

                compile和test对比:

main目录(空间)test目录(空间)开发过程(时间)部署到服务器(时间)
compile有效有效有效有效
test无效有效有效无效
provided有效有效有效无效
            <dependency>
                <groupId>com.aaa</groupId>
                <artifactId>aaa-commons</artifactId>
                <version>1.7.4</version>
                <scope>import</scope>
            </dependency>

                标签范围就是《scope》标签中的指定的属性。
                百分之99都是compile范围的,也就是主体功能要用到的。compile也是默认值
                provided范围引入的依赖,就是我们服务器tomcat上面已经提供了,提供了就不用带了,如果非要带就会有可能有冲突。例如servlet相关依赖。
                结论:
                compile:通常使用的第三方框架的jar包这样在项目实际运行时真正要用到的jar包都是以compile范围进行依赖的,比如ssm框架所需要的jar包
                test:测试过程中使用的jar包,以test范围依赖进来,比如junit
                provided:在开发过程中需要用到服务器上的jar包,通常以proveded范围依赖进来,比如servlet.api,jsp.api。而这个范围的jar包之所以不参与部署,不放进war包,就是避免和服务器上已有的同类jar包产生冲突同时减轻服务器的负担,说白了就是服务器上已经有了,就不需要带了。

                7、依赖的传递
                1)传递的原则:
                      在A依赖B,B依赖C的前提下,C是否能够传递A,取决于B依赖C时使用的依赖范围。B依赖C时使用compile范围,可以传递,B依赖C时使用test或provided范围,不能传递,所以需要这样的jar包时,就必须在需要的地方明确配置依赖才可以。
                       

                8、依赖的排除
                1)概念:
                      当A依赖B,B依赖C而且C可以传递到A的时候,A不想要C,需要在A里面把C排除掉,而在这种情况都是为了避免jar包之间的冲突。
                2)配置方式

            <dependency>
                <groupId>com.aaa</groupId>
                <artifactId>aaa-commons</artifactId>
                <version>1.7.4</version>
                <scope>compile</scope>
                <!-- 使用exclusions标签配置依赖的排除 -->
                <exclusions>
                    <!-- 在exclusionz标签中配置一个具体的排除 -->
                    <exclusion>
                        <!-- 指定要排除的依赖的坐标 不需要写version) -->
                        <groupId>com.limai</groupId>
                        <artifactId>common-mail</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>

                9、继承
                1)概念:Maven工程之间:A工程继承B工程,B工程父工程、A工程子工程
                      本质上时A工程的pom.xml中配置继承了B工程中的pom.xml的配置
                2)作用:在父工程中统一管理项目的依赖信息,具体来说是管理依赖信息的版本
                      背景:对一个比较大型的项目进行了模块拆分,一个project下面,创建了很多个module,每一个moudle都需要配置自己的依赖信息。
                      背后的需求是:
                       在每一个module中各自维护各自的依赖信息很容易发生出入,不易统一管理,使用同一个框架内的不同jar包,他们应该是同一个版本,所以整个项目中使用的框架版本需要统一,
                        使用框架是所需要的jar包组合(或者说依赖信息组合),需要经过长期搜索和反复调试,最终确定一个可用组合,这个耗费很大精力总结出来的方案不应该在新的项目中重新搜索。
                   打包方式为pom的Maven工程能够管理其他Maven工程,打包方式为pom的Maven工程中不写业务代码,它是专门管理其他Maven工程的工程。
                 
                3)在父工程中配置依赖的统一管理:
                    使用dependencyManagement标签配置对依赖的管理。
                    被管理的依赖并没有真正被引入,即使在父工程配置了对依赖的管理,子工程需要使用具体哪一个依赖还是要明确配置。只不过不用谢版本号了。但是还是要明确依赖

    <dependencyManagement>
        <dependencies>
            <!-- 核心依赖 -->
            <!--spring boot-->
            <dependency>
                <groupId>com.aaa</groupId>
                <artifactId>limai-aaa</artifactId>
                <version>1.7.4</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

                对于已经在父工程进行了管理的依赖,子工程中引用时间可以不写version,不写的话子工程就采纳的是复工陈管理的版本,如果没有省略且跟父工程管理的版本不一致,那么这里子工程配置的版本会覆盖父工程管理的版本并最终采纳,。
                4)我们的版本号,可以在properties标签中自定义配置,然后使用$大括号引入对应的标签。类似于下面这种。

 <properties>
        <maven.build.timestamp.format>yyyyMMdd-HHmm</maven.build.timestamp.format>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
        <dockerfile-maven-plugin.version>1.4.10</dockerfile-maven-plugin.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven-source-plugin.version>3.2.1</maven-source-plugin.version>
    </properties>
 <dependencyManagement>
        <dependencies>
            <!-- 核心依赖 -->
            <!--spring boot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-validation</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>

            <!--spring cloud-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


            <!--hutool-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-bom</artifactId>
                <version>${hutool.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--spring cloud alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.nacos</groupId>
                <artifactId>nacos-client</artifactId>
                <version>${nacos.version}</version>
            </dependency>
            <dependency>
                <groupId>io.seata</groupId>
                <artifactId>seata-spring-boot-starter</artifactId>
                <version>${seata.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
                <version>${gateway.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jdbc</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>


        </dependencies>

                 10、聚合
                  就是在父工程种用moudle将各个模块组合起来:

    <modules>
        <module>im-aaa</module>
        <module>im-bbb</module>
        <module>im-ccc</module>
        <module>im-gateway</module>
        <module>im-ddd</module>

    </modules>

                好处:
                     1)一键执行maven命令;很多构建命令都可以在总工程种一键执行:
                        已mvn install 命令为例:maven要求有父工程是先安装父工程,有依赖的工程时,先安装被依赖的工程。我们自己考虑这些规则会很麻烦,但是工程聚合之后,在总工程执行mvn install 可以一键完成安装,而且会自动按照正确的顺序执行。
                        配置聚合之后,各个模块会在总工程种战死一个列表,让项目一目了然。

                10)idea种执行maven命令行
                        mvn clean intall -Dmaven.test.skip=true ,表示跳过测试,
                        -D 表示后面要附加命令的参数,和后面的参数是紧挨着的,中间没有其他任何字符,maven.test.skip=true 表示在执行命令的过程中跳过测试

                右击pom文件,点击Open in Termina,可以在终端中使用命令行运行maven命令。 

                 11、maven的生命周期
                  为什么要定义生命周期的概念,根本目的还是提高我们构建过程的自动化程度,因为每个生命周期会有好多个环节,不管是从生命周期的哪一个环节下的命令,他都是从最开始的生命周期开始执行的,加入说生命周期有5个环节,你下的命令是5,他会从1开始把前面的都执行了,你下的命令是3,他就从1开始执行到3。也就是说你下达任何一个环节对应的命令,他前面的操作都不用你操心,他都会替你去做。
                  1)三个生命周期:

生命周期名称作用各个环节
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)。

                  clean就是我们用的mvn clean;
                  site就是生成站点,他会把我们整个maven项目,会把项目的介绍、开发人员、我们所依赖的信息全部都抽取出来,生成一组静态页面,这一组静态页面已经可以构成一个对我们项目做简要说明的站点了。
 

                12、插件和目标
                1)插件:
                  maven的核心程序仅仅负责宏观调度,不做具体工作,具体工作都是由maven插件完成的,例如:编译就是由 maven-compiler-plugin-3.1.jar插件来执行的。也就是说maven核心程序是下达命令的,具体干活是插件来干的。一个插件就是一个具体的jar包
                2)目标:
                   目标的意思就是插件的功能,一个目标就是插件的一个功能,比如说maven-compiler-plugin-3.1.jar这个插件,他就是具体来执行编译操作的。编译操作不管能编译我们的主程序,也可以编译测试程序。这就他们两个不同的目标

                13、仓库
                 1)本地仓库:在当前电脑上,为电脑上所有maven工程服务,
                  2)  远程仓库:需要联网
                                  局域网:我们自己搭建的maven私服,例如使用Nexus技术
                                  Internet:
                                          中央仓库:内容和中央仓库保持一致,但是能够分担中央仓库的负载,同时让用户就近访问提高下载速度,例如:Nexus.aliyun.
                建议:不要中央仓库和阿里云镜像昏庸,否则jar包来源不纯,彼此冲突。

                三、Maven的完整功能
                maven是一款构建管理和依赖管理的工具,但事实上这只是Maven的一部分功能,Maven本身的产品定位是一款项目管理工具。
                从项目管理的角度来看。Maven提供了如下功能:
                1)项目对象模型(POM):将整个项目本身抽象,封装为应用程序的一个对象,以便于管理和操作。
                2)全局性构建逻辑重用:Maven对整个构建过程进行封装之后,程序员只需要指定配置信息即可完成构建,让构建过程从Ant的编程式升级到了Maven的声明式。
                3)构建的标准集合:在Maven提供的标准框架体系内,所有的构建都可以按照统一的规范生成和使用。
                 4)构建关系的定义:Maven定义了构建之间的三种基本关系,让大型应用系统可以使用Maven来进行管理。
                  · 继承关系:通过从上到下的继承关系,将各个构建中的重复信息提取到夫构建中统一管理
                  · 聚合关系:将多个构建聚合为一个整体,便于统一操作
                  ·  依赖关系:Maven定义了依赖的范围,依赖的传递、依赖的排除、版本仲裁机制等一系列规范和标准,让大型项目可以有序容纳数百甚至更多依赖。
                5)插件目标系统:Maven核心程序定义抽象的生命周期,然后将插件的目标绑定到生命周期中的特定阶段,实现了标准和具体实现耦合,让Maven程序极具扩展性
                 6)项目描述信息和维护:我们不仅可以在Pom在声明项目描述信息,更可以将整个项目相关信息收集起来生成HTML页面组成一个可以直接访问的站点。这些项目描述信息包括:
                       · 公司或组织信息
                       · 项目许可证
                       · 开发成员信息
                       · issue 管理信息
                       · SCM信息

        POM的四个层次:
             1)超级POM:
                Maven在构建过程中有很多默认的设定,例如:源文件存放的目录、测试源文件存放的目录、构建数据目录等等、但是其实这些要素也都是被Maven定义过的,定义的位置就是:超级POM. 所以我们自己的POM即使没有明确指定一个父工程(父POM),其实也默认继承了超级POM,就好比一个java类继承了Object类。
             2)父POM 
                 和java类一样,POM之间其实也是单继承的。如果我们给一个POM指定了父POM,那么继承关系如下图:
               

          3)有效pom
               有效pom,它的概念是这样的:在pom的继承关系中,子pom可以覆盖父pom中的配置;如果子pom没有覆盖,那么父pom中的配置将会被继承。按照这个规则,继承关系中的所有pom叠加到一起,就得到了一个最终生效的pom,显然maven实际运行过程中,执行构建操作就是按照这个最终生效的POM来运行,这个最终生效的POM就是有效POM.

        属性的声明与引用:
       

第三节 属性的声明与引用

#1、help 插件的各个目标

官网说明地址:https://maven.apache.org/plugins/maven-help-plugin

目标说明
help:active-profiles列出当前已激活的 profile
help:all-profiles列出当前工程所有可用 profile
help:describe描述一个插件和/或 Mojo 的属性
help:effective-pom以 XML 格式展示有效 POM
help:effective-settings为当前工程以 XML 格式展示计算得到的 settings 配置
help:evaluate计算用户在交互模式下给出的 Maven 表达式
help:system显示平台详细信息列表,如系统属性和环境变量

#2、使用 help:evaluate 查看属性值

①定义属性

<properties>
    <com.atguigu.hello>good morning maven</com.atguigu.hello>
</properties>

#②运行命令

③运行结果

images

#3、通过 Maven 访问系统属性

#① Java 系统属性一览

[1] Java 代码
Properties properties = System.getProperties();
Set<Object> propNameSet = properties.keySet();
for (Object propName : propNameSet) {
    String propValue = properties.getProperty((String) propName);
    System.out.println(propName + " = " + propValue);
}
#[2]运行结果

java.runtime.name = Java(TM) SE Runtime Environment
sun.boot.library.path = D:\software\Java\jre\bin
java.vm.version = 25.141-b15
java.vm.vendor = Oracle Corporation
java.vendor.url = http://java.oracle.com/
path.separator = ;
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg = sun.io
user.country = CN
user.script =
sun.java.launcher = SUN_STANDARD
sun.os.patch.level =
java.vm.specification.name = Java Virtual Machine Specification
user.dir = D:\idea2019workspace\atguigu-maven-test-prepare
java.runtime.version = 1.8.0_141-b15
java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs = D:\software\Java\jre\lib\endorsed
os.arch = amd64
java.io.tmpdir = C:\Users\ADMINI~1\AppData\Local\Temp\
line.separator =
java.vm.specification.vendor = Oracle Corporation
user.variant =
os.name = Windows 10
sun.jnu.encoding = GBK
java.library.path = D:\software\Java\bin;C:\WINDOWS\Sun\Java\bin;C:\WIN……
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 10.0
user.home = C:\Users\Administrator
user.timezone =
java.awt.printerjob = sun.awt.windows.WPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
java.class.path = D:\software\Java\jre\lib\charsets.jar;D:\softw……
user.name = Administrator
java.vm.specification.version = 1.8
sun.java.command = com.atguigu.maven.MyTest
java.home = D:\software\Java\jre
sun.arch.data.model = 64
user.language = zh
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.windows.WToolkit
java.vm.info = mixed mode
java.version = 1.8.0_141
java.ext.dirs = D:\software\Java\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
sun.boot.class.path = D:\software\Java\jre\lib\resources.jar;D:\sof……
java.vendor = Oracle Corporation
file.separator = \
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.desktop = windows
sun.cpu.isalist = amd64

②使用 Maven 访问系统属性

images

#4、访问系统环境变量

${env.系统环境变量名}

images

#5、访问 project 属性

#①含义

使用表达式 ${project.xxx} 可以访问当前 POM 中的元素值。

#②访问一级标签

${project.标签名}

images

#③访问子标签

${project.标签名.子标签名}

images

#④访问列表标签

${project.标签名[下标]}

images

#6、访问 settings 全局配置

${settings.标签名} 可以访问 settings.xml 中配置的元素值。

images

#7、用途

  • 在当前 pom.xml 文件中引用属性
  • 资源过滤功能:在非 Maven 配置文件中引用属性,由 Maven 在处理资源时将引用属性的表达式替换为属性值

        Build标签详解:
        在实际使用Maven的过程中,我们发现build标签有时候有,有时候没,其实通过有效POM我们能过够看到,build标签的相关配置其实一致都在,只是我们需要定制构建过程的时候才会通过配置build标签覆盖默认值或补充配置,可以通过打印有效pom来看到。 
        所以本质上来说,我们配置的build都是对超级pom配置的叠加,那我们又为什么要在默认配置的基础上叠加呢?很简单,在默认配置无法满足需求的时候定制构建过程。

        build标签组成:
        1)定义约定的目录结构
             参考示例中的如下部分:

<sourceDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\src\main\java</sourceDirectory>
<scriptSourceDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\src\main\scripts</scriptSourceDirectory>
<testSourceDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\src\test\java</testSourceDirectory>
<outputDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\target\classes</outputDirectory>
<testOutputDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\target\test-classes</testOutputDirectory>
<resources>
    <resource>
        <directory>D:\idea2019workspace\atguigu-maven-test-prepare\src\main\resources</directory>
    </resource>
</resources>
<testResources>
    <testResource>
        <directory>D:\idea2019workspace\atguigu-maven-test-prepare\src\test\resources</directory>
    </testResource>
</testResources>
<directory>D:\idea2019workspace\atguigu-maven-test-prepare\target</directory>

我们能看到各个目录的作用如下:

目录名作用
sourceDirectory主体源程序存放目录
scriptSourceDirectory脚本源程序存放目录
testSourceDirectory测试源程序存放目录
outputDirectory主体源程序编译结果输出目录
testOutputDirectory测试源程序编译结果输出目录
resources主体资源文件存放目录
testResources测试资源文件存放目录
directory构建结果输出目录

       

 2)备用插件管理
        pluginManagement 标签存放着几个极少用到的插件:

  • maven-antrun-plugin
  • maven-assembly-plugin
  • maven-dependency-plugin
  • maven-release-plugin

通过 pluginManagement 标签管理起来的插件就像 dependencyManagement 一样,子工程使用时可以省略版本号,起到在父工程中统一管理版本的效果。情看下面例子:

  • 被 spring-boot-dependencies 管理的插件信息:
<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<version>2.6.2</version>
</plugin>
  • 子工程使用的插件信息:
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

#③生命周期插件
 

plugins 标签存放的是默认生命周期中实际会用到的插件,这些插件想必大家都不陌生,所以抛开插件本身不谈,我们来看看 plugin 标签的结构:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <executions>
        <execution>
            <id>default-compile</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
        <execution>
            <id>default-testCompile</id>
            <phase>test-compile</phase>
            <goals>
                <goal>testCompile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

         1)坐标部分:
             artfacid 和 version 标签定义了插件的坐标,作为Maven的自带插件这里省略了groupId

          2)执行部分:
             exections标签内可以配置多个execution标签,execution标签内:
             id:指定唯一标识
             phase:关联生命周期阶段
             goals/goal:关联指定生命周期的目标
            一个插件可以有很多个目标,goals里面可以有很多goal,就表示关联这一个生命周期,可以给他配置很多个关联的目标。就是说当我们运行到phase对应的声明周期的时候,在goals里面如果指定很多个goal的话,那么就可以来执行我们这里面好多个目标。大部分情况下只配了一个。

              另外插件目标的执行过程可以进行配置,例如maven-site-plugin插件的site目标:

<execution>
    <id>default-site</id>
    <phase>site</phase>
    <goals>
        <goal>site</goal>
    </goals>
    <configuration>
        <outputDirectory>D:\idea2019workspace\atguigu-maven-test-prepare\target\site</outputDirectory>
        <reportPlugins>
            <reportPlugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-project-info-reports-plugin</artifactId>
            </reportPlugin>
        </reportPlugins>
    </configuration>
</execution>

           configuration标签内进行配置时使用的时标签时插件本身定义的,就以maven-site-plugin插件为例,它的核心类是org.apache.maven.plugin.site.render.SiteMoJo,在这个类中我们看到了outputDirectory属性。
        

SiteMojo 的父类是:AbstractSiteRenderingMojo,在父类中我们看到 reportPlugins 属性:

每个插件能做那些设置都是哥哥插件自己规定的,无法一概而论。

         典型应用:指定jdk版本

#①提出问题

前面我们在 settings.xml 中配置了 JDK 版本,那么将来把 Maven 工程部署都服务器上,脱离了 settings.xml 配置,如何保证程序正常运行呢?思路就是我们直接把 JDK 版本信息告诉负责编译操作的 maven-compiler-plugin 插件,让它在构建过程中,按照我们指定的信息工作。

②暂时取消 settings.xml 配置

为了测试对 maven-compiler-plugin 插件进行配置的效果,我们暂时取消 settings.xml 中的 profile 配置。

<!-- 配置Maven工程的默认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> -->

③编写源文件代码

很明显这里用到了 Lambda 表达式,这是 JDK 1.8 才支持的语法。

package com.atguigu.maven;

public class Hello {

    public void hello() {
        new Thread(()->{
            System.out.println("thread ...");
        }).start();
    }

}

此时我们执行编译命令:

images

#④配置构建过程
 

<!-- build 标签:意思是告诉 Maven,你的构建行为,我要开始定制了! -->
<build>
    <!-- plugins 标签:Maven 你给我听好了,你给我构建的时候要用到这些插件! -->
    <plugins>
        <!-- plugin 标签:这是我要指定的一个具体的插件 -->
        <plugin>
            <!-- 插件的坐标。此处引用的 maven-compiler-plugin 插件不是第三方的,是一个 Maven 自带的插件。 -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            
            <!-- configuration 标签:配置 maven-compiler-plugin 插件 -->
            <configuration>
                <!-- 具体配置信息会因为插件不同、需求不同而有所差异 -->
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

⑤再次执行编译命令

images

#⑥两种配置方式比较

  • settings.xml 中配置:仅在本地生效,如果脱离当前 settings.xml 能够覆盖的范围,则无法生效。
  • 在当前 Maven 工程 pom.xml 中配置:无论在哪个环境执行编译等构建操作都有效。

⑦补充说明

#[1]source 标签含义

查看 Maven 官网页面 (opens new window),我们找到 source 标签的介绍:

翻译过来就是:调用 Java 编译器命令时传入的 -source 参数。那对编译器来说,-source 参数是啥意思呢?

images

『提供与指定发行版的源兼容性』这句话我的理解是:

  • 我们写代码是按 JDK 1.8 写的——这就是『源兼容性』里的『源』。
  • 指定发行版就是我们指定的 JDK 1.8。
  • 『兼容性』是谁和谁兼容呢?现在源代码是既定的,所以就是要求编译器使用指定的 JDK 版本来兼容我们的源代码。

另外我们还看到:

这个功能还可以通过在 properties 标签中配置 maven.compiler.source 属性来实现。所以我们也经常会看到类似这样的配置:

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
[2]target 标签含义

翻译过来就是:调用 Java 编译器命令时传入的 -target 参数。那对编译器来说,-target 参数是啥意思呢?

images

『生成特定 VM 版本的类文件』这句话我的理解是:

  • VM 指 JVM
  • 类文件指 *.class 字节码文件
  • 整体意思就是源文件编译后,生成的 *.class 字节码文件要符合指定的 JVM 版本

4、典型应用:SpringBoot 定制化打包

#①需求

很显然 spring-boot-maven-plugin 并不是 Maven 自带的插件,而是 SpringBoot 提供的,用来改变 Maven 默认的构建行为。具体来说是改变打包的行为。默认情况下 Maven 调用 maven-jar-plugin 插件的 jar 目标,生成普通的 jar 包。

普通 jar 包没法使用 java -jar xxx.jar 这样的命令来启动、运行,但是 SpringBoot 的设计理念就是每一个『微服务』导出为一个 jar 包,这个 jar 包可以使用 java -jar xxx.jar 这样的命令直接启动运行。

这样一来,打包的方式肯定要进行调整。所以 SpringBoot 提供了 spring-boot-maven-plugin 这个插件来定制打包行为。

images

#②示例代码

所有的一切已经都被 SpringBoot 封装好了,所以配置非常简单,提供插件坐标即可。

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<version>2.5.5</version>
		</plugin>
	</plugins>
</build>

#③插件的七个目标

images

目标名称作用
spring-boot:build-imagePackage an application into a OCI image using a buildpack.
spring-boot:build-infoGenerate a build-info.properties file based on the content of the current MavenProject.
spring-boot:helpDisplay help information on spring-boot-maven-plugin.
Call mvn spring-boot:help -Ddetail=true -Dgoal=<goal-name> to display parameter details.
spring-boot:repackageRepackage existing JAR and WAR archives so that they can be executed from the command line using java -jar. With layout=NONE can also be used simply to package a JAR with nested dependencies (and no main class, so not executable).
spring-boot:runRun an application in place.
spring-boot:startStart a spring application. Contrary to the run goal, this does not block and allows other goals to operate on the application. This goal is typically used in integration test scenario where the application is started before a test suite and stopped after.
spring-boot:stop

Stop an application that has been started by the 'start' goal. Typically invoked once a test suite has completed.

5、典型应用:Mybatis 逆向工程

使用 Mybatis 的逆向工程需要使用如下配置,MBG 插件的特点是需要提供插件所需的依赖:

<!-- 控制 Maven 在构建过程中相关配置 -->
<build>
		
	<!-- 构建过程中用到的插件 -->
	<plugins>
		
		<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
		<plugin>
			<groupId>org.mybatis.generator</groupId>
			<artifactId>mybatis-generator-maven-plugin</artifactId>
			<version>1.3.0</version>
	
			<!-- 插件的依赖 -->
			<dependencies>
				
				<!-- 逆向工程的核心依赖 -->
				<dependency>
					<groupId>org.mybatis.generator</groupId>
					<artifactId>mybatis-generator-core</artifactId>
					<version>1.3.2</version>
				</dependency>
					
				<!-- 数据库连接池 -->
				<dependency>
					<groupId>com.mchange</groupId>
					<artifactId>c3p0</artifactId>
					<version>0.9.2</version>
				</dependency>
					
				<!-- MySQL驱动 -->
				<dependency>
					<groupId>mysql</groupId>
					<artifactId>mysql-connector-java</artifactId>
					<version>5.1.8</version>
				</dependency>
			</dependencies>
		</plugin>
	</plugins>
</build>

#6、小结

不知大家有没有发现,通常需要用到 build 标签的时候底层都会帮我们封装好,需要我们配置的地方不多。即使有些地方需要我们配置,也不会真的我们自己去写,把现成的案例复制过来就行。

所以对 build 标签来说,我们的掌握要求就是:能大致看懂就行。

        依赖范围:
        1)import
        管理依赖最基本的办法就是继承父工程,但是和java类一样,Maven也是单继承的,如果不同体系的依赖信息封装在不同POM中了,没办法继承多个父工程怎么办?这是就可以使用import依赖范围。
        典型案例当然是在项目引入SpringBoot,SpringCloud依赖:

<dependencyManagement>
    <dependencies>

        <!-- SpringCloud 依赖导入 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR9</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!-- SpringCloud Alibaba 依赖导入 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!-- SpringBoot 依赖导入 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.3.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

import 依赖范围使用要求:

  • 打包类型必须是 pom
  • 必须放在 dependencyManagement 中

       

2)system

以 Windows 系统环境下开发为例,假设现在 D:\tempare\atguigu-maven-test-aaa-1.0-SNAPSHOT.jar 想要引入到我们的项目中,此时我们就可以将依赖配置为 system 范围:

<dependency>
    <groupId>com.atguigu.maven</groupId>
    <artifactId>atguigu-maven-test-aaa</artifactId>
    <version>1.0-SNAPSHOT</version>
    <systemPath>D:\tempare\atguigu-maven-test-aaa-1.0-SNAPSHOT.jar</systemPath>
    <scope>system</scope>
</dependency>

但是很明显:这样引入依赖完全不具有可移植性,所以不要使用。如果需要引入体系外 jar 包我们后面会讲专门的办法。

        3)runtime

专门用于编译时不需要,但是运行时需要的 jar 包。比如:编译时我们根据接口调用方法,但是实际运行时需要的是接口的实现类。典型案例是:

<!--热部署 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

2、可选依赖

#①配置举例

<!--热部署 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

#②本质含义

可选其实就是『可有可无』。官网的解释是:

images

其核心含义是:Project X 依赖 Project A,A 中一部分 X 用不到的代码依赖了 B,那么对 X 来说 B 就是『可有可无』的。

images

3、版本仲裁

#①最短路径优先

在下图的例子中,对模块 pro25-module-a 来说,Maven 会采纳 1.2.12 版本。

#②路径相同时先声明者优先

images

此时 Maven 采纳哪个版本,取决于在 pro29-module-x 中,对 pro30-module-y 和 pro31-module-z 两个模块的依赖哪一个先声明。

#③小结

其实 Maven 的版本仲裁机制只是在没有人为干预的情况下,自主决定 jar 包版本的一个办法。而实际上我们要使用具体的哪一个版本,还要取决于项目中的实际情况。所以在项目正常运行的情况下,jar 包版本可以由 Maven 仲裁,不必我们操心;而发生冲突时 Maven 仲裁决定的版本无法满足要求,此时就应该由程序员明确指定 jar 包版本。

        Maven自定义插件:
              可参考资料;

       

        profile概述:

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值