springcloud:maven快速上手 | maven常用标签(十三)

0. 引言

最近发现有同学在搭建微服务项目时,对于pom中的依赖管理的非常的混乱,并且对于maven的理解也没有系统的掌握。因此特出一章针对maven的入门简介,后续再讲讲微服务项目中如何对pom进行优雅的依赖管理。

:本文不会针对maven的所有标签做介绍,更多以最常用的标签引入,向大家作介绍,如果想要了解全部标签可以查看maven官网

1. maven简介

1.1 什么是maven

maven是apache开源的一款项目管理工具。它使用项目对象模型(Project Object Model)的概念,通过一小段描述信息来管理项目的构建。

所以你知道pom文件的代表的含义是什么了吧,就是项目对象模型。这里的一小段描述信息就是我们常写在pom中的dependency

<dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
</dependency>
复制代码

在没有maven之前我们要声明引用一个jar包时,得在libraries中手动导入。一个两个还好,当引入的外部jar包成百上千时,这样手动的方式实在太麻烦,而且还不太好管理。当maven引入之后,我们只需要在pom文件中声明jar的依赖,即可自动引入该jar 在这里插入图片描述

1.2 maven仓库

maven中有两种仓库:本地仓库和远程仓库

  • 本地仓库

所谓本地仓库,就是你本机中的一个文件夹,你在项目中引入的jar会下载到该文件夹中,之后项目的引用实际上就是从这个文件夹中引入的

我们可以在IDEA>settings中看到maven的仓库地址。这里需要注意的是IDEA模式是自带了maven的,如果你想要使用自己下载的maven,那么也需要在这里将maven home path修改为你的安装路径 在这里插入图片描述 我们打开看一下,会发现其文件结构就是我们在pom中声明的groupId+artifactId+version。真正引用的就是里面的.jar文件。

因此当我们在项目中出现xxx程序包不存在时可以先去本地仓库中对应路径下检查.jar文件是否存在,如果不存在说明压根没有下载成功。可以通过更换国内镜像地址后重新下载 在这里插入图片描述

  • 远程仓库

远程仓库又分为私有远程仓库和中央远程仓库

所谓私有远程仓库是指公司或者个人在服务器上搭建的远程仓库,用于存放公司内部常用或者自己打包的jar包,方便内部开发使用的。而中央远程仓库就是我们默认的apache所提供的远程仓库,基本上所有的公开的jar包都能在上面下载到。

1.3 国内镜像地址

默认的中央远程仓库地址是apache提供的,因为部分政策原因,外网地址在国内访问一直不稳定,因此国内一些大公司比如阿里、网易都提供了maven镜像地址,这样我们下载就是从国内的站点下载的,速度会快很多

其配置方法,就是在maven的settings.xml文件中配置如下内容:

<mirrors>
    <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus aliyun</name>
        <url>https://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror>
</mirrors>
复制代码

settings.xml文件位置可以在上述截图的settings>Build,Execution,Deployment>Build Tools>Maven中找到 在这里插入图片描述

1.4 仓库优先级

本地仓库 > 配置文件中配置的镜像仓库 > 默认的apache中央仓库

pom中添加的依赖,默认会先到本地仓库中寻找,如果找到就将jar引用到项目中,如果找不到就会去配置文件中配置的镜像仓库中下载到本地,如果下载不到或者没有配置镜像仓库,就会去apache中央仓库下载到本地

1.5 依赖优先级

maven项目依赖采取“最短路径优先”原则:意味着项目依赖关系树中路径最短的版本会被使用。

比如:A,B,C之间的依赖关系是A->B->C->D(2.0),A,E之间的依赖关系是A->E->D(1.0)。那么A中D(1.0)会被使用,因为A-E-D路径更短

1.6 依赖传递

pom的依赖具有传递性,简单来说如果项目A中引入mysql依赖,如果项目B引入来项目A,那么项目B自然继承了A中的mysql依赖

我们常常利用这个特性,将通用的依赖放到父项目或者一个单独的common项目中,然后通过引入这个项目来实现依赖的统一引入,也方便管理。

1.7 聚合项目

所谓聚合项目,就是指将公用的pom依赖抽离到一个单独的项目中,其他项目通过引入这个单独的项目从而实现依赖的统一管理,这个单独的项目就称为聚合项目

比如项目A,B,C中都需要引入mysql,mybatis,spring web依赖,我们现在创建一个项目common,在这个项目中添加依赖mysql,mybatis,spring web。然后项目A,B,C中就只需要引入项目common就能实现一次引入上述的所有依赖的

这样做的好处是统一管理,方便调整。

2. pom常用标签

下面我们来介绍一下pom文件中的常用标签:

2.1 基础标签

  • groupId:组织ID,对应java的包结构,比如项目src.main.java目录下的结构是com.example.xxx那么这里的groupid就是com.example.xxx
  • artifactId:项目ID,一般对应项目名,也就是com.example.xxx中的xxx
  • version:版本号,通过不同的版本号来声明项目的迭代升级
  • name:项目名称,其作用是在maven中显示的名称,一般与artifactId保持一致即可
  • description:项目描述,针对项目的简单描述,非比填
  • packaging:打包方式,maven支持的打包方式为pom,jar,war,默认为jar。下面我们详细介绍
  • modelVersion:当前POM模型的版本,maven2和maven3中只能是4.0.0
  • parent:声明父项目,通过声明父项目可以使用父pom中的依赖和属性,这个后续我们会实际演示
  • properties:声明的属性集,可以将版本号统一属性,然后通过调用属性来间接声明版本号
  • dependencies:引入的依赖集
  • modules:声明子模块
  • build:声明项目如何编译打包项目,以及使用的编译插件
  • dependencyManagement:针对maven依赖进行版本管理

2.1.1 maven支持的打包方式

  • jar:默认的打包方式,常见的项目都会打包成jar包
  • pom:逻辑工程,用在父级工程和聚合工程中,用来做jar包的版本控制和统一管理,这种项目中不会书写任何代码
  • war:用来发布至web服务器上的项目,比如tomcat。但现在springboot项目已经内置了tomcat,其jar包中包含了tomcat,所以war包相对使用的很少了。

2.2 dependency标签

dependency标签用来声明我们需要引入的jar包,

<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
</dependency>
复制代码

不知道依赖地址的话,我们可以从maven依赖查询中查询我们需要的依赖 在这里插入图片描述 这个网站因为是外网的,有时也不太稳定,可以在idea中下载Maven Search插件搜索 在这里插入图片描述

2.2.1 依赖排除exclusion

当我们引入的是一个项目,其项目以及包含了多个依赖,但其中某几个依赖我们不需要时,就可以通过exclusion标签来将其排除,如下

<dependency>
    <groupId>com.wu</groupId>
    <artifactId>user-server</artifactId>
    <version>0.0.1-SNAPSHOT</verison>
    <exclusions>
        <exclusion>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </exclusion>
    </exclusions>
</dependency>
复制代码

2.2.2 去除依赖传递optional

如果项目B引用了项目A,项目A中的部分依赖项目B是不需要使用的。那么就需要在项目A中将这部分依赖添加上<optional>true</optional>。表明这部分依赖是可选依赖,如果要在项目B中使用这些依赖,需要显示声明这些依赖

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
 </dependency>
复制代码

2.3 properties标签

用于声明pom中依赖的版本声明为属性,后续通过调用属性来实现统一的版本管理

比如:

 <properties>
        <seata-version>1.4.0</seata-version>
    </properties>
复制代码

依赖声明时使用${属性名}来声明版本:

<dependencies>
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>${seata-version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>${seata-version}</version>
        </dependency>

    </dependencies>
复制代码

2.4 dependencyManagement标签

该标签用于进行统一的依赖版本管理,在其中声明依赖的版本,后续的项目中就不需要声明版本了,会自动使用这里声明的版本号

常常结合properties标签使用

<properties>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
        <spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version>
</properties>
    
<dependencyManagement>
        <dependencies>
            <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>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>
复制代码

dependency中声明依赖时,就不用再声明版本号了

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
</dependencies>
复制代码

2.4.1 依赖范围

在dependency中可以在scope标签中定义依赖的作用范围,以此定义依赖在什么时候生效

<dependency>
    <groupId>com.wu</groupId>
    <artifactId>user-server</artifactId>
    <version>0.0.1-SNAPSHOT</verison>
    <scope>compile<scope>
</dependency>
复制代码
  • compile: 在编译和运行时都有效,默认配置

  • provided: 在编译和运行时都需要该依赖,但在运行项目时由于容器已经提供了,所以不需要maven重复引入,比如servlet-api

  • runtime: 编译时不需要生效,只在运行时生效。典型的例子时JDBC的驱动器

  • system: 系统范围与provided类似,不过你必须显示的指定一个本地系统路径的jar。此类依赖应该一直有效,maven也不会去仓库中寻找它。但是,在使用system范围依赖时,必须通过systemPath显示地指定依赖文件的路径

  • test: 只在编译测试代码和运行测试的时候需要,应用的正常运行不需要

  • import: 只适用于pom文件中的部分,表明指定的pom必须使用中声明的版本,import只能用在dependencyManagement的scope里

当需要规定子工程只能使用父工程中在dependencyManagement中声明的版本号时,就可以通过在对用的依赖下添加import来实现

2.4.2 type标签

我们上述的案例在dependencyManagement中声明了一个<type>pom</type>,那么这个标签是什么作用呢? 依赖类型,我们可以在<dependency>标签中通过<type>标签来声明依赖的类型,默认是jar。也就是我们要引入的依赖的文件的拓展名,通常这个类型与依赖的打包方式保持一致。

比如我们要引入mybatis-plus的jar包,那么其依赖的type就一定是jar

但可以看到我们在上述的案例中引入的spring-boot-dependencies的type是pom,这个引入的是什么东西呢?因为我们之前说过pom一般用于父项目和聚合项目

<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
</dependency>
复制代码

其实我们只要点开这个依赖就知道了

它就是一个聚合项目,帮我们定义了springboot项目相关依赖的版本号。如此就不用我们再手动实现这些依赖的版本管理了。是不是很贴心。 在这里插入图片描述

2.5 build标签

一般build都是配置好的不需要自己写,如果有需要单独配置的,多数情况是到网上查找固定的写法,拷贝即用。但是我们还是要掌握build中常用标签的含义

build标签下主要包含以下几种子标签:

  • plugins:声明maven插件,后续会详细说明
  • resources:声明资源文件存放路径,所谓资源文件就是.xml.properties文件,资源文件默认的路径在resources文件夹下,但有时我们需要将这些资源文件提到java文件夹下,比如mapper.xml文件,这时我们就需要在pom中的resources下声明路径
  • defaultGoal:执行构建时默认的goal,什么是goal?这个下面详细说明
  • directory:编译的项目文件的输出路径,默认为${basedir}/target路径
  • finalName:打包文件名

2.5.1 resources标签

  • targetPath: 资源文件的目标路径
  • filtering:构建过程是否对资源进行过滤,默认false
  • directory:资源文件路径,默认为${basedir}/src/main/resources
  • includes:包含的资源文件集合
  • excludes:不包含的资源文件集合,可以设置排除掉哪些资源文件
<resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
</resources>
复制代码

2.5.2 plugins标签

  • groupId:插件组织ID
  • artifactId:插件ID
  • version:版本号
  • extensions:声明插件的某个goal的执行方式,这个要先理解什么是goal,我们在下一小节讲述
  • configuration: 该插件所需要的特殊配置
  • dependencies:该插件所需要的依赖类库
  • testResources:测试过程涉及的资源文件,默认在${basedir}/src/test/resources下。不会被编译到包中
<plugins>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
</plugins>
复制代码

plugins标签即使不添加,也会默认添加如下插件

插件 作用
maven-clean-plugin 清理上一次执行创建的目标文件
maven-resources-plugin 处理资源文件和测试资源文件
maven-compiler-plugin 编译源文件和测试源文件
maven-surefire-plugin 执行测试文件
maven-jar-plugin 打包jar
maven-install-plugin 安装jar,将生成的jar放到本地仓库中
maven-deploy-plugin 发布jar
### 2.5.3 什么是插件的goal?
maven中的插件以jar的方式存在于maven仓库中,通过坐标(groupId+artifactId+version)进行访问。一个插件包含了多个功能,插件中的每个功能就叫做插件的目标(goal)

如何查看插件的goal呢? 我们可以在idea的maven的plugins中查看,如图所示 在这里插入图片描述

3. maven常用指令

  • install

编译、打包

  • compile

只编译

  • package

编译、打包

  • deploy(很少使用)

编译、打包 会部署到maven本地仓库以及maven远程私服仓库

install和package的区别?

package完成了项目编译、单元测试、打包功能。但是没有把打好的可执行jar包(/war包)部署到本地maven仓库和远程maven私服仓库 install会部署到maven本地仓库,但是不会部署到maven远程私服仓库

下期预告

springcloud:微服务项目中如何对pom进行优雅的依赖管理

猜你喜欢

转载自juejin.im/post/7097221123040870407