Maven 介绍
什么是 Maven
Maven 是基于我的项目对象模型(POM project object model),能够通过一小段形容信息(配置)来治理我的项目的构建,报告和文档的软件项目管理工具,简略的说就是用来治理我的项目所须要的依赖且治理我的项目构建的工具。
Maven 的装置与配置
- 从 Maven 官网下载压缩包,解压到本地。
- 配置环境变量
MAVEN_HOME
为 Maven 的解压目录。 - 增加 Maven 目录下的 bin 目录到环境变量
PATH
中。 - 能够在 Maven 目录下的 conf/setting.xml 文件中,通过
<localRepository />
来指定本地仓库门路。 - 关上终端,输出
mvn -version
验证时是否胜利。
Idea 中配置本地装置的 Maven
关上 Idea 的配置面板,找到 Maven 配置页。
Maven home directory
:设置为本地的 Maven 门路User settings file
:勾选前面的 Override 能够自定义 settings 文件,能够指向 Maven 门路下的conf/settings.xml
Local repository
:勾选 Override 同样能够自定义仓库门路,默认会从配置的 settings 文件中读取。
Maven 坐标与依赖
坐标
Maven 通过 groupId、artifactId、version 三个变量来惟一确定一个具体的依赖,俗称 GAV。
依赖
在 pom.xml 中咱们通过 dependency 来申明坐标信息(GAV),如咱们须要申明对 4.2.6.RELEASE 版本 spring-core 包的依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
依赖 scope
- compile:编译依赖范畴,在编译,测试,运行时都须要,依赖范畴默认值
- test:测试依赖范畴,测试时须要。编译和运行不须要,如 junit
- provided:已提供依赖范畴,编译和测试时须要。运行时不须要,如 servlet-api
- runtime:运行时依赖范畴,测试和运行时须要。编译不须要,例如面向接口编程,JDBC 驱动实现 jar
- system:零碎依赖范畴。本地依赖,不在 Maven 地方仓库,联合 systemPath 标签应用
依赖排除
应用 <exclusions>
标签下的 <exclusion>
标签指定 GA 信息来排除,例如:排除 xxx.jar 传递依赖过去的 yyy.jar
<dependency>
<groupId>com.xxx</groupId>
<artifactId>xxx</artifactId>
<version>x.version</version>
<exclusions>
<exclusion>
<groupId>com.xxx</groupId>
<artifactId>yyy</artifactId>
</exclusion>
</exclusions>
</dependency>
依赖关系查看
进入工程根目录,在命令行中运行
mvn dependency:tree
命令会列出依赖关系树及各级依赖关系mvn dependency:analyze
剖析依赖关系
Maven 我的项目的构造
Maven 我的项目有其余规范的目录组织构造,如上图所示:
|- project: 我的项目目录
|- src: 源码目录
|- src/main/java: 我的项目 java 源码文件寄存目录
|- src/main/resources: 我的项目资源文件寄存目录
|- src/test/java: 我的项目单元测试源码文件寄存目录
|- src/test/resources: 我的项目单元测试资源文件寄存目录
|- target: 我的项目编译 / 打包后寄存的指标门路
|- pom.xml: 我的项目依赖治理配置文件
Maven 的生命周期
Maven 有 3 套生命周期,每套生命周期都蕴含了一些阶段,这些阶段是有序的,前面的阶段依赖后面的阶段。这三套生命周期是互相独立的,能够仅仅调用 clean 生命周期的某个阶段,或者调用 default 生命周期的某个阶段,而不会对其余生命周期产生任何影响。
- clean:清理我的项目
-
default:构建我的项目
- compile:编译我的项目的源代码
- package:打包编译好的代码
- install:将包装置至本地仓库,提供给其余我的项目依赖
- deploy:将最终的包复制到近程的仓库,提供给其余开发人员和我的项目共享。
- site:建设我的项目站点
生命周期的执行:
# 清理我的项目
mvn clean
# 打包我的项目
mvn package
# 打包并装置到本地仓库
mvn install
能够组合各阶段进行执行:
# 清理我的项目后打包并公布到近程仓库
mvn clean package deploy
settings 文件详解
settings 文件的作用
settings 是用来设置 Maven 参数的配置文件,并且,settings.xml 是 Maven 的全局配置文件。settings.xml 中蕴含相似本地仓库、近程仓库和联网应用的代理信息等配置。
settings 文件的地位
全局配置:${MAVEN_HOME}/conf/settings.xml
用户配置:${user.home}/.m2/settings.xml
settings 文件配置优先级
其实绝对于多用户的 PC 机而言,在 Maven 装置目录的 conf 子目录上面的 settings.xml 才是真正的全局的配置。而用户目录的 .m2 子目录上面的 settings.xml 的配置只是针对以后用户的。当这两个文件同时存在的时候,那么对于雷同的配置信息用户目录上面的 settings.xml 中定义的会笼罩 Maven 装置目录上面的 settings.xml 中的定义。用户目录下的 settings.xml 文件个别是不存在的,然而 Maven 容许咱们在这里定义咱们本人的 settings.xml,如果须要在这里定义咱们本人的 settings.xml 的时候就能够把 Maven 装置目录上面的 settings.xml 文件拷贝到用户目录的 .m2 目录下,而后改成本人想要的样子。
settings.xml 元素
顶级元素概览
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository/>
<interactiveMode/>
<usePluginRegistry/>
<offline/>
<pluginGroups/>
<servers/>
<mirrors/>
<proxies/>
<profiles/>
<activeProfiles/>
</settings>
LocalRepository
该值示意构建零碎本地仓库的门路。其默认值:~/.m2/repository
。
Servers
个别,仓库的下载和部署是在 pom.xml 文件中的 repositories 和 distributionManagement 元素中定义的。然而,个别相似用户名、明码(有些仓库拜访是须要平安认证的)等信息不应该在 pom.xml 文件中配置,这些信息能够配置在 settings.xml 中。
<!-- 配置服务端的一些设置。一些设置如平安证书不应该和 pom.xml 一起散发。这种类型的信息应该存在于构建服务器上的 settings.xml 文件中。-->
<servers>
<!-- 服务器元素蕴含配置服务器时须要的信息 -->
<server>
<!-- 这是 server 的 id(留神不是用户登陆的 id),该 id 与 distributionManagement 中 repository 元素的 id 相匹配。-->
<id>server001</id>
<!-- 鉴权用户名。鉴权用户名和鉴权明码示意服务器认证所须要的登录名和明码。-->
<username>my_login</username>
<!-- 鉴权明码。鉴权用户名和鉴权明码示意服务器认证所须要的登录名和明码。明码加密性能已被增加到 2.1.0 +。详情请拜访明码加密页面 -->
<password>my_password</password>
<!-- 鉴权时应用的私钥地位。和前两个元素相似,私钥地位和私钥明码指定了一个私钥的门路(默认是 ${user.home}/.ssh/id_dsa)以及如果需要的话,一个密语。未来 passphrase 和 password 元素可能会被提取到内部,但目前它们必须在 settings.xml 文件以纯文本的模式申明。-->
<privateKey>${usr.home}/.ssh/id_dsa</privateKey>
<!-- 鉴权时应用的私钥明码。-->
<passphrase>some_passphrase</passphrase>
<!-- 文件被创立时的权限。如果在部署的时候会创立一个仓库文件或者目录,这时候就能够应用权限(permission)。这两个元素非法的值是一个三位数字,其对应了 unix 文件系统的权限,如 664,或者 775。-->
<filePermissions>664</filePermissions>
<!-- 目录被创立时的权限。-->
<directoryPermissions>775</directoryPermissions>
</server>
</servers>
Mirrors
用于定义一系列的近程仓库的镜像。对于一个 Maven 我的项目,如果没有特地申明,默认应用 Maven 的 central 库,url 为 http://repo.maven.apache.org/…。然而这些近程库往往须要连贯互联网拜访,因为拜访互联网的限度或安全控制的须要,在企业外部往往须要建设对近程库的镜像,即近程库的 mirror。
留神:
- 定义多个近程仓库镜像时,只有以后一个 mirror 无奈连贯的时候,才会去找后一个,相似于备份和容灾。
- mirror 也不是按 settings.xml 中写的那样的程序来查问的。所谓的第一个并不一定是最下面的那个。当有 id 为 B、A、C 的程序的 mirror 在 mirrors 节点中,Maven 会依据字母排序来指定第一个,所以不管怎么排列,肯定会找到 A 这个 mirror 来进行查找,当 A 无奈连贯,出现意外的状况下,才会去 B 查问。
Mirror
当 Maven 须要到的依赖 jar 包不在本地仓库时,就须要到近程仓库下载。这个时候如果 settings.xml 中配置了镜像,而且镜像配置的规定中匹配到指标仓库时,Maven 认为指标仓库被镜像了,不会再去被镜像仓库下载依赖 jar 包,而是间接去镜像仓库下载。简略而言,mirror 能够拦挡对近程仓库的申请,扭转对指标仓库的下载地址。
<mirrors>
<!-- 给定仓库的下载镜像。-->
<mirror>
<!-- 该镜像的惟一标识符。id 用来辨别不同的 mirror 元素。-->
<id>mirrorId</id>
<!-- 镜像名称 -->
<name>PlanetMirror Australia</name>
<!-- 该镜像的 URL。构建零碎会优先思考应用该 URL,而非应用默认的服务器 URL。-->
<url>http://downloads.planetmirror.com/pub/maven2</url>
<!-- 被镜像的服务器的 id。例如,如果咱们要设置了一个 Maven 地方仓库(http://repo.maven.apache.org/maven2/)的镜像,就须要将该元素设置成 central。这必须和地方仓库的 id central 完全一致。-->
<mirrorOf>repositoryId</mirrorOf>
</mirror>
</mirrors>
减速近程依赖的下载
应用镜像能够解决近程依赖下载慢的问题。
<mirrors>
<!-- 国内阿里云提供的镜像,十分不错 -->
<mirror>
<!--This sends everything else to /public -->
<id>aliyun_nexus</id>
<mirrorOf>central</mirrorOf>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
</mirrors>
在 settings.xml 中配置如上 mirrors,近程的依赖就会从阿里云镜像中下载。
高级镜像配置
为了满足一些简单的需要,Maven 还反对更高级的镜像配置:
<mirrorOf>*</mirrorOf>
:匹配所有近程仓库。<mirrorOf>external:*</mirrorOf>
:匹配所有近程仓库,应用 localhost 的除外,应用file://
协定的除外。也就是说,匹配所有不在本机上的近程仓库。<mirrorOf>repo1,repo2</mirrorOf>
:匹配仓库 repo1 和 repo2,应用逗号分隔多个近程仓库。<mirrorOf>*,!repo1</miiroOf>
:匹配所有近程仓库,repo1 除外,应用感叹号将仓库从匹配中排除。
案例
集体的 Maven 配置了阿里的镜像,而我的项目中须要应用到一些第三方 jar 包,为了不便引入,已上传到 192.168.0.201 的 nexus 私服下。但因为集体 Maven 阿里的镜像配置为 <mirrorOf>*</mirrorOf>
,所有的仓库都被镜像,不会再去 192.168.0.201 下下载第三方 jar 包。
上传的第三方 jar 包指标门路:
http://192.168.0.201:8081/nexus/content/groups/public/com/alipay/sdk-java/20170615110434/sdk-java-20170615110434.pom
被镜像后门路:
http://maven.aliyun.com/nexus…
所以须要批改镜像的 mirrorOf 规定,防止默认从镜像中下载。
Maven 的 conf/settings.xml
<mirrors>
<!-- 国内阿里云提供的镜像,十分不错 -->
<mirror>
<!--This sends everything else to /public -->
<id>aliyun_nexus</id>
<!-- 对所有仓库应用该镜像, 除了一个名为 maven_nexus_201 的仓库除外 -->
<!-- 这个名为 maven_nexus_201 的仓库能够在 javamaven 我的项目中配置一个 repository-->
<mirrorOf>*,!maven_nexus_201</mirrorOf>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
</mirrors>
Maven 我的项目下的 pom.xml 配置一个近程仓库
<repositories>
<!-- 192.168.0.201 近程仓库 -->
<repository>
<id>maven_nexus_201</id>
<name>maven_nexus_201</name>
<layout>default</layout>
<url>http://192.168.0.201:8081/nexus/content/groups/public/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
pom 文件详解
顶级元素概览
<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/maven-v4_0_0.xsd">
<parent />
<!-- 申明我的项目描述符遵循哪一个 POM 模型版本。模型自身的版本很少扭转,尽管如此,但它依然是必不可少的,这是为了当 Maven 引入了新的个性或者其余模型变更的时候,确保稳定性。-->
<modelVersion />
<groupId />
<artifactId />
<version />
<packaging />
<name />
<url />
<description />
<prerequisites />
<issueManagement />
<ciManagement />
<inceptionYear />
<mailingLists />
<developers />
<contributors />
<licenses />
<scm />
<organization />
<build />
<profiles />
<modules />
<repositories />
<pluginRepositories />
<dependencies />
<reports />
<reporting />
<dependencyManagement />
<distributionManagement />
<properties />
</project>
parent
<!-- 父我的项目的坐标。如果我的项目中没有规定某个元素的值,那么父我的项目中的对应值即为我的项目的默认值。坐标包含 group ID,artifact ID 和 version。-->
<parent>
<!-- 被继承的父我的项目的构件标识符 -->
<artifactId>xxx</artifactId>
<!-- 被继承的父我的项目的寰球惟一标识符 -->
<groupId>xxx</groupId>
<!-- 被继承的父我的项目的版本 -->
<version>xxx</version>
<!-- 父我的项目的 pom.xml 文件的相对路径。相对路径容许你抉择一个不同的门路。默认值是../pom.xml。Maven 首先在构建以后我的项目的中央寻找父我的项目的 pom,其次在文件系统的这个地位(relativePath 地位),而后在本地仓库,最初在近程仓库寻找父我的项目的 pom。-->
<relativePath>xxx</relativePath>
</parent>
groudId、artifactId、version、packaging
<!-- 我的项目的寰球惟一标识符,通常应用全限定的包名辨别该我的项目和其余我的项目。并且构建时生成的门路也是由此生成,如 com.mycompany.app 生成的相对路径为:/com/mycompany/app -->
<groupId>xxx</groupId>
<!-- 构件的标识符,它和 group ID 一起惟一标识一个构件。换句话说,你不能有两个不同的我的项目领有同样的 artifact ID
和 groupID;在某个特定的 group ID 下,artifact ID 也必须是惟一的。构件是我的项目产生的或应用的一个货色,Maven
为我的项目产生的构件包含:JARs,源码,二进制公布和 WARs 等。-->
<artifactId>xxx</artifactId>
<!-- 我的项目以后版本,格局为: 主版本. 次版本. 增量版本 - 限定版本号 -->
<version>1.0-SNAPSHOT</version>
<!-- 我的项目产生的构件类型,例如 jar、war、ear、pom。插件能够创立他们本人的构件类型,所以后面列的不是全副构件类型 -->
<packaging>jar</packaging>
<packaging>
默认构件类型为 jar,当作为父级 Maven 我的项目的时候,构件类型为 pom。
modules
<!-- 模块(有时称作子项目)被构建成我的项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径 -->
<modules>
<!-- 子项目相对路径 -->
<module></module>
</modules>
通过 <modules>
Maven 我的项目之间能够造成父子关系,能够有多个层级。
repositories
<!-- 发现依赖和扩大的近程仓库列表。-->
<repositories>
<!-- 蕴含须要连贯到近程仓库的信息 -->
<repository>
<!-- 如何解决近程仓库里公布版本的下载 -->
<releases>
<!-- true 或者 false 示意该仓库是否为下载某种类型构件(公布版,快照版)开启。-->
<enabled><enabled>
<!-- 该元素指定更新产生的频率。Maven 会比拟本地 POM 和近程 POM 的工夫戳。这里的选项是:always(始终),daily(默认,每日),interval:X(这里 X 是以分钟为单位的工夫距离),或者 never(从不)。-->
<updatePolicy></updatePolicy>
<!-- 当 Maven 验证构件校验文件失败时该怎么做:ignore(疏忽),fail(失败),或者 warn(正告)。-->
<checksumPolicy></checksumPolicy>
</releases>
<!-- 如何解决近程仓库里快照版本的下载。有了 releases 和 snapshots 这两组配置,POM 就能够在每个独自的仓库中,为每种类型的构件采取不同的策略。例如,可能有人会决定只为开发目标开启对快照版本下载的反对。-->
<snapshots>
<enabled><enabled>
<updatePolicy></updatePolicy>
<checksumPolicy></checksumPolicy>
</snapshots>
<!-- 近程仓库惟一标识符。能够用来匹配在 settings.xml 文件里配置的近程仓库 -->
<id>banseon-repository-proxy</id>
<!-- 近程仓库名称 -->
<name>banseon-repository-proxy</name>
<!-- 近程仓库 URL,按 protocol://hostname/path 模式 -->
<url>http://192.168.1.169:9999/repository/</url>
<!-- 用于定位和排序构件的仓库布局类型 - 能够是 default(默认)或者 legacy(遗留)。Maven 2 为其仓库提供了一个默认
的布局;然而,Maven 1.x 有一种不同的布局。咱们能够应用该元素指定布局是 default(默认)还是 legacy(遗留)。-->
<layout> default </layout>
</repository>
</repositories>
<id>
能够配合 settings.xml 中的近程仓库配置进行应用,见上一节中的 案例。
properties
<!-- 以值代替名称,Properties 能够在整个 POM 中应用,也能够作为触发条件。格局是 <name>value</name>。-->
<properties>
<name>value</name>
</properties>
dependencies
<!-- 该元素形容了我的项目相干的所有依赖。这些依赖组成了我的项目构建过程中的一个个环节。它们主动从我的项目定义的仓库中下载。-->
<dependencies>
<dependency>
<!-- 依赖的 group ID -->
<groupId>org.apache.maven</groupId>
<!-- 依赖的 artifact ID -->
<artifactId>maven-artifact</artifactId>
<!-- 依赖的版本号。在 Maven 2 里,也能够配置成版本号的范畴。-->
<version>3.8.1</version>
<!-- 依赖类型,默认类型是 jar。它通常示意依赖的文件的扩展名,但也有例外。一个类型能够被映射成另外一个扩大
名或分类器。类型常常和应用的打包形式对应,只管这也有例外。一些类型的例子:jar,war,ejb-client 和 test-jar。如果设置 extensions 为 true,就能够在 plugin 里定义新的类型。所以后面的类型的例子不残缺。-->
<type>jar</type>
<!-- 依赖的分类器。分类器能够辨别属于同一个 POM,但不同构建形式的构件。分类器名被附加到文件名的版本号前面。例如,如果你想要构建两个独自的构件成 JAR,一个应用 Java 1.4 编译器,另一个应用 Java 6 编译器,你就能够应用分类器来生
成两个独自的 JAR 构件。-->
<classifier></classifier>
<!-- 依赖范畴。在我的项目公布过程中,帮忙决定哪些构件被包含进来。欲知详情请参考依赖机制。- compile:默认范畴,用于编译
- provided:相似于编译,但反对你期待 jdk 或者容器提供,相似于 classpath
- runtime: 在执行时须要应用
- test: 用于 test 工作时应用
- system: 须要外在提供相应的元素。通过 systemPath 来获得
- systemPath: 仅用于范畴为 system。提供相应的门路
- optional: 当我的项目本身被依赖时,标注依赖是否传递。用于间断依赖时应用 -->
<scope>test</scope>
<!-- 仅供 system 范畴应用。留神,不激励应用这个元素,并且在新的版本中该元素可能被笼罩掉。该元素为依赖规定了文件
零碎上的门路。须要绝对路径而不是相对路径。举荐应用属性匹配绝对路径,例如 ${java.home}。-->
<systemPath></systemPath>
<!-- 当计算传递依赖时,从依赖构件列表里,列出被排除的依赖构件集。即通知 Maven 你只依赖指定的我的项目,不依赖我的项目的
依赖。此元素次要用于解决版本抵触问题 -->
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
<!-- 可选依赖,如果你在我的项目 B 中把 C 依赖申明为可选,你就须要在依赖于 B 的我的项目(例如我的项目 A)中显式的援用对 C 的依赖。可选依赖阻断依赖的传递性。-->
<optional>true</optional>
</dependency>
</dependencies>
dependencyManagement
- 只能呈现在父 pom 里
- 用于对立版本号
- 只是依赖申明,并不间接依赖,须要时在子项目中在申明要应用依赖的 GA 信息,V 信息能够省略。
<!-- 继承自该项目标所有子项目的默认依赖信息。这部分的依赖信息不会被立刻解析,而是当子项目申明一个依赖(必须形容 groupId 和 artifactId 信息),如果 group ID 和 artifact ID 以外的一些信息没有
形容,则通过 group ID 和 artifact ID 匹配到这里的依赖,并应用这里的依赖信息。-->
<dependencyManagement>
<dependencies>
<!-- 参见 dependencies/dependency 元素 -->
<dependency>
</dependency>
</dependencies>
</dependencyManagement>
build
<build>
<!-- 该元素设置了我的项目源码目录,当构建我的项目的时候,构建零碎会编译目录里的源码。该门路是绝对于 pom.xml 的相对路径。-->
<sourceDirectory></sourceDirectory>
<!-- 该元素设置了我的项目单元测试应用的源码目录,当测试项目的时候,构建零碎会编译目录里的源码。该门路是绝对于 pom.xml 的相对路径。-->
<testSourceDirectory></testSourceDirectory>
<!-- 被编译过的应用程序 class 文件寄存的目录。-->
<outputDirectory></outputDirectory>
<!-- 被编译过的测试 class 文件寄存的目录。-->
<testOutputDirectory></testOutputDirectory>
<!-- 这个元素形容了我的项目相干的所有资源门路列表,例如和我的项目相干的属性文件,这些资源被蕴含在最终的打包文件里。-->
<resources>
<!-- 这个元素形容了我的项目相干或测试相干的所有资源门路 -->
<resource>
<!-- 是否应用参数值代替参数名。参数值取自 properties 元素或者文件里配置的属性,文件在 filters 元素里列出。-->
<filtering></filtering>
<!-- 形容寄存资源的目录,该门路绝对 pom.xml 门路 -->
<directory></directory>
<!-- 蕴含的模式列表,例如 **/*.xml. -->
<includes>
<include></include>
</includes>
<!-- 排除的模式列表,例如 **/*.xml -->
<excludes>
<exclude></exclude>
</excludes>
</resource>
</resources>
<!-- 子项目能够援用的默认插件信息。该插件配置项直到被援用时才会被解析或绑定到生命周期。给定插件的任何本地配置都会笼罩这里的配置 -->
<pluginManagement>
<!-- 参见 dependencies 元素 -->
<plugins>
</plugins>
</pluginManagement>
<!-- 该我的项目应用的插件列表。-->
<plugins>
<!-- plugin 元素蕴含形容插件所须要的信息。-->
<plugin>
<!-- 插件在仓库里的 group ID -->
<groupId></groupId>
<!-- 插件在仓库里的 artifact ID -->
<artifactId></artifactId>
<!-- 被应用的插件的版本(或版本范畴)-->
<version></version>
<!-- 在构建生命周期中执行一组指标的配置。每个指标可能有不同的配置。-->
<executions>
<!-- execution 元素蕴含了插件执行须要的信息 -->
<execution>
<!-- 执行指标的标识符,用于标识构建过程中的指标,或者匹配继承过程中须要合并的执行指标 -->
<id></id>
<!-- 绑定了指标的构建生命周期阶段,如果省略,指标会被绑定到源数据里配置的默认阶段 -->
<phase></phase>
<!-- 配置的执行指标 -->
<goals></goals>
<!-- 作为 DOM 对象的配置 -->
<configuration></configuration>
</execution>
</executions>
<!-- 我的项目引入插件所须要的额定依赖 -->
<dependencies>
<!-- 参见 dependencies/dependency 元素 -->
<dependency>
</dependency>
</dependencies>
<!-- 作为 DOM 对象的配置 -->
<configuration></configuration>
</plugin>
</plugins>
</build>
应用 Nexus 搭建 Maven 私服
Nexus 是一个弱小的 Maven 仓库管理器,它极大的简化了本地外部仓库的保护和内部仓库的拜访。
Docker 搭建 Nexus
咱们采纳 Docker 形式来装置:
1. 拉取 nexus3 镜像
# 拉取 nexus3 镜像
docker pull sonatype/nexus3:3.16.0
2. 启动 nexus3 容器
# 通过镜像启动容器
docker run -d --name nexus -p 8081:8081 -v /Users/linfuyan/Develop/nexus-data:/nexus-data sonatype/nexus3:3.16.0
-d:后盾模式运行容器
–name:容器命名为 nexus
-p:映射本地 8081 端口到容器内的 8081 端口
-v:将容器内的 /nexus-data 目录挂载到本地目录
3. 浏览器中拜访 localhost:8081 就能够看到 Nexus 页面了。
留神:
3.6.0 版本的 sonatype/nexus3 无奈查看到 upload 页面。
3.27.0 版本的 sonatype/nexus3 在我电脑上跑不起来,而且初始密码存在 admin.password 文件中。
最终抉择了 3.16.0 版本。
Nexus 根底应用
通过右上角的 sign in 按钮,输出默认账号密码 admin/admin123
能够对仓库等进行治理。
创立近程仓库
可选 Maven2 group、hosted、proxy 类型。
hosted:本地仓库,通常咱们会部署本人的构件到这一类型的仓库。比方公司的第二方库。
proxy:代理仓库,它们被用来代理近程的公共仓库,如 Maven 地方仓库。
group:仓库组,用来合并多个 hosted/proxy 仓库,当你的我的项目心愿在多个 repository 应用资源时就不须要屡次援用了,只须要援用一个 group 即可。
新建 hosted 类型仓库
把 craft4j 增加到 maven-public 中。
创立具备上传权限的角色
创立具备上传权限的角色的用户
上传 jar 组件到 Nexus
通过网页手动上传第三方 jar 到 Nexus
上传胜利当前,就能够在对应的近程仓库中查看到上传实现的组件信息。
通过 mvn deploy:deploy-file 上传到 Nexus
➜ ron-jwt git:(master) ✗ mvn deploy:deploy-file -DgroupId=io.craft4j -DartifactId=checkstyle -Dversion=1.0.1-SNAPSHOT -Dpackaging=jar -Dfile=/Users/linfuyan/Code/java-lab/airplan-java-server/codestyle/checkstyle-7.0-all.jar -DrepositoryId=craft4j -Durl=http://127.0.0.1:8081/repository/craft4j/
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[pom]---------------------------------
[INFO]
[INFO] --- maven-deploy-plugin:2.7:deploy-file (default-cli) @ standalone-pom ---
Downloading from remote-repository: http://127.0.0.1:8081/repository/craft4j/io/craft4j/checkstyle/1.0.1-SNAPSHOT/maven-metadata.xml
Downloaded from remote-repository: http://127.0.0.1:8081/repository/craft4j/io/craft4j/checkstyle/1.0.1-SNAPSHOT/maven-metadata.xml (770 B at 3.7 kB/s)
Uploading to remote-repository: http://127.0.0.1:8081/repository/craft4j/io/craft4j/checkstyle/1.0.1-SNAPSHOT/checkstyle-1.0.1-20200910.081245-2.jar
Uploading to remote-repository: http://127.0.0.1:8081/repository/craft4j/io/craft4j/checkstyle/1.0.1-SNAPSHOT/checkstyle-1.0.1-20200910.081245-2.pom
repositoryId 依赖 settings.xml 中的 server 配置,次要是用户名与明码。
通过 mvn deploy 形式上传到 Nexus
在下面的步骤中,曾经将新建的 craft4j 仓库增加到 maven-public 仓库组中。
在 settings.xml 中批改配置:
<servers>
<server>
<id>nexus-releases</id>
<username>dev</username>
<password>dev123</password>
</server>
<server>
<id>craft4j</id>
<username>dev</username>
<password>dev123</password>
</server>
</servers>
在我的项目 pom.xml 中批改配置:
<distributionManagement>
<repository>
<id>maven-releases</id>
<name>Nexus Release Repository</name>
<url>http://127.0.0.1:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>craft4j</id>
<name>Nexus Snapshot Repository</name>
<url>http://127.0.0.1:8081/repository/craft4j/</url>
</snapshotRepository>
</distributionManagement>
pom.xml 中的 repository id 与 settings.xml 中的 server id 绝对应,须要保持一致。
在须要公布的我的项目中执行 mvn deploy
,看到如下日志,就阐明公布胜利了,同样能够在 Nexus 的仓库浏览页中查看。
➜ ron-jwt git:(master) ✗ mvn clean deploy
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------------< io.ron:ron-jwt >---------------------------
[INFO] Building ron-jwt 1.0-SNAPSHOT
[INFO] --------------------------------[jar]---------------------------------
[INFO] ...
[INFO] --- maven-deploy-plugin:2.7:deploy (default-deploy) @ ron-jwt ---
Downloading from craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/1.0-SNAPSHOT/maven-metadata.xml
Uploading to craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/1.0-SNAPSHOT/ron-jwt-1.0-20200910.071640-1.jar
Uploaded to craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/1.0-SNAPSHOT/ron-jwt-1.0-20200910.071640-1.jar (15 kB at 21 kB/s)
Uploading to craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/1.0-SNAPSHOT/ron-jwt-1.0-20200910.071640-1.pom
Uploaded to craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/1.0-SNAPSHOT/ron-jwt-1.0-20200910.071640-1.pom (1.3 kB at 2.6 kB/s)
Downloading from craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/maven-metadata.xml
Uploading to craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/1.0-SNAPSHOT/maven-metadata.xml
Uploaded to craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/1.0-SNAPSHOT/maven-metadata.xml (757 B at 2.0 kB/s)
Uploading to craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/maven-metadata.xml
Uploaded to craft4j: http://127.0.0.1:8081/repository/craft4j/io/ron/ron-jwt/maven-metadata.xml (271 B at 1.0 kB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.243 s
[INFO] Finished at: 2020-09-10T15:16:42+08:00
[INFO] ------------------------------------------------------------------------
Maven 构件的版本治理
应用 Maven 作为依赖管理工具,个别咱们对于依赖的版本号,常见两种类型:一种以“-RELEASE”结尾,另一种以“-SNAPSHOT”结尾。
私服中,会存在 snapshot 快照仓库和 release 公布仓库,snapshot 快照仓库用于保留开发过程中的不稳固版本,release 正式仓库则是用来保留稳固的发行版本。
Maven 会依据模块的版本号(pom 文件中的 version)中是否带有“-SNAPSHOT”(留神这里必须是全副大写)来判断是快照版本还是正式版本。如果是快照版本,那么在 mvn deploy 时会主动公布到私服的快照版本库中;如果是正式公布版本,那么在 mvn deploy 时会主动公布到正式版本库中。
快照版本的依赖,Maven 编译打包的时候无论本地是否存在,都会去私服拉取最新的,而正式版本的依赖,如果本地仓库曾经存在,Maven 不会去私服拉取最新的版本,所以咱们要基于快照版本进行开发,然而上线的时候肯定记得变成正式版,否则如果本地正在进行开发另一个性能,提交到私服的代码有可能会被误上线。
那咱们有什么好的办法来防止这种状况呢?
1. 在 settings.xml 中批改私服配置,通过 updatePolicy 为 always 强制更新。
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>nexus</id>
<name>Nexus</name>
<url>http://127.0.0.1:8081/repository/groups/maven-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
</pluginRepository>
</pluginRepositories>
</profile>
2. 在构建的时候加上“-U”参数,强制拉取所有依赖的最新代码
mvn clean install -U
3. 语义化版本
首先,咱们在团队合作时,要定义好开发中的依赖肯定不要遗记降级版本号,而后开发的过程中还要放弃版本号以“-SNAPSHOT”结尾,来把该依赖作为快照版本进行开发,这样每次他人更新完上传到私服当前,你本地打包时会主动拉取最新代码,从而不便咱们的开发和保护。
参考与致谢
带你深度解析 Maven
史上最全的 maven 的 pom.xml 文件详解
setting.xml 配置详解
上传 jar 包到 nexus 私服
Maven 私服:Docker 装置 nexus3
Maven 版本号中暗藏的惊天大机密
Maven 全局配置文件 settings.xml 详解
如果你看完本文有播种,欢送关注微信公众号:精进 Java(ID: craft4j),更多 Java 后端与架构的干货等你一起学习与交换。