《Maven实战》读后感

news2024/11/26 13:55:49

目录

  • 一、一些思考
    • 1、为什么平时编写的Java项目也叫做Maven项目?
    • 2、平常的Java项目目录为什么长这样,可以改变目录结构吗?
    • 3、对于Maven项目来说,Maven能帮我们做什么?
    • 4、为什么一定需要Maven私服,不要行不行?
    • 5、为什么在执行mvn package之前必须要执行mvn clean呢?
    • 6、为什么在pom.xml中一般都会配置maven-compiler-plugin插件,并且设置source和target的值呢?
    • 7、如何配置pom.xml、settings.xml,才能把项目打成jar包推送到maven私服中,以及从maven私服中下载依赖jar包?
  • 二、小知识点
    • 1、pom.xml中的gav、目录的关联关系
    • 2、超级Pom的位置
  • 三、Maven私服—Nexus
    • 1、放在这里的原因
    • 2、maven私服的作用
    • 3、在k8s中搭建Nexus
    • 4、宿主仓库、代理仓库、仓库组
    • 5、创建宿主仓库
    • 6、创建代理仓库
    • 7、创建仓库组
    • 8、仓库链接
    • 9、Nexus使用教程
  • 四、settings.xml
    • 1、放在这里的原因
    • 2、pom.xml中的repositories、pluginRepositories,然后settings.xml中的repositories、pluginRepositories,然后超级pom中的repositories、pluginRepositories,然后settings.xml中的镜像,到底哪个会生效?
      • (1)pom.xml中的repositories、pluginRepositories配置方式
      • (2)settings.xml中的repositories、pluginRepositories配置方式
      • (3)超级pom中的repositories、pluginRepositories配置方式
      • (4)settings.xml中的镜像配置方式
      • (5)生效原则
    • 3、settings.xml中的repositories、pluginRepositories配置方式如何控制构件的下载?
    • 4、settings.xml位置说明
    • 5、相关知识点
    • 6、元素作用说明
      • (1)localRepository
      • (2)proxies
      • (3)servers
      • (4)mirrors
      • (5)profiles
  • 五、pom.xml
    • 1、放在这里的原因
    • 2、想把普通业务jar包或者Maven插件jar包发送到Maven私服中,应该怎么配置,其实也就是说明下pom.xml中distributionManagement元素下面的repository元素和snapshotRepository元素怎么用?
    • 3、相关知识点
      • (1)依赖范围
      • (2)传递性依赖
      • (3)依赖范围和传递性依赖
      • (4)依赖调解(即相同groupId和artifactId,而version不同的依赖,到底哪个最终会被使用?)
      • (5)Maven属性
      • (6)从仓库解析依赖的机制
      • (7)聚合
        • 1)作用
        • 2)实现方式
        • 3)注意点
      • (8)继承
        • 1)作用
        • 2)实现方式
        • 3)注意点
      • (9)聚合和继承的关系
      • (10)生命周期与插件
        • 1)生命周期是什么
        • 2)生命周期阶段是什么
        • 3)插件是什么
        • 4)插件目标是什么
        • 5)生命周期、生命周期阶段、插件、插件目标的关系
        • 6)生命周期详细解释
        • 7)插件和插件目标详细解释
        • 8)pom.xml中插件groupId和artifactId的解析过程
        • 9)mvn 命令行中插件前缀解析过程
    • 4、元素作用说明
      • (1)modelVersion
      • (2)groupId、artifactId、version
      • (3)parent
      • (4)modules
      • (5)packaging
      • (6)name
      • (7)description
      • (8)几个不太常用的项目信息元素
      • (9)properties
      • (10)dependencyManagement
      • (11)dependencies
      • (12)build
        • 1)finalName
        • 2)sourceDirectory
        • 3)resources
        • 4)plugin
      • (13)profiles
      • (14)distributionManagement》repository
      • (15)distributionManagement》snapshotRepository
      • (16)repositories》repository
      • (17)pluginRepositories》pulginRepository
  • 六、Maven插件
    • 1、作用
    • 2、注意点
    • 3、和普通Maven项目的区别
    • 4、示例

一、一些思考

1、为什么平时编写的Java项目也叫做Maven项目?

那是因为平时编写的项目都是按照Maven编写规范编写的,其中目录结构、pom.xml都是按照maven配置要求并添加对应值的

2、平常的Java项目目录为什么长这样,可以改变目录结构吗?

我们看一下RuoYi项目中的ruoyi-admin模块,如下:

在这里插入图片描述

大家应该都是编写过java代码的,一般都是把主代码放在src/main/java目录下面,主配置文件放在src/main/resources目录下面,测试代码放在src/test/java目录下面,测试配置文件放在src/test/resources目录下面,然后在模块下面放置pom.xml文件,这是全部都是maven在超级pom.xml(类似于所有类的超类都是Object一样,也就是所有pom.xml都会继承超级pom)中规定好的

那我们就去找一下maven超级pom.xml中的规定吧,在maven安装目录下找到lib目录,在里面找到maven-model-builderXXX.jar(其中XXX是安装的maven版本,例如我的maven版本是3.5.4,那我需要找到的jar包就是maven-model-builder-3.5.4.jar),然后我们通过反编译工具打开该jar包,然后找到org.apache.maven.model目录,然后打开目录下的pom-4.0.0.xml,这时就会看到如下内容,其中${project.basedir}是当前模块的目录:

在这里插入图片描述

说明:推荐一款jar包反编译工具:jd-gui.ext

当maven执行相关命令的时候,比如mvn clean package的时候就会使用上述目录下进行相关工作,所以我们一定要让maven知道这些目录在哪里,如果我们想更改主代码目录、主资源目录、测试代码目录、测试资源目录的位置,那就需要模仿超级pom的写法在我们模块的pom.xml文件中指明,这样maven就知道它需要的maven在哪里了。

对于一些老项目来说,可能没有被maven管理,现在要把项目改成被maven管理的,但是这种老项目的代码可能在source目录下面,而不是src/main/java下面,这个时候我们就需要更改模块中主代码目录的位置,这种情况我们公司之前的老项目改maven代码是遇到过的,如下:

在这里插入图片描述

3、对于Maven项目来说,Maven能帮我们做什么?

Maven是一个跨平台的项目管理工具,主要应用于项目信息管理、项目构建、依赖管理。

  • 跨平台:Maven可以安装在Windows平台上(代码开发时在用),也可以安装在Linux平台上(使用Jenkins操作Maven直接对代码进行编译打包)
  • 项目信息管理:在pom.xml的project元素下面可以放置很多项目信息元素,比如:
    • name:名称
    • description:描述
    • organization:所属组织
    • licenses(集合)》license:许可证
    • mailingLists(集合)》mailingList:邮件列表
    • developers(集合)》developer:开发者
    • contributors(集合)》contributor:贡献者
    • issueManagement:问题追踪系统
    • ciManagement:持续追踪系统
    • scm:版本控制系统
      在这里插入图片描述
  • 项目构建:maven有非常多的命令,最常用的是clean、compile、package、install、test,其中项目打包构建用的是mvn clean package
  • 依赖管理:在pom.xml中放置了很多依赖,maven可以引入依赖、排除依赖、继承依赖、设置依赖范围等操作

4、为什么一定需要Maven私服,不要行不行?

公司之前没有搭建maven私服,然后入职的每个新同事都会收到一个很大的tomcat,这个tomcat中jar包很完善,基本用到jar包都用,虽然平时开发没有什么问题,但是一旦需要引入新的jar包,以及需要排除一些jar包,还有需要用到其他同事开发的项目jar包,这个过程就很难受,但是有了maven私服之后,这种事情就可以改变了,maven可以帮助我们去进行依赖管理,并且我们还可以把我们自己开发的项目jar包发送到maven仓库中,然后让其他同事引入

也有的朋友也会说,现在阿里云的maven仓库应该已经很快了,那我们为啥还有搭建一个maven私服呢,这样耗费带宽、存储空间。大家是否想过这些场景,公司内部基础框架肯定会产生一些jar包的,这些jar包肯定不能发送的公网上面,那就需要一个maven私服来进行jar包存储。当然maven私服的作用不仅仅这么一点,比如它还可以节约公司网络带宽、保证maven仓库访问的稳定性等作用

5、为什么在执行mvn package之前必须要执行mvn clean呢?

这个就涉及到maven的生命周期管理了,其实clean、package命令都是生命周期中的一个阶段名称,其实maven中一共有三套生命周期,分别是clean、default、site,其中:

  • clean生命周期:
    在这里插入图片描述
  • default生命周期:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • site生命周期:
    在这里插入图片描述

从上面可以看出来clean阶段clean生命周期中,而package阶段default生命周期

首先说明两点,这三个生命周期没有任何联动关系,对于每个生命周期中的阶段来说,后面的阶段执行的时候必将先执行前面的阶段

由于我们需要先通过clean阶段删除target目录,然后对最新的代码进行package阶段(由于compile阶段package阶段前面,所以执行package阶段的时候肯定会执行compile阶段),所以执行package命令执行先执行clean命令

6、为什么在pom.xml中一般都会配置maven-compiler-plugin插件,并且设置source和target的值呢?

在模块的pom.xml中我们一般看到如此的插件设置,如下:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

在《Maven实战》的P33页提到:

这是Maven初学者常常会遇到的一个问题。由于历史原因,Maven的核心插件之一——compiler插件默认支持编译Java 1.3,因为需要配置该插件使其支持其他Java版本

由于我代码中写的是有lamda表达式,这是java8的特性,所以必须编译器需要支持java8版本,因为在插件中添加了相关属性信息

其实这块和超级Pom有关,但是我看3.5.4版本Maven中的超级Pom里面就没有定义compiler插件的默认版本了,所以如果我们不定义compiler插件的版本,就会使用最新的稳定版本,所以就不用担心该问题了,这主要依赖maven的版本,因此若依作者在写项目的时候可能担心由于版本不同会出现问题,所以直接显式写明了compiler插件的version,避免出现问题

7、如何配置pom.xml、settings.xml,才能把项目打成jar包推送到maven私服中,以及从maven私服中下载依赖jar包?

这需要对pom.xml、settings.xml中的各种地址进行相关配置,TODO 后续补充

二、小知识点

1、pom.xml中的gav、目录的关联关系

  • pom.xml中的gav
    • groupId:定义项目属于哪个组,这个组往往和项目所在的组织和公司存在关联,一般是公司域名的倒序+项目名称,比如:com.atguigu.netiler,也可以仅仅是公司域名的倒序,比如:com.ruoyi
    • artifactId:定义当前Maven项目在组中的唯一ID,一般是子项目(模块)名称,比如:kms-wiki
    • version:定义子项目(模块)版本
  • 目录:由于主代码目录和测试代码目录中的结构基本类似,以主代码目录为例,在src/main/java目录下面是groupId/artifactId(注意:1、把groupId中的.换成/;2、artifactId可以变化,比如若依其中一个模块是ruoyi-system,而目录是:src/main/ava/com/ruoyi/system;比如我们下面的例子,就把kms-wiki在目录中换成了kmswiki),再往下的目录中就可以写代码了,比如:src/main/java/com/atguigu/netiler/kmswiki

2、超级Pom的位置

超级Pom的地位相当于java编程中的Object超类,所以的业务代码pom.xml都会继承超级Pom中的配置,我们也可以在业务代码中的pom.xml重写相关配置来配置超级Pom中的配置,其中超级Pom就位于Maven安装位置libmaven-model-builder-XXX.jar中的org.apache.maven.model.pom-4.0.0.xml,我的maven版本是3.5.4的,pom-4.0.0.xml的内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<!-- START SNIPPET: superpom -->
<project>
  <modelVersion>4.0.0</modelVersion>

  <repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
  </pluginRepositories>

  <build>
    <directory>${project.basedir}/target</directory>
    <outputDirectory>${project.build.directory}/classes</outputDirectory>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
    <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${project.basedir}/src/test/resources</directory>
      </testResource>
    </testResources>
    <pluginManagement>
      <!-- NOTE: These plugins will be removed from future versions of the super POM -->
      <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
      <plugins>
        <plugin>
          <artifactId>maven-antrun-plugin</artifactId>
          <version>1.3</version>
        </plugin>
        <plugin>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.8</version>
        </plugin>
        <plugin>
          <artifactId>maven-release-plugin</artifactId>
          <version>2.5.3</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

  <reporting>
    <outputDirectory>${project.build.directory}/site</outputDirectory>
  </reporting>

  <profiles>
    <!-- NOTE: The release profile will be removed from future versions of the super POM -->
    <profile>
      <id>release-profile</id>

      <activation>
        <property>
          <name>performRelease</name>
          <value>true</value>
        </property>
      </activation>

      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-source-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar-no-fork</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-javadoc-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-javadocs</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
              <updateReleaseInfo>true</updateReleaseInfo>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

</project>
<!-- END SNIPPET: superpom -->

三、Maven私服—Nexus

1、放在这里的原因

真正介绍知识点之前,我想先说一下Maven私服Nexus的情况,因为pom.xml和settings.xml中涉及到依赖上传和下载的地方都和私服有关。虽然Maven私服有很多种可以选择,但是现在最火热的就是Nexus

2、maven私服的作用

  • 降低中央仓库负荷
  • 节省外网带宽
  • 加速Maven构建
  • 自己部署构建

3、在k8s中搭建Nexus

直接查看k8s云原生环境搭建笔记中的安装nexus

4、宿主仓库、代理仓库、仓库组

这几种都是仓库,不过用途不一样

  • 宿主仓库:用来放置公司自己的构件(业务项目和插件都是构件),分为Release(用来部署发布版本构件)和Snapshot类型(用来部署快照版本构件)
  • 代理仓库:用来放置远程仓库的构件,比如从阿里云中央仓库下载的构件
  • 仓库组:不放置任何构件,它用来装载宿主仓库和代理仓库,类似于nginx的作用,未来会把下载请求分给其他仓库,而仓库组当做门户来用

下面贴出书中的内容进行详细解释:

在这里插入图片描述

5、创建宿主仓库

首先需要点击创建仓库按钮,如下图:

在这里插入图片描述

然后选择宿主仓库类型,如下:

在这里插入图片描述

然后选择和输入相应的参数,对于Version policy来说,一般情况下Snapshot版本的jar包都会和正式发布版的jar包存储位置放开的,所以我们需要两个宿主仓库,Version policy分别是ReleaseSnapshot类型的,分别用来存储对应类型的jar包,说明信息如下:

在这里插入图片描述
在这里插入图片描述

我用了两个仓库分别来存储发布版本的构件和快照版本的构件,他们分别是test-dev和test-snapshot,如下:

在这里插入图片描述

6、创建代理仓库

首先需要点击创建仓库按钮,如下图:

在这里插入图片描述

然后选择代理仓库类型,如下:

在这里插入图片描述

在中国来说阿里云中央仓库(地址:http://maven.aliyun.com/nexus/content/groups/public)的速度还是很快的,所以我选择阿里云中央仓库来当做代理仓库,如下:

在这里插入图片描述

目前我设置了一个代理仓库test-ali,如下:

在这里插入图片描述

7、创建仓库组

首先需要点击创建仓库按钮,如下图:

在这里插入图片描述

然后选择仓库组类型,如下:

在这里插入图片描述

仓库组类似于nginx的作用,里面可以包裹宿主仓库和代理仓库,作为仓库的统一入口,如下:

在这里插入图片描述
在这里插入图片描述

8、仓库链接

在这里插入图片描述

9、Nexus使用教程

完整教学:nexus搭建maven私服

四、settings.xml

1、放在这里的原因

pom.xml中含有更多的信息,settings.xml相对比较简单,所以我们先讲述settings.xml,然后在讲述pom.xml的时候,部分内容可以和settings.xml进行联动讲解

2、pom.xml中的repositories、pluginRepositories,然后settings.xml中的repositories、pluginRepositories,然后超级pom中的repositories、pluginRepositories,然后settings.xml中的镜像,到底哪个会生效?

(1)pom.xml中的repositories、pluginRepositories配置方式

repositories元素中是普通仓库(业务代码jar包)的连接信息,而pluginRepositories元素中是插件仓库(maven插件jar包)的连接信息,至于详细内容在下面会详细解释

在这里插入图片描述

(2)settings.xml中的repositories、pluginRepositories配置方式

repositories元素中是普通仓库(业务代码jar包)的连接信息,而pluginRepositories元素中是插件仓库(maven插件jar包)的连接信息,然后通过下面的activeProfile元素激活profile元素的配置,至于详细内容在下面会详细解释

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

(3)超级pom中的repositories、pluginRepositories配置方式

寻找超级Pom:在maven安装目录下找到lib目录,在里面找到maven-model-builderXXX.jar(其中XXX是安装的maven版本,例如我的maven版本是3.5.4,那我需要找到的jar包就是maven-model-builder-3.5.4.jar),然后我们通过反编译工具打开该jar包,然后找到org.apache.maven.model目录,然后打开目录下的pom-4.0.0.xml,这时就会看到超级Pom,其中超级Pom类似于java编程中的Object类一样,所以超级Pom中的所有东西其他pom.xml都会继承

在这里插入图片描述

(4)settings.xml中的镜像配置方式

在上面两种方式中,无论是repository元素或是pluginRepository元素,对应的都有一个id元素,如果id元素的值能匹配上mirrorOf元素中的值,那就会把请求转到镜像指代的url地址中去执行jar包下载工作。比如mirrorOf元素中配置*,那所有的下载请求都会转到这里,其他配置方式都是等值比较。至于详细内容在下面会详细解释

在这里插入图片描述
在这里插入图片描述

(5)生效原则

  • 找到合适的仓库:
    下载依赖的时候首先不会涉及settings.xml中的镜像信息,那就是涉及到pom.xmlsettings.xml超级Pom中的普通仓库和插件仓库配置信息了,优先级从大到小依次是:pom.xml>settings.xml>超级Pom

  • 选择仓库之后,那就需要讨论是否在settings.xml中配置镜像信息了

    • settings.xml中有匹配的镜像信息:那就看镜像信息能否配置上仓库信息了,其实也就是看仓库的id元素值和镜像的mirrorOf元素能否匹配上,匹配不上就相当于没有可用镜像信息。比如mirrorOf元素中配置*,那所有的下载请求都会转到这里,其他配置方式都是等值比较。对于有匹配的镜像信息来说,那就需要根据镜像中id的值去servers元素中找到对应id元素值的用户信息进行登录获取相关jar包了,此时普通仓库和插件仓库配置的url配置什么都不在重要了
    • settings.xml中没有匹配的镜像信息:那就需要只能根据自己里面配置的id值去servers元素中找到对应id值的用户信息去进行获取相关jar包了
  • 如果选中的远程仓库的ip都无法访问,那么就轮到其他配置方式的远程仓库了,否则还是远程仓库下载,即使下载结果是有问题的

  • 对于普通仓库和插件仓库来说,如果id元素值相同,那就会根据优先级规则产生覆盖效果,比如超级Pom中配置的普通仓库和插件仓库的id元素值都是central,那么我在settings.xml中普通仓库和插件仓库的id元素值替换成central,那settings.xml中的仓库信息就会覆盖中央仓库的仓库信息

一图胜千言,我用流程图给大家演示一下普通业务代码jar包的一个下载流程,当然插件代码jar包的下载流程也是这样,不在赘述,如下:

在这里插入图片描述

3、settings.xml中的repositories、pluginRepositories配置方式如何控制构件的下载?

无论是普通Maven项目,还是Maven插件项目,其中都包括发布版本和快照版本构建,那么在下载构件的时候需要控制是否能够下载该构件、检查更新构件的频率、检查校验的策略

  • enabled:是否开启下载构件的支持,开启才会下载,反之不会下载
  • updatePolicy:配置Maven从远程仓库检查更新的频率,默认的值是daily,表示Maven每天检查一次,可选值在下面
    • daily:每天检查一次,这也是默认值
    • always:每次构建都检查更新
    • interval: X:每隔X分钟检查一次更新(X为任意整数)
    • never:从不检查更新
      上面这几种可选值需要根据真实情况调节,一般在下载快照版本构件中用的多,比如我现在无法连接公司内网,所以只能把更新策略调成never,否则会影响项目构建。
      之前公司一些同事不太了解Maven中构件更新策略的使用,出现过Jenkins中调用maven构建项目无法取到最新快照版构件的事情,也出现过同事A把最新快照版构建发布到Maven仓库中,然后同事B在构建的时候要询问同事B发布了哪个快照版本构件,然后同事A在本地仓库中删除该快照版本,之后在重新构建项目才拉取到最新的快照版本构件,其实这些情况都是不了解Maven使用方式
  • checksumPolicy:用来校验Maven本地仓库的文件,一般设置为ignore即可,这样才不会影响我们的正常使用,书中的说明信息如下:
    在这里插入图片描述
  • 示例:
    下面是我在settings.xml中使用的示例
    在这里插入图片描述

4、settings.xml位置说明

《Maven实战》这本书中提倡配置用户范围的settings.xml和本地Maven仓库,但是我喜欢配置全局范围的settings.xml和本地Maven仓库,原因是我的电脑就我一个人用,把settings.xml和本地Maven仓库放在一个确切的位置我比较好找,不然还要去C盘的用户目录去查找,这也太麻烦了吧!

我一般把Maven安装某个盘符中,然后在maven安装位置中的conf目录下的settings.xml就是全局配置文件,例如:

在这里插入图片描述

5、相关知识点

6、元素作用说明

settings.xml元素参考:
在这里插入图片描述

(1)localRepository

  • 含义:本地仓库所在位置

  • 默认值:${user.home}/.m2/repository;注意:前面${user.home}代表用户目录,在windows和linux下面是不同的,另外对于linux来说,以.开头的目录是隐藏目录,所以需要ls -a命令才能看到隐藏目录

  • windows配置示例:<localRepository>C:\software\MAVEN\apache-maven-3.5.4\mavenRepository</localRepository>

  • linux配置示例:<localRepository>/var/jenkins_home/maven_repository</localRepository>

(2)proxies

用来设置HTTP代理,具体作用就是当无法直接访问Maven私服,而是需要通过网络代理,甚至是带用户名和密码登录的网络代理才能访问Maven私服的时候,那就需要用到这块的内容了,但是我们公司是内网开发但是目前也没遇到这种情况,所以就不在介绍了,感兴趣的朋友可以去:《Maven实战》P17——2.4 设置HTTP代理这一节

(3)servers

  • 含义:配置登录Maven私服的用户名和密码,用来给pom.xml、settings.xml、超级pom中的普通仓库、插件仓库、镜像、宿主仓库(上传jar包)、快照仓库(上传jar包)访问maven私服使用

  • 用法:可以在server》id中配置id值,只要pom.xml、settings.xml、超级pom中的普通仓库、插件仓库、镜像、宿主仓库(上传jar包)、快照仓库(上传jar包)中的id能够和该id值对应上,那就可以使用username和password的值去访问Maven私服,举例如下:

    • pom.xml中的仓库id对上server中的id:
      在这里插入图片描述

    • settings.xml中的仓库id对上server中的id:
      在这里插入图片描述

    • settings.xml中的镜像id对上server中的id:在这里插入图片描述

    • pom.xml中的仓库id对上server中的id:在这里插入图片描述

  • 值含义:上面基本已经对id值的含义进行了相关介绍,下面介绍一下另外两个参数的值,它们分别是username和password,这两个参数分别是Maven私服(例如Nexus)的用户登录信息

  • 示例值:

<servers>
	<server>
	  <id>admin</id>
	  <username>admin</username>
	  <password>admin123456</password>
	</server>
	<server>
	  <id>central</id>
	  <username>admin</username>
	  <password>admin123456</password>
	</server>
</servers>

(4)mirrors

  • 含义:在《Maven实战》这本书中提到镜像比仓库的范围更宽泛,如果仓库和镜像能匹配上,那就会根据根据镜像id去找到合适的用户信息,然后配合镜像url值访问Maven私服,进而把jar包上传到Maven仓库,或者把jar包从Maven仓库中下载下来
  • 仓库和镜像如何匹配:如果仓库的id值和镜像的mirrorOf值能匹配上,那就是匹配成功,如果mirrorOf是通配符*,那可以匹配所有仓库;否则那就需要完全一致才是匹配上了
  • 示例值:
<mirrors>
	<mirror>
	  <id>admin</id>  
	  <url>http://192.168.139.133:31743/repository/test-public/</url>   
	  <mirrorOf>*</mirrorOf>    
	</mirror>
</mirrors>

(5)profiles

  • 含义:添加仓库信息 + 配置信息

  • 使用位置:pom.xml、settings.xml

  • 理论上能使用哪些属性:
    在这里插入图片描述

  • 真实情况下能使用哪些属性:
    在这里插入图片描述
    原因: 避免项目移动到其他地方之后出现问题,所以Maven不允许用户在settings.xml中的profile中声明依赖或者插件,所以事实上settings.xml中只能使用上面三个元素

  • 使用举例:
    解释: 这是我们公司内部配置的maven信息,左侧是settings.xml,其中仓库配置信息就是用来下载jar包的(普通业务jar包+Maven插件jar包),而属性配置信息是给右侧pom.xml使用的,这是为了上传jar包的(普通业务jar包+Maven插件jar包)
    在这里插入图片描述
    上面没有提到下载插件jar包的配置信息,下面举个我自己搭建的Nexus的例子:
    在这里插入图片描述

  • 激活方式

    • 命令行激活:mvn clean install -PXXX,XXX,其中XXX指代profile中的id,可以一次性激活多个profile
    • settings文件显式激活:直接配置即可,如下所示:
      在这里插入图片描述
    • 系统属性激活
      直接引用书籍中的内容解释的更好,如下:
      在这里插入图片描述
      在这里插入图片描述
    • 操作系统环境激活
      直接引用书籍中的内容解释的更好,如下:
      在这里插入图片描述
      在这里插入图片描述
    • 文件存在与否激活
      直接引用书籍中的内容解释的更好,如下:
      在这里插入图片描述
    • 默认激活:
      直接引用书籍中的内容解释的更好,如下:在这里插入图片描述
      在这里插入图片描述

五、pom.xml

1、放在这里的原因

上面已经把settings.xml进行了简单介绍,其实settings.xml中的内容还是比较少的,毕竟它的主要作用就是设置本地仓库localRepository、配置登录Maven私服的用户信息server、配置镜像mirror、配置仓库和配置信息profile、配置激活profile的activeProfiles;

简单的搞完了,那就需要关注pom.xml中的详细内容了

2、想把普通业务jar包或者Maven插件jar包发送到Maven私服中,应该怎么配置,其实也就是说明下pom.xml中distributionManagement元素下面的repository元素和snapshotRepository元素怎么用?

之前我们已经说过Nexus中如何建立宿主仓库了,以及如何获取宿主仓库的链接,下面的test-dev是发布版本构件的宿主仓库,而test-snapshot是快照版本构件的宿主仓库,如下:

在这里插入图片描述

无论是普通业务jar包或者Maven插件jar包在pom.xml中的配置都是一样的。在pom.xml中,只要version是以-SNAPSHOT结尾的,那就是快照版本构件,需要发到快照版本构件宿主仓库。反之需要发到发布版本构件宿主仓库。直接来一个例子吧,如下:

<distributionManagement>
    <repository>
        <id>admin</id>
        <url>http://192.168.139.133:31743/repository/test-dev/</url>
    </repository>
    <snapshotRepository>
        <id>admin</id>
        <url>http://192.168.139.133:31743/repository/test-snapshot/</url>
    </snapshotRepository>
</distributionManagement>

在上面settings.xml中的profile元素中介绍过真正可以使用的元素只有repositoriespluginReporitoriesactiveProfiles,所以提交jar包到maven私服的配置只能写在pom.xml中了,上面就是在pom.xml中的上传jar包的配置信息。上传jar包的配置信息只和上面的配置以及settings.xml中的server元素有关,毕竟要使用server中记录的Maven私服用户信息。

一图胜千言,下面用图描述一下:

在这里插入图片描述
根据真实情况,我们再来一张图说明一下:
在这里插入图片描述

3、相关知识点

(1)依赖范围

大家在pom.xml应该都看过这种写法:

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.10</version>
	<scope>test</scope>
</dependency>

其中有一个scope元素非常特殊,该元素取值将影响依赖使用范围,其中依赖范围包括编译、测试、运行环境,下面介绍一下相关取值:

  • compile:编译依赖范围,这是默认值,在编译、测试、运行环境都可以使用,例如:spring-core依赖

  • test:测试依赖范围,只在测试环境可以使用,例如:JUnit依赖

  • provided:已提供依赖范围,在编译和测试环境都可以使用,但是运行时环境无效,例如:servlet-api,由于在tomcat容器中运行的时候已经提供了该jar包,那就不需要maven重复引入了

  • runtime:运行时依赖范围,只在测试和运行时环境有效,但是在编译环境无效,例如:JDBC驱动实现

  • system:系统依赖范围,只在编译和测试环境中可以使用,但是在运行时无效,使用该范围的依赖必须通过systemPath元素显示指定依赖文件的相对路径,基本使用情况是jar包不在maven仓库中,而是直接放在项目中,然后通过这种方式引入项目,虽然存在范围特性,但是既然引入项目中还是想在运行时环境使用的,所以那就需要在打包的时候也要给该依赖打包
    我给大家举个实际使用场景的例子吧,产品需要我完成一个根据分节符拆分word文档的功能,所以我用了spire.doc.free-5.2.0.jar,并且修改了该jar包是的字节码文件内容,但是我们公司Maven私服Nexus又不知道找谁给我开权限往上传jar包,所以我就把jar包直接放在项目中了,然后通过type为system这种形式的依赖进行引入,并且设置打包的时候需要打包这种依赖,最终完成了该jar包在项目中的使用,如下:
    在这里插入图片描述

  • import(Maven 2.9.0及以上):导入依赖范围,该依赖范围和编译、测试、运行时环境无关,该依赖范围只在dependencyManagement元素下有效,作用是将目标模块pom.xml中的dependencyManagement元素导入并合并到当前模块的pom.xml中的dependencyManagement元素中,一般目标模块的打包方式是pom,专门就是做继承模块用的,这种情况下还要去type元素的值是pom,这块上面讲过的,例如:

    <!-- SpringBoot的依赖配置-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.5.14</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    

    总结一下依赖范围和编译、测试、运行时环境的关系:

    在这里插入图片描述

(2)传递性依赖

假设模块A直接依赖模块B,而模块B依赖模块C和模块D,如果没有传递性依赖,那就需要在模块A的pom.xml中不仅写上模块B的依赖坐标信息,也要写上模块C和模块D的信息。

由于传递性依赖的存在,所以Maven会解析各个直接依赖(比如依赖的模块B),然后将间接依赖(比如模块C和模块D)通过传递性依赖的方式引入到模块A中。

所以说传递性依赖方便了依赖引入这一操作

(3)依赖范围和传递性依赖

如果A依赖B,而B依赖C(即A——>B——>C),那么A是B的第一直接依赖,而B对于C是第二直接依赖,而C是A的传递性依赖。

第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围,下图中左侧表示第一直接依赖范围,而上面表示第二直接依赖范围,中间结果表示传递性依赖范围,如下:

在这里插入图片描述
结合上面对依赖范围的讲述,传递性依赖范围就能决定在什么情况下才能使用传递性依赖,也就是模块A在到底在编译、测试、运行时候是否能使用传递性依赖C

(4)依赖调解(即相同groupId和artifactId,而version不同的依赖,到底哪个最终会被使用?)

上面已经对传递性依赖进行了讲解,由于maven项目中无法存在相同groupId、artifactId,但是version不同的依赖,但是传递型依赖就有可能造成这种选择困境,我们不知道哪个version的依赖在起到作用。假设有以下两种依赖情况,那就需要通过依赖调节原则进行判断那个版本的依赖是可用的了

  • 情况1:模块A存在这种依赖关系:A->B->C->X(1.0)、A->D->X(2.0)
  • 情况2:模块A存在这种依赖关系:A->B->Y(1.0)、A->D->Y(2.0),假设A依赖B写在pom.xml的前面

针对这两种情况,分别可以使用依赖调节的第一原则和第二原则进行解决:

  • 依赖调节第一原则:路径最近则优先。针对上述情况1,那就是A->D-X(2.0)的最近,所以依赖X的版本是2.0
  • 依赖调节第二原则:第一声明者优先,当使用第一原则无法判断的时候,那就使用第二原则去判断。针对上述情况2,由于A依赖B写在pom.xml的前面,所以依赖Y的版本是1.0

(5)Maven属性

简单来说就是A处定义的属性,在B处可以通过${属性名称}这种方式引用,达到一处修改处处生效的效果,一共分为6大种,这种写法在pom.xml、配置文件、maven插件种都有可能用到。

默认情况下,只有pom.xml中的Maven属性才会被解析,而src/main/resources中的资源目录都不会被解析,但是maven插件中用到的maven属性也可以被解析

  • 内置属性
    在这里插入图片描述

  • POM属性
    在下面几种的基础上我在补充一种${project.basedir},这个也是项目根目录,在pom.xml中也是经常使用的,但是我在超级Pom中没有找到basedir属性,但是不影响使用
    在这里插入图片描述在这里插入图片描述

  • 自定义属性
    我们经常在pom.xml通过properties元素下面自定义pom,但是也可以在settings.xml中的profile元素下面通过properties元素来自定义pom,如下:
    在这里插入图片描述
    当然,书中展示的是在pom.xml中通过properties元素来自定义Maven属性,如下:
    在这里插入图片描述

  • Settings属性
    在这里插入图片描述

  • Java系统属性
    在这里插入图片描述

  • 环境变量属性
    在这里插入图片描述

  • 用法拓展:
    在同一个大项目中,也父子模块之分,一般情况下面,父模块的groupId和version和子模块的一致,然后子模块之间也存在相互引入的关系,比如B、C、D都是A模块的子模块,当在B模块中引入模块C和D的依赖时,可以模块C和D中的groupId和artifactId换成POM属性,即使你在模块B通是通过parent元素形式引入的模块A的groupId、artifactId也没有任何的影响,我在RuoYi项目中已经尝试过了。
    在这里插入图片描述

(6)从仓库解析依赖的机制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(7)聚合

1)作用

一次构建,处处生效

对于一个大项目来说,里面肯定有很多的子模块,那么我想达到的一个效果是我对聚合项目进行比如mvn clean deploy的操作,那所有的子模块都会进行同样的操作,达到一动全动的目的

2)实现方式

在聚合模块中加上modules>module属性,然后在属性值中写上其他模块的相对位置信息,用若依来举例吧,如下:

在这里插入图片描述

3)注意点

  • 聚合模块的打包方式必须为pom,即<packaging>pom</packaging>
  • module元素的值是模块目录名称,而不是artifactId的值
  • 不需要关注构建顺序,因为聚合模块在构建的时候会自动通过计算构建顺序,和modules元素中的声明无关
  • 聚合模块和被聚合模块不是必须是父子目录关系,如果是平级关系,那就需要在module元素中值前面添加../,也就是说module中的值是相对位置,只要能通过该值找到被聚合模块就可以了

(8)继承

1)作用

一次修改处处生效,父模块中声明好了,子模块中就可以去使用,未来父模块中发生改变,那子模块中也就可以自动改变了

比如我们在父模块中定义了version,然后子模块中继承了父模块的version,那未来只需要在父模块中修改version的值,那所有子模块中version的值自然会发生改变。这只是其他一个改变,比如依赖、插件、构建、普通项目构件下载仓库、插件构件下载仓库都是可以继承到

2)实现方式

一般情况下,我们在父模块pom.xml将gav、dependencyManagement、dependencies、build、repositories、pluginRepositories声明好,那么子模块中就可以用了

对于gav坐标来说,子模块中可以继承父模块的gv,然后自己只用写一个artifactId就可以了,示例如下:

在这里插入图片描述

对于dependencyManagement依赖管理来说,在父模块中定义的依赖管理,那么子模块中默认不会继承,但是可以在dependencies元素中只用写ga的方式就可以继承了,因为version已经被父模块给指定了,当然也可以通过指定version来覆盖父模块中给的version,示例如下:

在这里插入图片描述

对于dependencies依赖来说,子模块会完全继承父模块的依赖,不过这种写法比较少,一般都是通过依赖管理的方式让子模块自己去按需选择的,当然子模块也可以自己在依赖中写gav坐标去覆盖父模块的依赖

对于build、repositories、pluginRepositories来说,子模块会完全继承父模块,也可以通过重写的方式去覆盖父模块给与的配置信息

3)注意点

  • 父模块的打包方式必须为pom,即<packaging>pom</packaging>
  • 父子模块不是必须是父子目录关系,如果是平级关系,那就需要在子模块的parent元素中添加relativePath元素,然后在里面指明父模块的相对位置../父模块目录名称/pom.xml,也就是说如果父子模块之间不是父子目录,那就需要在子模块的parent>relativePath元素中指明父模块的相对位置,对于relativePath元素来说,默认值是../pom.xml,由于若依的子模块和父模块是父子目录关系,所以直接使用默认relativePath元素值即可,我们将其显式声明出来让大家看下具体用法:
    在这里插入图片描述

(9)聚合和继承的关系

大部分情况下,聚合模块和父模块是同一个模块,并且该模块和子模块 / 被聚合模块是父子模块的关系,例如若依中就是这样,如下:

在这里插入图片描述

父模块举例:

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ruoyi</groupId>
    <artifactId>ruoyi</artifactId>
    <version>4.7.5</version>

    <name>ruoyi</name>
    <url>http://www.ruoyi.vip</url>
    <description>若依管理系统</description>
    
    <properties>
        <!-- 依赖version -->
        <ruoyi.version>4.7.5</ruoyi.version>
        <!-- 编码方式 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- jdk版本 -->
        <java.version>1.8</java.version>
        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
        <shiro.version>1.9.1</shiro.version>
        <thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
        <druid.version>1.2.11</druid.version>
        <bitwalker.version>1.21</bitwalker.version>
        <kaptcha.version>2.3.2</kaptcha.version>
        <swagger.version>3.0.0</swagger.version>
        <mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version>
        <pagehelper.boot.version>1.4.3</pagehelper.boot.version>
        <fastjson.version>1.2.83</fastjson.version>
        <oshi.version>6.2.2</oshi.version>
        <commons.io.version>2.11.0</commons.io.version>
        <commons.fileupload.version>1.4</commons.fileupload.version>
        <poi.version>4.1.2</poi.version>
        <velocity.version>2.3</velocity.version>
    </properties>

    <!-- 依赖声明 -->
    <dependencyManagement>
        <dependencies>

            <!-- SpringBoot的依赖配置-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.5.14</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            ……

        </dependencies>
    </dependencyManagement>

    <modules>
        <module>ruoyi-admin</module>
        <module>ruoyi-framework</module>
        <module>ruoyi-system</module>
        <module>ruoyi-quartz</module>
        <module>ruoyi-generator</module>
        <module>ruoyi-common</module>
    </modules>
    <packaging>pom</packaging>


    <dependencies>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

</project>

子模块举例:

<?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">
    <parent>
        <artifactId>ruoyi</artifactId>
        <groupId>com.ruoyi</groupId>
        <version>4.7.5</version>
        <!-- ../pom.xml是默认值,特意写出来让大家看下配置方法 -->
        <relativePath>../pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>ruoyi-admin</artifactId>

    <description>
        web服务入口
    </description>

    <dependencies>

        <!-- SpringBoot集成thymeleaf模板 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        ……

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.1.1.RELEASE</version>
                <configuration>
                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                    <warName>${project.artifactId}</warName>
                </configuration>
            </plugin>
            <!-- YUI Compressor (CSS/JS压缩)
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>yuicompressor-maven-plugin</artifactId>
                <version>1.5.1</version>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>compress</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <jswarn>false</jswarn>
                    <nosuffix>true</nosuffix>
                    <linebreakpos>50000</linebreakpos>
                    <sourceDirectory>src/main/resources/static</sourceDirectory>
                    <force>true</force>
                    <includes>
                        <include>**/*.js</include>
                        <include>**/*.css</include>
                    </includes>
                    <excludes>
                        <exclude>**/*.min.js</exclude>
                        <exclude>**/*.min.css</exclude>
                        <exclude>**/fileinput.js</exclude>
                        <exclude>**/bootstrap-table/**</exclude>
                    </excludes>
                </configuration>
            </plugin> -->
        </plugins>
        <finalName>${project.artifactId}</finalName>
    </build>

</project>

(10)生命周期与插件

常用插件列表:

在这里插入图片描述
在这里插入图片描述

1)生命周期是什么

Maven中含有三套完全独立的生命周期,分别是clean、default、site,其中clean生命周期的作用是清理项目,而default生命周期的作用构建项目,而site生命周期的目的是建立项目站点,很少使用site生命周期。下面会详细解释

2)生命周期阶段是什么

以若依项目为例,当我们通过IDEA打开若依项目,然后点击右侧的Maven按钮,之后找到任意一个模块打开,大家都会看到Lifecycle,下图红框中是我们是我们最常用的一些生命周期阶段,包括:clean、compile、test、package、install、deploy……

在这里插入图片描述

3)插件是什么

插件是插件目标的合集

4)插件目标是什么

按照编程来说,如果说生命周期阶段是接口,那么插件目标就是实现类,而插件里面包含了一个或者多个插件目标

5)生命周期、生命周期阶段、插件、插件目标的关系

一个生命周期对应一个或者多个生命周期阶段,而一个生命周期阶段对应一个插件目标,而一个插件对应一个或者多个插件目标

6)生命周期详细解释

  • 三套生命周期:Maven中含有三套完全独立的生命周期,分别是clean、default、site,其中clean生命周期的作用是清理项目,而default生命周期的作用构建项目,而site生命周期的目的是建立项目站点,很少使用site生命周期
  • 生命周期阶段:虽然三套生命周期是相互独立的,但是对每一套生命周期来说,调用后面的生命周期阶段就一定会触发前面的生命周期阶段,所以我们在打包的时候只需要指定mvn clean package就可以了,虽然clean生命周期不仅包含clean阶段,当然default生命周期也是包含很多阶段的,不过按照触发后面的生命周期阶段必将触发前面的生命周期阶段的原则,所以我们打包的命令是非常简洁的。当然由于每一套生命周期都是相互独立的,所以我们需要先执行clean阶段,在执行package阶段。下面将给出每一个生命周期中的各个阶段
    • clean生命周期
      在这里插入图片描述

    • default生命周期
      在这里插入图片描述
      在这里插入图片描述

    • site生命周期
      在这里插入图片描述

7)插件和插件目标详细解释

  • 插件作用:一个插件可以做很多事情,也就是说包含多个插件目标

  • 插件目标作用:一个插件对应一个插件目标,每一个插件目标就是一个功能,每一个插件目标将会执行上述生命周期阶段所描述的事情,示例如下:
    在这里插入图片描述

  • 生命周期阶段和插件目标绑定:Maven生命周期和插件互相绑定,用来完成实际的构建任务。例如项目编译这一任务,对应default生命周期的compile阶段,然后由maven-compiler-plugin插件的compile目标进行具体实现,两者绑定之后就能完成相关任务
    在这里插入图片描述

  • 生命周期和插件目标的内置绑定:

    • clean生命周期阶段与插件目标的绑定关系
      在这里插入图片描述

    • default生命周期阶段与插件目标的绑定关系
      在这里插入图片描述

    • site生命周期阶段与插件目标的绑定关系
      在这里插入图片描述

  • 自定义生命周期和插件目标的绑定关系:
    下面就是自定义绑定关系的过程,由于该绑定方式的存在,所以多个插件目标可以绑定到同一个阶段,这些插件声明的先后顺序决定的目标的执行顺序。
    在这里插入图片描述
    在这里插入图片描述

  • 命令行插件配置:
    下面这种做法在Dockerfile中经常会见到,通过设置插件目标的参数来跳过测试。

在这里插入图片描述

8)pom.xml中插件groupId和artifactId的解析过程

我们能够看到,有些时候plugin中可以不写groupIdartifactId,这依赖于groupIdartifactId的解析机制。

groupId: 如果我们省略groupId,那么Maven会以为该插件是Maven的官方插件,所以groupId就会被认为是org.apache.maven.plugins,当然maven的官方插件很多,写法例如:
在这里插入图片描述

version: 如果我们省略version,这就需要分情况讨论了,对于部分在超级Pom中已经定义了插件版本的情况来说,那就会使用默认version,针对maven3.5.4版本来说,已经设置好version的插件是信息如下:

在这里插入图片描述

如果插件的version没在超级pom中定义,针对Maven3来说,目前默认使用所有仓库中最新的发布版本,其中所有仓库包括:本地插件仓库和远程插件仓库,但是这种做法也是不建议的,毕竟每一个版本的插件都不一样,所以建议还是固定插件版本,下面是详细解释:

在这里插入图片描述
在这里插入图片描述

9)mvn 命令行中插件前缀解析过程

我们经常使用mvn clean package这种方式来让maven执行相关操作,这种方式是操作的生命周期阶段,通过生命周期阶段来操作插件目标

那如果我想直接操作插件目标呢,这就引出了在命令行中使用mvn的具体做法,如下:

mvn [options] [<goal(s)>][<phase>(s)]

我们上面的生命周期指定的就是上述命令中phase的用法,现在我们来说上述命令中goal的用法,这是直接通过命令行来调用插件目标的做法

下面来讲述上述命令中goal的用法,当我们在控制台执行mvn dependency:tree的时候,我们调用插件目标肯定需要指明插件的gav坐标和目标,对于mvn dependency:tree来说,其中dependency就是artifactId的前缀,而tree就是目标,现在我们看下如何通过artifactId前缀dependency找到完整的插件gav坐标。默认情况下,groupId默认被赋值成org.apache.maven.plugins或者org.codehaus.mojo,以org.apache.maven.plugins为例,maven会去本地仓库中查找org/apache/maven/plugins/maven-metadata.xml,目前在我的文件中该文件名称是maven-metadata-central.xml,我感觉这个名字应该和pom.xml或者settings.xml中配置的插件仓库id值有关,打开该文件可以看到如下内容:

在这里插入图片描述
通过搜索前缀dependency可以找到artifactId的真实值maven-dependency-plugin,现在groupIdartifactId都有了,这个时候在根据上面pom.xml中插件groupId和artifactId的解析过程中提到的version解析方法得到version值,现在插件gav就完整了,然后结合目标tree就可以完成插件目标的调用了

书中还提到,我们自己写一个插件的话,也可以通过命令行中mvn artifactId前缀:目标去调用执行,首先我们要把一个发布版本的插件放在本地仓库/远程仓库,然后在settings.xml中配置我们的插件artifactId前缀的解析规则文件maven-metadata-仓库id.xml位置信息,这就是我们自己的groupId值了,具体配置方式是:

在这里插入图片描述
所以我们也模仿本地仓库中org/apache/maven/plugins/maven-metadata-central.xml的配置方式配置我们自己的maven-metadata-仓库id.xml,当在命令行使用mvn artifactId缩写:目标这个时候就能根据settings.xml中的配置信息找到我们的maven-metadata-仓库id.xml(注意:pom.xml或者settings.xml中配置的仓库id值,可能要配置到xml文件的后面才能生效),进而找到artifactId真实值,现在groupId和artifactId都有了,那就需要根据自动查找version规则找出version了,当gav坐标齐全的时候,就可以调用插件目标了,最终完成通过命令行调用我们自己编写Maven插件中的目标了

4、元素作用说明

pom.xml元素参考:
在这里插入图片描述
在这里插入图片描述

(1)modelVersion

  • 含义:Pom模型的版本
  • 说明:根据书中的解释可以知道,对于Maven 2及Maven 3来说,它只能是4.0.0,来源于《Maven实战》P28

(2)groupId、artifactId、version

  • groupId:组织机构id,一般是公司域名的倒序+项目名称,或者直接就是公司域名的倒序,比如:com.atguigu.netiler、com.ruoyi
  • artifactId:构件id,一般是模块(子项目)名称,比如:kms-wiki
  • version:构件版本,一般分为快照版本和发布版本

(3)parent

  • 含义:声明继承的父级构件信息,方便通过父级构件中的pom.xml对子级构件进行依赖版本统一控制,并且可以避免子级构件重复定义元素信息(比如:dependencies元素、build元素、repositories元素、pluginRepositories元素);parent元素的用法在“聚合与继承”章节详细介绍
  • 使用方式:用若依项目举一个例子吧:
<parent>
    <artifactId>ruoyi</artifactId>
    <groupId>com.ruoyi</groupId>
    <version>4.7.5</version>
</parent>

<artifactId>ruoyi-system</artifactId>

关系图如下:

在这里插入图片描述

  • 注意点:
    • 在parent元素里面需要写父级构件的gav坐标值,父级构件不一定必须和子级构件是两级目录关系,在parent元素里面可以通过relativePath元素来指定父级构件pom.xml的相对路径,其中relativePath元素默认值是../pom.xml,默认值代表的就是父级构件和子级构件属于父子目录,所以一般情况下我们把父级构件和子级构件写成父子目录的形式就没有配置relativePath元素的值了
    • 子级构件可以继承父级构件的groupId和version,但是artifactId元素必须重写,当然也可以书写父级构件的groupId和version

(4)modules

  • 含义:在聚合模块中声明其他模块,用来对其他模块进行统一构建,比如执行mvn clean deploy命令可以对所有的其他模块进行统一发布操作
  • 使用方式:用若依项目举一个例子吧:
<modules>
    <module>ruoyi-admin</module>
    <module>ruoyi-framework</module>
    <module>ruoyi-system</module>
    <module>ruoyi-quartz</module>
    <module>ruoyi-generator</module>
    <module>ruoyi-common</module>
</modules>

关系图如下:

在这里插入图片描述

  • 注意点:
    • module元素的值是模块目录名称,而不是artifactId的值

(5)packaging

  • 含义:打包方式
  • 默认值:jar,也就是不设置该值就是打jar包
  • 可选值:
    • jar:打jar包,默认值
    • war:打war包
    • pom:聚合项目、继承父项目
    • maven-plugin:打maven插件,但是结果也是jar包
  • 示例:<packaging>maven-plugin</packaging>

(6)name

  • 含义:模块名称,仅仅是展示作用,例如:<name>ruoyi</name>

(7)description

  • 含义:模块描述,仅仅是展示作用,例如:<description>若依管理系统</description>

(8)几个不太常用的项目信息元素

  • organization:所属组织
  • licenses(集合)》license:许可证
  • mailingLists(集合)》mailingList:邮件列表
  • developers(集合)》developer:开发者
  • contributors(集合)》contributor:贡献者
  • issueManagement:问题追踪系统
  • ciManagement:持续追踪系统
  • scm:版本控制系统

(9)properties

  • 含义:Maven属性,这里面配置的信息都是提供给别的位置使用,比如:dependencies、dependencyManagement、build。放在这里的原因是方便统一修改,比如设置在父模块里面可以统一控制子模块的依赖version版本,一处修改而处处生效,可以放置依赖version、编码方式、jdk版本等
    我们公司的架构师就在父模块中写了很多properties,结合dependencyManagement用于控制依赖version,所以他们直接把依赖冲突、版本冲突的情况处理好了,对于我们使用者来说就不用担心依赖之间会导致依赖冲突问题了,感谢他们为工作推进做出的贡献
  • 示例:
<properties>
    <!-- 依赖version -->
    <ruoyi.version>4.7.5</ruoyi.version>
    <!-- 编码方式 -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <!-- jdk版本 -->
    <java.version>1.8</java.version>
    <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
    <shiro.version>1.9.1</shiro.version>
    <thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
    <druid.version>1.2.11</druid.version>
    <bitwalker.version>1.21</bitwalker.version>
    <kaptcha.version>2.3.2</kaptcha.version>
    <swagger.version>3.0.0</swagger.version>
    <mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version>
    <pagehelper.boot.version>1.4.3</pagehelper.boot.version>
    <fastjson.version>1.2.83</fastjson.version>
    <oshi.version>6.2.2</oshi.version>
    <commons.io.version>2.11.0</commons.io.version>
    <commons.fileupload.version>1.4</commons.fileupload.version>
    <poi.version>4.1.2</poi.version>
    <velocity.version>2.3</velocity.version>
</properties>

(10)dependencyManagement

  • 含义:依赖管理,一般写在父模块中,然后为子模块提供依赖管理,那么子模块在使用的时候,只用写groupId和artifactId就可以了,version可以由父模块控制,当然如果子模块写了version,那就会覆盖父模块中的version
  • 示例:
<!-- 依赖声明 -->
<dependencyManagement>
    <dependencies>
    
        <!-- SpringBoot的依赖配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.5.14</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        
        <!-- 阿里数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
        
        <!-- 阿里JSON解析器 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>

        <!-- 定时任务-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-quartz</artifactId>
            <version>${ruoyi.version}</version>
        </dependency>

        <!-- 代码生成-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-generator</artifactId>
            <version>${ruoyi.version}</version>
        </dependency>

        <!-- 核心模块-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-framework</artifactId>
            <version>${ruoyi.version}</version>
        </dependency>

        <!-- 系统模块-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-system</artifactId>
            <version>${ruoyi.version}</version>
        </dependency>

        <!-- 通用工具-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-common</artifactId>
            <version>${ruoyi.version}</version>
        </dependency>

    </dependencies>
</dependencyManagement>

(11)dependencies

  • 含义:依赖,里面最基本的也要写上gav,当然你看到下面有些依赖没有version,那是因为它们会从父模块的dependencyManagement元素中继承version;当然,除了gav坐标之外,还有其他元素可以写在dependency依赖里面,这些元素还有type、scope、optional、exclusions
  • 示例:
<dependencies>

    <!-- SpringBoot集成thymeleaf模板 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- spring-boot-devtools -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional> <!-- 表示依赖不会传递 -->
    </dependency>

    <!-- swagger3-->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-boot-starter</artifactId>
    </dependency>

    <!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
    <dependency>
        <groupId>io.swagger</groupId>
        <artifactId>swagger-models</artifactId>
        <version>1.6.2</version>
    </dependency>

    <!-- Mysql驱动包 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- 核心模块-->
    <dependency>
        <groupId>com.ruoyi</groupId>
        <artifactId>ruoyi-framework</artifactId>
    </dependency>

    <!-- 定时任务-->
    <dependency>
        <groupId>com.ruoyi</groupId>
        <artifactId>ruoyi-quartz</artifactId>
    </dependency>

    <!-- 代码生成-->
    <dependency>
        <groupId>com.ruoyi</groupId>
        <artifactId>ruoyi-generator</artifactId>
    </dependency>

</dependencies>
  • version为什么可以省略:那是因为当前这个是子模块,然后在父模块的dependencyManagement元素中已经定义了gav坐标,所以子模块在继承模块之后,就只用写ga就可以了,version直接从父模块那获取了
  • 其他元素的用法:
    • type:依赖类型,这是对应依赖的打包类型,默认是jar,不过有些情况需要指定,示例如下:

      <!-- SpringBoot的依赖配置-->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-dependencies</artifactId>
          <version>2.5.14</version>
          <type>pom</type>
          <scope>import</scope>
      </dependency>
      
    • scope:依赖范围,用来控制依赖于编译、测试、运行时环境的关系,详情请看上面的依赖范围一节

    • optional:标记依赖是否可选,例如模块A依赖于模块B,而模块B依赖于模块X和Y,不过模块X和Y不能共存,比如模块B是一个持久层框架,而模块X和模块Y分别是mysql和Oracle的依赖包,这个时候就要对模块B中的依赖X和依赖Y使用可选依赖了,这种依赖方式不会影响模块B对模块X和模块Y的使用,也不影响模块A依赖于模块B时产生依赖冲突,并且能给模块A提供具体持久层实现的参考,由于可选依赖无法传递,所以需要在模块A中显示生命模块X和模块Y

    • exclusions:排除相关依赖,大家都知道,Maven解析之后的依赖中,不会出现groupId和artifactId相同,但是version不同的两个依赖,如果我们想让Maven按照我们的要求去生成依赖jar包,这个时候就需要告诉Maven我们想要的依赖是哪一个。想要达到这个目的,我们就必须知道依赖调节原则,详情请看上面的依赖调节一节

(12)build

1)finalName

  • 含义:打成jar包或者war包的包名,默认值是artifactId-version.打包方式,现在就变成了finalName.打包方式
  • 用法:对于maven项目,Dockerfile中启动命令一般写的是java -jar XXX.jar,如果按照默认打包方式,那么当我们更改项目version的时候还需要去更改Dockerfile中的jar包名称,这个好麻烦的,如果我们自定义finalName值,那么当我们修改version的时候就不用修改Dockerfile中的jar包名称了
  • 示例:
<build>
    <finalName>${project.artifactId}</finalName>
</build>

关系图如下:

在这里插入图片描述

2)sourceDirectory

  • 含义:自定义源代码目录

  • 作用:公司之前有些老项目的源代码是写在source目录下面的,而不是src/main/java,但是不太像更改了,免得改错了,因此就需要设置该参数

  • 注意:根据Maven约定优于配置的原则,默认情况下maven在超级pom中已经定义了源代码目录(src/main/java)、编译输出目录(target/classes)、打包方式(jar)、包输出目录(target)。如果仅仅是因为喜好,那就不要耍个性,个性往往意味着牺牲通用性,意味着增加无谓的复杂度。

  • 示例:

    <build>
        <sourceDirectory>source</sourceDirectory>
    </build>
    

3)resources

  • 含义:自定义主资源文件目录

  • 作用:公司有些项目中的配置文件没有写到src/main/resources目录下面,而是放在config下面,所以就需要自定义主资源文件目录

  • 示例:

    <build>
    	<resources>
    		<resource>
    			<directory>config</directory>
    			<excludes>
    				<exclude>**/*.java</exclude>
    			</excludes>
    		</resource>
    	</resources>
    </build>
    
  • 关系图如下:
    在这里插入图片描述

  • resources资源目录过滤
    在上面已经讲述了Maven属性的作用,也知道了只有在pom.xml中的Maven属性也可以被自动解析,而src/main/resources中文件的Maven属性无法被自动解析,所以我们就需要指定需要被解析的资源目录中的文件
    只要我们指定了resource资源目录的位置,那就会覆盖超级Pom中的resource资源目录的位置。既然我们想指定过滤的资源目录中的文件,那就需要加上filtering属性,并且设置为true,默认是false的。
    在下面我们介绍为主资源目录和测试资源目录开启过滤的示例:
    在这里插入图片描述
    在这里插入图片描述
    当然也可以配置多个资源目录,并为其开启 / 不开启过滤,如下:
    在这里插入图片描述
    在这里插入图片描述

  • web资源目录过滤
    对于web项目,不仅存在src/main/resources资源目录,而且还存在另外一类web资源文件src/main/webapp,有些情况下,我们也需要对web资源文件开启过滤。
    书中提到“读者需要区分Web项目中一般资源文件和web资源文件,前者是通过maven-resource-plugin处理的,而后者是通过maven -war-plugin处理的。”,写法如下:
    在这里插入图片描述

4)plugin

插件我也不在懂,所以把经常使用的插件列表给大家列一下
在这里插入图片描述
在这里插入图片描述
在上面我们还讲述了生命周期和插件的关系,以及插件的详细信息

(13)profiles

详细使用方法参考上面讲述的settings.xml中的profiles元素用法,用法都是一致的,不过该元素很少在pom.xml中使用

(14)distributionManagement》repository

  • 含义:定义发布版本部署仓库,也就是把正式版本jar包发送到maven私服,不区分jar包是普通项目还是maven插件
    可以参考pom.xml中的想把普通业务jar包或者Maven插件jar包发送到Maven私服中,应该怎么配置这一节

  • 示例:
    里面的ip是我自己搭建的nexus—Maven私服,id中指代的账户信息也在settings.xml中写的有

    <distributionManagement>
        <repository>
            <id>admin</id>
            <url>http://192.168.139.133:31743/repository/test-dev/</url>
        </repository>
        <snapshotRepository>
            <id>admin</id>
            <url>http://192.168.139.133:31743/repository/test-snapshot/</url>
        </snapshotRepository>
    </distributionManagement>
    

(15)distributionManagement》snapshotRepository

  • 含义:定义快照版本部署仓库,也就是把快照版本jar包发送到maven私服,不区分jar包是普通项目还是maven插件
    可以参考pom.xml中的想把普通业务jar包或者Maven插件jar包发送到Maven私服中,应该怎么配置这一节
  • 示例
    里面的ip是我自己搭建的nexus—Maven私服,id中指代的账户信息也在settings.xml中写的有
    <distributionManagement>
        <repository>
            <id>admin</id>
            <url>http://192.168.139.133:31743/repository/test-dev/</url>
        </repository>
        <snapshotRepository>
            <id>admin</id>
            <url>http://192.168.139.133:31743/repository/test-snapshot/</url>
        </snapshotRepository>
    </distributionManagement>
    

(16)repositories》repository

  • 含义:下载普通项目(非Maven插件)依赖的仓库,不区分发布版本依赖和快照版本依赖
  • 示例:
    我们用若依父pom.xml来举例,如下:
    在这里插入图片描述

(17)pluginRepositories》pulginRepository

  • 含义:下载Maven插件(非普通项目)依赖的仓库,不区分发布版本依赖和快照版本依赖
  • 示例:
    我们用若依父pom.xml来举例,如下:
    在这里插入图片描述

六、Maven插件

1、作用

一次编写,多人使用,减少重复编码过程

比如:

  • 编写统计代码行数的插件
  • 在项目中生成Dockerfile、Jenkinsfile、YamlStatefulSet.yaml,并且在Jenkins中添加相关任务的插件

2、注意点

  • 打包方式:打包方式需要是maven-plugin,即pom.xml中要配置<packaging>maven-plugin</packaging>

  • 常用依赖:

    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-plugin-api</artifactId>
        <version>3.6.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven.plugin-tools</groupId>
        <artifactId>maven-plugin-annotations</artifactId>
        <version>3.6.0</version>
        <scope>provided</scope>
    </dependency>
    
  • 插件前缀设置:
    下面的generate元素值就是插件前缀,默认插件前缀是artifactId

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.6.4</version>
                <configuration>
                    <goalPrefix>generate</goalPrefix>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

    来看默认插件前缀是artifactId的情况,如下:
    在这里插入图片描述
    再来看插件前缀是我们指定的情况,如下:
    在这里插入图片描述

  • 插件目标类、插件目标名称、默认绑定的生命周期阶段设置:
    在这里插入图片描述

  • @Parameter注解的使用方法

    • defaultValue:默认值,可以使用Maven属性,这个名词可以全局搜索下,在pom.xml中详细解释
    • readonly:只读,也就是用户无法通过configuration元素中配置值
    • required:必填,也就是这个属性必须有值,无论是用户自己填的,还是默认值
    • name:名称,如果不设置的话,默认情况下configuration元素中可以使用属性名称,设置的话也可以使用name值
    • alias:别名,如果参数名称/name值太长了,定义别名之后可以在configuration元素中使用别名。其中属性名称、name、alias三种设置方法都是可以共存的,都可以在configuration元素中使用
  • 插件目标类中定义的属性如何在使用创建的项目pom.xml中定义:

    在这里插入图片描述

  • 插件目标类属性种类:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3、和普通Maven项目的区别

在代码编写上,没啥太大区别,该怎么写就怎么写就行了,然后在发布到Maven私服的时候也没啥区别,不过在下载的时候有区别,需要在settings.xml中进行特殊配置,可以看setting.xml中的第二个讲解内容

4、示例

  • 计算代码行数:
    链接:https://pan.baidu.com/s/1cWmDpuVNu5fXIkDOfhrXyg?pwd=nkxl
    提取码:nkxl
  • 生成项目地址文件:
    链接:https://pan.baidu.com/s/10UlfU_ugy3N60EbvKAD4yA?pwd=emd9
    提取码:emd9

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/760182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

easyrecovery数据恢复软件2023免费版下载

easyrecovery数据恢复软件2023免费版下载是一款操作简单、功能强大数据恢复软件,通过easyrecovery可以从硬盘、光盘、U盘、数码相机、手机等各种设备中恢复被删除或丢失的文件、图片、音频、视频等数据文件。 EasyRecovery数据恢复软件是一款功能强大的数据恢复软件&#xff0c…

卡尔曼滤波的理解

看了B站up主DR_CAN讲的卡尔曼滤波&#xff08;链接&#xff09;。up讲的非常好&#xff0c;强烈推荐&#xff0c;看完终于明白了卡尔曼滤波的奥秘。下面是我对其中内容的注解&#xff0c;或者说自己的理解。大部分推导省略了&#xff0c;但保留了算法的思想脉络。 引入 首先看…

Verilog基础之十七、锁相环PLL

目录 一、前言 1.1 背景 1.2 PLL结构 二、工程设计 2.1 PLL IP核配置 2.2 设计代码 2.3 测试代码 2.4 仿真结果 2.5 常见问题 一、前言 1.1 背景 若将一个FPGA工程看做一个人体&#xff0c;时钟的重要性丝毫不亚于心脏对于人体的重要性&#xff0c;时钟的每一个周期对…

支付、购物车、搜索、文件上传、登录、还款、订单测试怎么做?

支付功能怎么测试&#xff1a;1、从功能方面考虑&#xff1a; 1&#xff09;、正常完成支付的流程&#xff1b; 2&#xff09;、支付中断后继续支付的流程&#xff1b; 3&#xff09;、支付中断后结束支付的流程&#xff1b; 4&#xff09;、单订单支付的流程&#xff1b; 5&am…

【无标题】(前沿)

Java编程语言 目前为止最流行的 是Java编程语言 但是编程与语言有很多中php。phyone。 c c. c# java html. css javascript vue() 说到计算机有很多同学会说&#xff0c;就有很多人会说35的节点&#xff0c;我问一下同学们现在哪一个行业&#xff0c;是没有35岁的节点&#x…

7.5 SpringBoot 拦截器Interceptor实战 统一角色权限校验

文章目录 前言一、定义注解annotation二、拦截角色注解1. 在拦截器哪里拦截&#xff1f;2. 如何拦截角色注解&#xff1f;3. 角色如何读取?4. 最后做角色校验 三、应用&#xff1a;给管理员操作接口加注解四、PostMan测试最后 前言 在【7.1】管理员图书录入和修改API&#xf…

c语言指针进阶(二)

目录 引言 函数指针数组 指向函数指针数组的指针 回调函数 引言 大家好&#xff0c;我是c语言boom成家宝&#xff0c;今天博主带来的依然是指针的进阶讲解。上一篇博客博主有介绍指针&#xff0c;数组指针&#xff0c;指针数组&#xff0c;以及函数指针的概念以及应用&…

【Azure】Azure成本管理:规划、监控、计算和优化成本 [文末送书]

开篇先来一个不是总结的总结&#xff1a;平衡成本与性能始终是一个重大挑战。&#xff08;此处省略各种场景的解释&#xff09; 文章目录 前言一、Azure 成本管理工具1.1 什么是成本管理1.2 成本管理的主要功能 二、Azure 中可能影响成本的因素2.1 影响成本的因素2.1.1 资源类型…

leetcode|math|9.172.69.50.

9. Palindrome Number to_string 就行 172. Factorial Trailing Zeroes 不能直接乘起来&#xff0c;会overflow&#xff01;&#xff01; 166! 就是要找166乘到1一共有几个5。5&#xff0c;10&#xff0c;15&#xff0c;25...都算。166/5就是算一共有几个5。但是25其实贡献了…

【周末闲谈】感受AI时代魅力,创意无界限

i 个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 文章目录 前言人工智能的应用领域问题求解逻辑推理与定理证明自然语言处理智能信息检索技术专家系统 人工智能的三大短板展望未来从专用智能向通用智能发展从人工智能向人机混合智能发展…

Jdk 版本升级

Jdk 版本升级(多版本配置&#xff09; 一、配置多版本 首先如果系统第一次安装JDK 1.登录oracle官网Java Downloads | Oracle下载&#xff0c;此教程以Jdk1.8为例&#xff0c;一键下一步即可安装成功。 2.配置环境变量 然后在系统path路径中添加&#xff1a; %JAVA_HOME%…

单片机第一季:零基础10——串口通信和RS485

目录 1&#xff0c;串口通讯基础 1.1&#xff0c;同步和异步 1.2&#xff0c;并行和串行 1.3&#xff0c;单工、半双工与全双工通信 1.4&#xff0c;通信速率 2&#xff0c;单片机串口通讯 2.1&#xff0c;接口标准 2.2&#xff0c;通讯协议 2.3&#xff0c;串口…

834. 树中距离之和

给定一个无向、连通的树。树中有 n 个标记为 0…n-1 的节点以及 n-1 条边 。 给定整数 n 和数组 edges &#xff0c; edges[i] [ai, bi]表示树中的节点 ai 和 bi 之间有一条边。 返回长度为 n 的数组 answer &#xff0c;其中 answer[i] 是树中第 i 个节点与所有其他节点之间…

opencv环境搭建

1. 上网&#xff08;你懂的&#xff0c;没有网装不了&#xff09; 2. 参考视频&#xff1a;https://www.bilibili.com/video/BV1R44y157hW/?spm_id_from333.880.my_history.page.click&vd_source377867a48dd3d812b9d6521c8fc76de2 3. 这里我选择的是4.8的版本。 4. cmak…

charles中下载web证书

1.点击help&#xff0c;选中ssl Proxying ,点击Install Charles Root Certificate 2:点击”安装证书”按钮 3&#xff1a;点击”下一步”按钮 4&#xff1a;选中”将所有的证书都放入下列存储”&#xff0c;点击”游览”按钮 5&#xff1a;选中”受新任的根证书颁发机构”&…

day37-框架

0目录 框架 1.框架介绍 2. SSM三大框架简介 3.Mybatis 4.拓展 1.框架介绍 1.1 为什么使用框架&#xff1f; &#xff08;1&#xff09;框架效率高&#xff0c;成本低 &#xff08;2&#xff09;框架是别人写好的构建&#xff0c;我们只需学会如何使用它&#xff08;可维护性…

C++(12):动态内存

除了自动和static对象外&#xff0c;C还支持动态分配对象。动态分配的对象的生存期与它们在哪里创建是无关的&#xff0c;只有当显式地被释放时&#xff0c;这些对象才会销毁。 静态内存 用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量。 栈内存 用来…

mysql_to_clickhouse同步方案调研

调研时间&#xff1a;2021年08月&#xff0c;之后是否出现优化方案未知 方式1&#xff1a;网上开源python脚本-----mysql-clickhouse-replication 安装参考&#xff1a;https://www.cnblogs.com/gomysql/p/11199856.html 软件路径&#xff1a;https://github.com/yymysql/my…

【C++STL】模拟实现vector容器

文章目录 前言一、vector的成员函数二、增删查改工作说明size()和capapcity()2.1reserve()2.2 resize&#xff08;&#xff09;2.3 insert()2.4 erase&#xff08;&#xff09;2.5 push_back&#xff08;&#xff09;和pop_back&#xff08;&#xff09; 三、[]重载和迭代器3.1…

ahut 周赛3

A.gzm判试卷 AhutOj 线段树(注意,一定要开到4*N,不然会RE) 单点更新(求区间最值) 单点更新不需要懒标记,区间修改是大量的点,需要懒标记 AC代码: #include<iostream> #include<algorithm> #include<cstring> #include<cmath> using namespace st…