Maven 的安装与配置

下载地址:https://maven.apache.org/download.cgi

添加环境变量

使用 win + r 打开运行框,输入control system,回车进入设置界面后,创建一个环境变量MAVEN_HOME(maven的安装地址)。

创建好后,找到系统变量中的path,将MAVEN_HOME这个变量配置进去:%MAVEN_HOME%\bin

打开cmd命令行输入mvn -v,打印出版本号表示安装成功。

修改 settings.xml

修改 conf 下的 settings.xml,将 localRepository 替换成本地的 maven 仓库地址。

至此,maven 就能正常使用了!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
<?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.
-->

<!--
| This is the configuration file for Maven. It can be specified at two levels:
|
| 1. User Level. This settings.xml file provides configuration for a single user,
| and is normally provided in ${user.home}/.m2/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -s /path/to/user/settings.xml
|
| 2. Global Level. This settings.xml file provides configuration for all Maven
| users on a machine (assuming they're all using the same Maven
| installation). It's normally provided in
| ${maven.conf}/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -gs /path/to/global/settings.xml
|
| The sections in this sample file are intended to give you a running start at
| getting the most out of your Maven installation. Where appropriate, the default
| values (values used when the setting is not specified) are provided.
|
|-->
<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 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 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:\mvnrepository</localRepository>
<!-- interactiveMode
| This will determine whether maven prompts you when it needs input. If set to false,
| maven will use a sensible default value, perhaps based on some other setting, for
| the parameter in question.
|
| Default: true
<interactiveMode>true</interactiveMode>
-->

<!-- offline
| Determines whether maven should attempt to connect to the network when executing a build.
| This will have an effect on artifact downloads, artifact deployment, and others.
|
| Default: false
<offline>false</offline>
-->

<!-- pluginGroups
| This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
| when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
| "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
|-->
<pluginGroups>
<!-- pluginGroup
| Specifies a further group identifier to use for plugin lookup.
<pluginGroup>com.your.plugins</pluginGroup>
-->
</pluginGroups>

<!-- proxies
| This is a list of proxies which can be used on this machine to connect to the network.
| Unless otherwise specified (by system property or command-line switch), the first proxy
| specification in this list marked as active will be used.
|-->
<proxies>
<!-- proxy
| Specification for one proxy, to be used in connecting to the network.
|
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
-->
</proxies>

<!-- servers
| This is a list of authentication profiles, keyed by the server-id used within the system.
| Authentication profiles can be used whenever maven must make a connection to a remote server.
|-->
<servers>
<!-- server
| Specifies the authentication information to use when connecting to a particular server, identified by
| a unique name within the system (referred to by the 'id' attribute below).
|
| NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
| used together.
|
<server>
<id>deploymentRepo</id>
<username>repouser</username>
<password>repopwd</password>
</server>
-->

<!-- Another sample, using keys to authenticate.
<server>
<id>siteServer</id>
<privateKey>/path/to/private/key</privateKey>
<passphrase>optional; leave empty if not used.</passphrase>
</server>
-->
</servers>

<!-- mirrors
| This is a list of mirrors to be used in downloading artifacts from remote repositories.
|
| It works like this: a POM may declare a repository to use in resolving certain artifacts.
| However, this repository may have problems with heavy traffic at times, so people have mirrored
| it to several places.
|
| That repository definition will have a unique id, so we can create a mirror reference for that
| repository, to be used as an alternate download site. The mirror site will be the preferred
| server for that repository.
|-->

<!-- mirror
<mirrors>
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
|
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
</mirrors>
-->
<!-- 阿里云仓库 -->
<mirrors>
<!-- <mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror> -->

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

</mirrors>
<!-- profiles
| This is a list of profiles which can be activated in a variety of ways, and which can modify
| the build process. Profiles provided in the settings.xml are intended to provide local machine-
| specific paths and repository locations which allow the build to work in the local environment.
|
| For example, if you have an integration testing plugin - like cactus - that needs to know where
| your Tomcat instance is installed, you can provide a variable here such that the variable is
| dereferenced during the build process to configure the cactus plugin.
|
| As noted above, profiles can be activated in a variety of ways. One way - the activeProfiles
| section of this document (settings.xml) - will be discussed later. Another way essentially
| relies on the detection of a system property, either matching a particular value for the property,
| or merely testing its existence. Profiles can also be activated by JDK version prefix, where a
| value of '1.4' might activate a profile when the build is executed on a JDK version of '1.4.2_07'.
| Finally, the list of active profiles can be specified directly from the command line.
|
| NOTE: For profiles defined in the settings.xml, you are restricted to specifying only artifact
| repositories, plugin repositories, and free-form properties to be used as configuration
| variables for plugins in the POM.
|
|-->
<!-- profile
<profiles>
| Specifies a set of introductions to the build process, to be activated using one or more of the
| mechanisms described above. For inheritance purposes, and to activate profiles via <activatedProfiles/>
| or the command line, profiles have to have an ID that is unique.
|
| An encouraged best practice for profile identification is to use a consistent naming convention
| for profiles, such as 'env-dev', 'env-test', 'env-production', 'user-jdcasey', 'user-brett', etc.
| This will make it more intuitive to understand what the set of introduced profiles is attempting
| to accomplish, particularly when you only have a list of profile id's for debug.
|
| This profile example uses the JDK version to trigger activation, and provides a JDK-specific repo.
<profile>
<id>jdk-1.4</id>

<activation>
<jdk>1.4</jdk>
</activation>

<repositories>
<repository>
<id>jdk14</id>
<name>Repository for JDK 1.4 builds</name>
<url>http://www.myhost.com/maven/jdk14</url>
<layout>default</layout>
<snapshotPolicy>always</snapshotPolicy>
</repository>
</repositories>
</profile>
-->

<!--
| Here is another profile, activated by the system property 'target-env' with a value of 'dev',
| which provides a specific path to the Tomcat instance. To use this, your plugin configuration
| might hypothetically look like:
|
| ...
| <plugin>
| <groupId>org.myco.myplugins</groupId>
| <artifactId>myplugin</artifactId>
|
| <configuration>
| <tomcatLocation>${tomcatPath}</tomcatLocation>
| </configuration>
| </plugin>
| ...
|
| NOTE: If you just wanted to inject this configuration whenever someone set 'target-env' to
| anything, you could just leave off the <value/> inside the activation-property.
|
<profile>
<id>env-dev</id>

<activation>
<property>
<name>target-env</name>
<value>dev</value>
</property>
</activation>

<properties>
<tomcatPath>/path/to/tomcat/instance</tomcatPath>
</properties>
</profile>

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



<!-- activeProfiles
| List of profiles that are active for all builds.
|
<activeProfiles>
<activeProfile>alwaysActiveProfile</activeProfile>
<activeProfile>anotherAlwaysActiveProfile</activeProfile>
</activeProfiles>
-->
</settings>

Maven 配置详解

pom.xml 的基本结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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.ls.mavendemo</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>

<name>hello-world</name>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>

先看一下各个标签的含义:

:POM 的根元素,定义了一些POM相关的规范。
: POM版本号,我们用的是 Maven3 这里只能是4.0.0
:项目的坐标,用于确定一个唯一的项目

  • <groupId>:指的是当前构建隶属的实际项目,一般是 公司的网址倒序 + 项目名
  • <artifactId>:一般是指的当前项目中的其中一个模块
  • <version>:当前项目的版本号

Maven 的版本号规则实际上也是业界的通过规则,它的定义方式如下:

{主版本号}.{次版本号}.{增量版本号}-{里程碑版本}
主版本号:一般是指的当前的项目有了重大的架构变动,版本之间几乎完全不兼容,例如:最近出的 SpringBoot3 就已经放弃了Java8,如果不升级 JDK的话,还是只能使用SpringBoot2
次版本号:一般是指的项目的迭代版本,这种版本会修复大量的bug,带来一些小的新特性等,但是没有什么架构上的重大变化。
增量版本号:一般是用于修复一些紧急bug,改动量很小时,可以使用增量版本号。
里程碑版本:就是项目的当前版本处于一个什么样的阶段了,常见的里程碑版本有 SNAPSHOT,alpha,beta,release,GA 等。

  • SNAPSHOT:开发版,此时会存在大量的代码变动
  • alpha和beta分别对应的是内测版与公测版,属于不稳定版本,使用的时候非常容易踩坑,所以一般只用于demo体验,在正式环境中不能使用。
  • release和GA都属于是稳定的正式版本,可以在正式环境中使用。

:当前项目的名称
:当前项目引入的依赖
:单个需要引入的具体的依赖包
:依赖的范围,常见的有 compile 和 test,不同的范围起到包隔离的作用

Maven 的依赖

来看一下完整的依赖配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!--type 指的的当前引入的构件类型,默认为 jar -->
<type></type>
<scope></scope>
<optional></optional>
<exclusions>
<exclusion>
<groupId></groupId>
<artifactId></artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

依赖传递

通过pom.xml 分别描述 A、B 构建的依赖关系:

1
2
3
4
5
6
7
8
<!-- A 依赖 B -->
<dependencies>
<dependency>
<groupId>com.ls.mavendemo</groupId>
<artifactId>B</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
1
2
3
4
5
6
7
8
<!-- B 依赖 C -->
<dependencies>
<dependency>
<groupId>com.ls.mavendemo</groupId>
<artifactId>C</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>

此时,A 可以使用 C 里面打包的代码。

在上面的依赖配置基础上,如果我们不想将 C 传递给 A,则可以在 B 引入 C 的时候,将其设置为可选依赖:

引入的依赖如果标记为 optional 则不再向上传递,此时 A 不能再直接使用 C中的代码,可以选依赖在 pom.xml 中表示为:

1
2
3
4
5
6
7
8
9
<!-- B 依赖 C -->
<dependencies>
<dependency>
<groupId>com.ls.mavendemo</groupId>
<artifactId>C</artifactId>
<version>1.0.0</version>
<optional>true</optional>
</dependency>
</dependencies>

为什么会需要禁止依赖传递?

举个简单的开发例子,我们在一个 WEB 项目的开发中,将 service 层与 dao 分别拆成了两个构件,service 包依赖 dao 包,但是 service 中只需要使用我们写的主代码,而不需要使用例如数据库驱动、JDBC、ORM框架等依赖,我们就可以在 dao 中使用禁止这些持久化相关的包向上传递到service。

依赖范围

依赖范围在 pom.xml 中使用 来表示,有5种选项:

  • compile:默认选项,也是最常用的选项,在编译、运行、测试的classpath中有引入;依赖范围在向上传递的时候,间接依赖于直接依赖的范围一致
  • provided:只在编译、测试引入,运行时不引入,例如:lombok;依赖范围不会向上传递
  • runtime:只在运行、测试引入,编译期不引入,例如:mysql-connector-java;依赖范围可向上传递,直接依赖为compile时,间接依赖的范围依然是runtime
  • test:只在测试中有效,例如:JUnit;依赖范围不会向上传递
  • system:与provided相同,但是需要手动指定依赖文件路径(system会破坏可移植性,不推荐使用)

依赖冲突

直接依赖:在同一个 pom.xml 下,后声明的依赖会覆盖先声明的依赖。

间接依赖:在不同的 pom.xml 下,依赖路径最短的那个依赖会生效,也就是就近原则

有时候我们需要手动的排除一部分传递性的依赖,然后再定义我们需要的依赖,举个简单的例子:

我们在 spring-boot 的项目中使用 redis,首先需要引入一个 starter,这个 starter 中又依赖了 lettuce 这个客户端,此时,我们不想使用这个客户端,想切换成 jedis,那么我们就可以使用exclusionslettuce 排除掉。

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.2.5.RELEASE</version>
<exclusions>
<!-- 注:这里的exclusion 中不需要使用版本号。 -->
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>

然后再引入 jedis 的依赖就可以了。

Maven 的继承与聚合

模块的继承

所有的 pom.xml 文件都会默认继承 super pom,在 super pom 中定义了这么几个配置:

  • 构件与插件仓库的地址

  • 源码、测试代码以及资源文件resources的默认路径

  • 编译及打包后的文件路径

这也是为什么我们创建一个Maven项目之后,只要在 Maven 约定好的路径中编写我们的代码,其他的几乎什么都不用配置,就可以直接进行构建,也是一种约定优于配置的思想体现。

super pom 的位置在Maven主目录的lib文件夹下面,找到一个叫maven-model-builder.jar 的文件,在这个 jar 包的\org\apache\maven\model\pom-4.0.0.xml 路径下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<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>
</build>
</project>

手动引入自定义父POM

pom 的引入语法很简单,在parent标签中添加构件坐标即可,类似于dependency引入依赖:

1
2
3
4
5
6
7
<parent>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!-- relativePath 指的是父 pom.xml 所在的相对路径,默认值是 ../pom.xml -->
<relativePath></relativePath>
</parent>

子模块会优先从上级目录中查找pom.xml,如果查不到则到本地仓库中查找,如果还是查不到则会从远程仓库中查找。

模块的聚合

demo-a 依赖 demo-b, demo-b 依赖 demo-c , 在这种情况下,我们需要先 install c ,再 install b ,最后再构建 a,执行起来非常麻烦,为了处理这个问题,Maven 引入了聚合机制,可以将这三个模块聚合在一起,一次性完成构建。

聚合的语法也非常简单,只需要在父目录的 pom.xml 中添加 <modules> 即可:

1
2
3
4
5
<modules>
<module>demo-a</module>
<module>demo-b</module>
<module>demo-c</module>
</modules>

<module> 中填写的并不是 artifactId,而是需要被聚合的模块的名称。

反应堆(reactor)

Maven 的反应堆是将多个模块的项目按照一定的顺序进行构建。

当我们执行install或package语句时,maven先构建的是配置了聚合关系的聚合模块,然后才是子模块。子模块构建的时候会按照被依赖的顺序,由底层向上层进行构建。因此,我们的模块之间不能出现循环依赖的情况,假如在demo-c中引入demo-a的依赖,此时构建就会报错。

依赖管理

Maven配置会把子模块中使用到的依赖以及版本号等,抽取到父模块中由子模块直接继承。

父pom.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
<properties>
<mysql-connector-java.verison>8.0.29</mysql-connector-java.verison>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.verison}</version>
</dependency>
</dependencies>
</dependencyManagement>

子pom.xml可不声明依赖版本,直接继承父pom.xml的版本

1
2
3
4
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

Maven 的生命周期

Maven 的生命周期有三个,分别是cleandefaultsite

  • clean:默认是清除target目录中的所有文件,避免将历史版本打到新的包中造成一些不在预期中的问题
  • process-resources:将资源文件src/main/resources下的文件复制到target/classes目录中。
  • compile:将src/main/java下的代码编译成 class 文件,也放到target/classes目录中。
  • process-test-resources:将资源文件src/test/resources下的文件复制到target/test-classes目录中。
  • test-compile:将src/test/java下的代码编译成 class 文件,也放到target/test-classes目录中。
  • test:运行单元测试并在target/surefire-reports中生成测试报告。
  • package:将资源文件、class文件、pom文件打包成一个jar包。
  • install:将生成的jar包推送到本地仓库中。
  • deploy:将生成的jar包推送到远程仓库中。

执行构建时,会按照阶段顺序从上到下的执行,但只有绑定了插件目标阶段才会执行

可以在通过<plugin>标签引入插件,通过<excutions>来定义执行计划,通过<phase><goal>绑定阶段插件模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<build>
<plugins>
<plugin>
<!--源码插件引入-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<!--执行计划-->
<executions>
<execution>
<!--在哪个生命周期阶段执行-->
<phase>install</phase>
<!--执行别名-->
<id>build-source</id>
<goals>
<!--插件目标-->
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Maven 私服

Maven 的仓库只有两种类型:本地仓库远程仓库

对于 远程仓库 来说,有几种特殊的子类型,最特殊的就是 Maven 的 中央仓库,这个是 Maven 提供的官方仓库,我们可以在里面找到市面上的几乎任何一个开源构件。除了中央仓库之前,还有其他的公共仓库,例如:JBoss的仓库,阿里云、腾讯云的镜像仓库等。

另外一种就是我们接下来要讲到的私服了,私服是假设在局域网中的仓库服务,也可以看作是对公用远程仓库的代理。

私服 Nexus

本地的开发电脑在引入某个依赖的时候,可以先从私服查找,如果私服没有找到再去公用仓库下载,同时,也允许我们将开发好的某些构件上传到私服中,供其他的开发者下载使用。

私服有以下优势:

  • 节省带宽,增加构件的下载速度,同时也增加了仓库的稳定性。
    在同一个局域网中,只要有一个开发者引入了某个构件,触发了私服从公用仓库中下载构件后,私服就会将这构件缓存到私服所在的服务器中。此时,再有其他的开发者要使用这个构件,就能够直接从局域网下载了,局域网相对于公网,更快更稳定。
  • 可以上传公共仓库中没有的构件,与同一局域网中的其他开发者共享。

Docker 安装私服

登录

在 docker-desktop 中找到 sonatype/nexus3 这个镜像,拉取一个版本下来。

打开 powershell,执行以下命令启动:

1
2
3
docker volume create --name nexus-data
# 将容器的8081端口映射到宿主机的8082端口
docker run -dp 8082:8081 --name nexus -v nexus-data:/nexus-data sonatype/nexus3

打开 nexus 管理台

image-20240119094827382

进入到 nexus 容器里,进入sonatype-work/nexus3文件夹,找到 admin.password,里面保存着初始密码

1
docker exec -it nexus bash

获取到密码之后,回到网页上,点击右上角的 sign in ,使用 admin 登录,接下来会进入一个引导流程,会做下面两个配置:

修改密码:这里直接改成admin123
配置是否允许匿名登录:即后面使用Maven连接私服的时候是否需要使用密码
安全的配置一般都是不允许使用匿名登录的,这里我们选择Disable anonymous access。

仓库配置

登录成功之后,我们需要在私服中配置国内的公用仓库作为私服下载构件的下载源,在这之前,我们先看一下默认的仓库配置。打开Server administration and configuration进行配置,也就是标题栏上面那个齿轮,然后打开Repositores

image-20240119105708923

Type:

  • proxy:代理仓库,用来代理中央仓库或其他的远程公用仓库。
  • hosted:用来保存我们在局域网中发布的构件,也就是私有仓库。
  • group:仓库分组,里面可以配置多个仓库,并指定仓库访问的优先级。

Name:

  • maven-release:存放非SNAPSHOT的构件。
  • maven-snapshots:用于存放里程碑版本为SNAPSHOT的构件。
  • maven-central:代理Maven中央仓库,这里会缓存从中央仓库下载的构件。
  • maven-public:是仓库的分组,这个仓库中配置了上面三个仓库的访问顺序。

回到仓库列表页面,点击左上角的Create repository,然后选择`maven2(proxy)

image-20240119111324927

ali_repo 配置如下:

image-20240119111757956

然后打开maven_public,将ali_repo配置上去:

image-20240119112013042

将ali_repo放到 snapshotsmaven-central 之间

image-20240119151424667

如果是正式环境使用的话,还需要对新建角色role,并针对每一个开发者都创建一个用户user

私服的使用

修改Maven配置

先修改setting.xml的两个配置,让Maven可以连接上私服

1
2
3
4
5
6
7
<servers>
<server>
<id>nexus</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>

然后是镜像配置,这里的url配置成上面所说的maven-public地址:

1
2
3
4
5
6
7
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8082/repository/maven-public/</url>
</mirror>
</mirrors>

注意:两个配置中的id需要保持一致

从私服中下载构件

尝试引入一个spring-core的jar包(一定本地仓库中没有的,不然不会触发从私服中拉取),去查看私服中是否进行了下载:

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.28</version>
</dependency>

可以在私服上成功看到下载下来的依赖

image-20240119151253203

推送构件到私服

如果要把自定义的构件发布到仓库中,需要使用以下两个指令:

1
2
3
4
5
6
# 发布到本地仓库
mvn clean install
# 发布到远程仓库
mvn clean deploy
# 如果需要忽略test
mvn clean deploy -Dmaven.test.skip=true

在 pom.xml 中配置将构件推送到哪个仓库中

1
2
3
4
5
6
7
8
9
10
<distributionManagement>
<repository>
<id>nexus</id>
<url>http://localhost:8082/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus</id>
<url>http://localhost:8082/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>

成功在私服上看到我们自定义的构件

image-20240119153656855

打包源码

在开发协作中,有时候还需要将源码发布到私服中以便其他开发者下载,源码中包含了注释和接口说明,更有利于协作,例如:api包、封装的工具包、基础架构包等。

但是Maven的默认生命周期中没有加入打包源码的插件,所以需要我们自行引入,在plugins标签中加入插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<plugin>
<!--源码插件引入-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<!--执行计划-->
<executions>
<execution>
<!--在生命周期的哪个阶段执行-->
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>

重新打包完成之后,查看Maven仓库会发现里面多了一个xxx-sources.jar的源码包。

image-20240119154543318