Maven全面详解——概念、使用方法、进阶
1. Maven简介
为什么使用mava?
为什么要使用 Maven**?它能帮助我们解决什么问题?**
①**添加第三方 jar 包**:
在今天的 JavaEE 开发领域,有大量的第三方框架和工具可以供我们使用。要使用这些 jar 包最简单 的方法就是复制粘贴到 WEB-INF/lib 目录下。但是这会导致每次创建一个新的工程就需要将 jar 包重复复 制到 lib 目录下,从而造成工作区中存在大量重复的文件,让我们的工程显得很臃肿。 而使用 Maven 后每个 jar 包本身只在本地仓库中保存一份,需要 jar 包的工程只需要以坐标的方式 简单的引用一下就可以了。不仅极大的节约了存储空间,让项目更轻巧,更避免了重复文件太多而造成 的混乱。
②**jar 包之间的依赖关系**
jar 包往往不是孤立存在的,很多 jar 包都需要在其他 jar 包的支持下才能够正常工作,我们称之为 jar 包之间的依赖关系。最典型的例子是:commons-fileupload-1.3.jar 依赖于 commons-io-2.0.1.jar,如果 没有 IO 包,FileUpload 包就不能正常工作。 那么问题来了,你知道你所使用的所有 jar 包的依赖关系吗?当你拿到一个新的从未使用过的 jar 包,你如何得知他需要哪些 jar 包的支持呢?如果不了解这个情况,导入的 jar 包不够,那么现有的程 序将不能正常工作。再进一步,当你的项目中需要用到上百个 jar 包时,你还会人为的,手工的逐一确 认它们依赖的其他 jar 包吗?这简直是不可想象的。 而引入 Maven 后,Maven 就可以替我们自动的将当前 jar 包所依赖的其他所有 jar 包全部导入进来, 无需人工参与,节约了我们大量的时间和精力。用实际例子来说明就是:通过 Maven 导入 commons-fileupload-1.3.jar 后,commons-io-2.0.1.jar 会被自动导入,程序员不必了解这个依赖关系。
下图是 Spring 所需 jar 包的部分依赖关系
③**获取第三方 jar 包
JavaEE 开发中需要使用到的 jar 包种类繁多,几乎每个 jar 包在其本身的官网上的获取方式都不尽相 同。为了查找一个 jar 包找遍互联网,身心俱疲,没有经历过的人或许体会不到这种折磨。不仅如此, 费劲心血找的 jar 包里有的时候并没有你需要的那个类,又或者又同名的类没有你要的方法——以不规 范的方式获取的 jar 包也往往是不规范的。 使用 Maven 我们可以享受到一个完全统一规范的 jar 包管理体系。你只需要在你的项目中以坐标的 方式依赖一个 jar 包,Maven 就会自动从中央仓库进行下载,并同时下载这个 jar 包所依赖的其他 jar 包
④**将项目拆分成多个工程模块
随着 JavaEE 项目的规模越来越庞大,开发团队的规模也与日俱增。一个项目上千人的团队持续开 发很多年对于 JavaEE 项目来说再正常不过。那么我们想象一下:几百上千的人开发的项目是同一个 Web 工程。那么架构师、项目经理该如何划分项目的模块、如何分工呢?这么大的项目已经不可能通过 package 结构来划分模块,必须将项目拆分成多个工程协同开发。多个模块工程中有的是 Java 工程,有 的是 Web 工程。 那么工程拆分后又如何进行互相调用和访问呢?这就需要用到 Maven 的依赖管理机制。
2. 什么是Maven?
Maven 是 Apache 软件基金会组织维护的一款自动化构建工具,专注服务于 Java 平台的项目构建和 依赖管理。Maven 这个单词的本意是:专家,内行。读音是[‘meɪv(ə)n]或[‘mevn]。![]
什么是构建
构建就是以我们编写的 Java 代码、框架配置文件、国际化等其他资源文件、JSP 页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。
构建过程的几个主要环节
①**清理:删除以前的编译结果,为重新编译做好准备。
②**编译:将 Java 源程序编译为字节码文件。
③**测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
④**报告:在每一次测试后以标准的格式记录和展示测试结果。
⑤**打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java 工程对应 jar 包,Web 工程对应 war 包。
⑥**安装:在 Maven 环境下特指将打包的结果——jar 包或 war 包安装到本地仓库中。
⑦**部署**:将打包的结果部署到远程仓库或将 war 包部署到服务器上运行。
自动化构建
我们为什么还要使用 Maven 这样的构建工具呢?我们来看一个小故事:
这是阳光明媚的一天。托马斯向往常一样早早的来到了公司,冲好一杯咖啡,进入了自己的邮箱——很 不幸,QA小组发来了一封邮件,报告了他昨天提交的模块的测试结果——有 BUG。“好吧,反正也不是第一 次”,托马斯摇摇头,进入IDE,运行自己的程序,编译、打包、部署到服务器上,然后按照邮件中的操作 路径进行测试。“嗯,没错,这个地方确实有问题”,托马斯说道。于是托马斯开始尝试修复这个 BUG,当他 差不多有眉目的时候已经到了午饭时间。
下午继续工作。BUG 很快被修正了,接着托马斯对模块重新进行了编译、打包、部署,测试之后确认没 有问题了,回复了 QA 小组的邮件。
一天就这样过去了,明媚的阳光化作了美丽的晚霞,托马斯却觉得生活并不像晚霞那样美好啊。
让我们来梳理一下托马斯这一天中的工作内容 :
3. Maven的下载和安装
-
下载地址:Maven – Introduction
-
点击下载
- 下载历史版本
下一步:
下载即可
安装maven核心程序
1、解压maven核心程序安装包,放在一个非中文无空格的文件夹中
- 配置maven的相关环境变量
新增环境变量名:MAVEN_HOME 或者 M2_HOME;
变量值为安装目录bin目录的上一级目录;
Path:%M2_HOME%bin
- 验证:运行 mvn -v 命令查看maven的版本
C:UsersAdministrator>mvn -v
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T02:33:1
4+08:00)
Maven home: E:Program Filesmaven3.5.4apache-maven-3.5.4bin..
Java version: 1.8.0_25, vendor: Oracle Corporation, runtime: E:Program Filesja
va1.8jdk1.8jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"
4.Maven 核心概念
Maven 能够实现自动化构建是和它的内部原理分不开的,这里我们从 Maven 的八个核心概念入手,看看 Maven 是如何实现自动化构建的:
①**POM**
②**约定的目录结构**
③**坐标**
④**依赖管理**
⑤**仓库**
⑥**生命周期/插件/目标**
⑦**继承**
⑧**聚合**
5. 第一个maven项目
创建约定的目录结构
1. 目录结构的介绍:
[1] Hello︰工程名
[2]src目录∶源码
[3]pom.xml文件:Maven工程的核心配置文件
[4]main目录∶存放主程序
[5]test目录∶存放测试程序
[6]java目录︰存放Java源文件
[7]resources目录∶存放配置文件
2. 示例:
主程
测试程序
Pom.xml
6. 为什么创建约定的目录结构?
约定的目录结构对于 Maven 实现自动化构建而言是必不可少的一环,就拿自动编译来说,Maven 必须 能找到 Java 源文件,下一步才能编译,而编译之后也必须有一个准确的位置保持编译得到的字节码文件。
7. 基本的Maven命令
[1]mvn clean: 清理
[2]mvn compile: 编译主程序
[3]mvn test-compile: 编译测试程序
[4]mvn test: 执行测试
[5]mvn package: 打包
[6]mvn install: 安装
maven的install可以将项目本身编译并打包到本地仓库,这样其他项目引用本项目的jar 包时不用去私服上下载jar包,直接从本地就可以拿到刚刚编译打包好的项目的jar包, 很灵活;
※注意:运行Maven命令时一定要进入pom.xml文件所在的目录!
测试:
1. 进入Hello项目所在目录执行:mvn compile
命令执行后会有一个下载,
- 下载完指定的插件,并编译了主程序后的日志:
3. 主程序编译后文件存放的目录
发现刚才所写的文件都给我们编译好了。编译函的文件存在于classes中
- 运行mvn test-compile 编译测试程序
可以查看编译好的测试程序
- 运行mvn test 运行测试程序进行测试
注:mvn test命令执行的是test目录中,类名是***Test.java中带有@Test注解的方法
8. 关于联网下载的问题
- Maven的核心程序中仅仅定义了抽象的生命周期,但是具体的工作必须由特定的插件来完成。而插件本身并不包含在Maven的核心程序中。
- 当我们执行的Maven命令需要用到某些插件时,Maven核心程序会首先到本地仓库中查找。
- 本地仓库的默认位置︰C:Users[登录当前系统的用户名].m2repository
- Maven核心程序如果在本地仓库中找不到需要的插件,那么它会自动连接外网,到中央仓库下载。
- 如果此时无法连接外网,则构建失败。
- 由于maven默认的本地仓库的目录是C:Users[登录当前系统的用户名].m2repository,当然也可以进行修改,步骤如下:
[1]找到Maven解压目录confsettings.xml
[2]在settings.xml文件中找到localRepository标签
[3]将
[4]在标签体中指定本地仓库的目录地址
7. maven下载插件或者依赖包默认从远程仓库进行下载,下载速度比较慢,可以修改为镜像地 址,提供下载 速度,修改settings.xml文件,在
<mirror>
<id>alimavenmirror</id>
<mirrorOf>central</mirrorOf>
<name>nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central</url>
</mirror>
9. 仓库
1. 生活中的仓库?
2. Maven中的仓库
主要用来存放第三方jar包,maven所需要的插件已及我们自己开发的maven项目
3. 仓库的分类:
a. 本地仓库:
在你电脑上存放jar包的位置
例:C:Users[登录当前系统的用户名].m2repository
b. 远程仓库:
(1)私服:由公司或单位创建的一个仓库,由公司维护;
项目从本地仓库获取第三方jar包,当本地仓库没有时,可以从公司(或单位)创建的 远程仓库上获取,也可以直接从中央仓库获取;
(2)中央仓库:在互联网上,由maven团队维护
(3) 中央仓库镜像:
中央仓库服务器在外国,中国访问很慢,中央仓库镜像(国内公司提供)就是提高下载速。
阿里云
华为云
10. pom
什么是pom?
Pom全称为project object model,意思为项目对象模型。通过xml表示maven项目,使用pom.xml来实现。
主要描述了项目:包括配置文件,开发者需要遵循的规则,组织和项目的url,项目的依赖性,以及其他所有的项目相关因素。
11.坐标
几何中的坐标
[1]在一个平面中使用 x、y 两个向量可以唯一的确定平面中的一个点。
[2]在空间中使用 x、y、z 三个向量可以唯一的确定空间中的一个点。
Maven 的坐标
使用如下三个向量在 Maven 的仓库中确定一个 Maven 工程。
[1]groupid:定义了项目属于哪个组,举个例子,如果你的公司是mycom,有一个项目为myapp,那么groupId就应该是com.mycom.myapp.
[2]artifactId:当前项目的模块名称
[3]version:当前模块的版本
<groupId>com.mqf.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
注:SNAPSHOT是快照的意思,代表版本不稳定、尚处于开发中的版本;如果设为
Release版本则代表稳定的版本
如何通过坐标在仓库中查找 jar 包?
[1]将 gav 三个向量连起来
com.mqf.maven+Hello+0.0.1-SNAPSHOT
[2]以连起来的字符串作为目录结构到仓库中查找
com/mqf/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar
※注意:我们自己的 Maven 工程必须执行安装操作才会进入仓库。安装的命令是:mvn install
12. 依赖初步认识
简介
A项目需要引用B项目中的类,那么A对B就产生了依赖。
Commons-fileupload依赖Commons-io包。
Maven解析依赖信息时会到本地仓库中查找被依赖的jar包。对于我们自己开发的Maven工程,使用mvn install命令安装后就可以进入仓库。
第二个maven工程
①工程名:HelloFriend
②目录结构与第一个Maven工程相同
③POM文件
<?xml version="1.0" ?>
<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.mqf.maven</groupId>
<artifactId>HelloFriend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>HelloFriend</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.mqf.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
④主程序:在src/main/java/com/mqf/maven目录下新建文件HelloFriend.java
package com.mqf.maven;
import com.mqf.maven.Hello;
public class HelloFriend {
public String sayHelloToFriend(String name){
Hello hello = new Hello();
String str = hello.sayHello(name)+" I am "+this.getMyName();
System.out.println(str);
return str;
}
public String getMyName(){
return "jek";
}
}
⑤测试程序:在/src/test/java/com/mqf/test目录下新建测试文件HelloFriendTest.java
package com.mqf.test;
import org.junit.Test;
import com.mqf.maven.Hello;
import com.mqf. maven.HelloFriend;
public class HelloFriendTest {
@Test
public void testHelloFriend(){
HelloFriend helloFriend = new HelloFriend();
String results = helloFriend.sayHelloToFriend("litingwei");
System.out.println(results);
}
}
说明:
如果我们想要在工程中引入某个jar 包,只需要在pom.xml 中引入其jar 包的坐标即可。比如引入junit的依赖:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Maven 通过groupId、artifactId与version三个向量来定位Maven 仓库其jar 包所在的位置,并把对应的jar 包引入到工程中来。
同理,如果我们想让HelloFriend依赖Hello项目,要在HelloFriend添加Hello的坐标,并把Hello项目安装在本地仓库;
13. Maven生命周期详解
一、Maven的生命周期
Maven的生命周期就是对所有的构建过程进行统一。包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署等几乎所有的构建步骤。
二、详解
只解释一些比较重要和常用的阶段:
validate 验证项目是否正确,所有必要的信息可用
generate-sources
process-sources
generate-resources
process-resources 复制并处理资源文件,至目标目录,准备打包。
compile 编译项目的源代码。
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources 复制并处理资源文件,至目标测试目录。
test-compile 编译测试源代码。
process-test-classes
test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署
prepare-package
package 接受编译好的代码,打包成可发布的格式,如JAR
pre-integration-test
integration-test
post-integration-test
verify 对集成测试的结果执行任何检查,以确保满足质量标准
install将包安装至本地仓库,以让其它项目依赖。
deploy将最终的包复制到远程的仓库,以让其它开发人员与项目共享或部署到服务器上运行。
注意:
执行任何一个生命周期阶段,之前的生命周期阶段都会被执行。
14. 插件和目标
1.**生命周期与插件是相互绑定的。**
- 执行生命周期命令时,需要通过插件来完成。
- compile和test-compile都通过同一个插件完成的。
- 目标:就是插件所需要做的事情,例如:maven-compiler-plugin既可以执行compile,也可以执行testCompile, compile和testCompile是maven-compiler-plugin插件的两个功能;当maven-compiler-plugin插件执行compile的时候,那么compile就是插件的一个最终目标;
15. idea集成maven
1. 配置maven本地仓库地址
2. 非maven项目转maven
选中项目》右键
maven记得一定要选允许自动导入依懒,如下图:
3. 创建maven版的java工程
- 选中Maven选项
- 定义坐标
- 创建成功
- test中加入资源文件夹resource
- 最终项目
4. idea中执行maven命
找到指定的命令直接双击即可
5. 解决当前项目测试乱码问题
执行测试命令,输出到控制台的中文有乱码
解决方案
在当前项目的pom.xml文件中增加插件配置
<build>
<plugins>
<!-- 解决maven test命令时console出现中文乱码乱码 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<configuration>
<!--在一个进程中进行所有测试 ; 默认值:once -->
<forkMode>once</forkMode>
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>
</plugins>
</build>
加入插件后,在执行测试命令,乱码消失:
16.加入maven对jdk的引用
在maven设置对jdk版本信息的目的是,让创建的maven项目使用该版本的jdk编译项目;
【1】设置JDK版本引用: D:DevInstallapache-maven-3.2.2confsettings.xml
<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>
17. 第三个maven工程
工程名称和坐标
主程序
测试程序
18. 依赖进阶
1. 直接依赖和间接依赖
A依赖B,B依赖于C
A和B之间就是直接依赖;
A和C之间就是间接依赖;
依赖关系具有传递性。
依赖的原则:
路径最短者优先
MakeFriend依赖HellFriend,HelloFriend依赖Hello,那么MakeFriend将会优先依赖HelloFriend中的jar包。
路径相同时先声明者优先
这里“声明”的先后顺序指的是dependency标签配置的先后顺序。
MakeFriend同时依赖 Hello(log4j-1.2.7.jar)和HelloFriend(log4j-1.2.14.jar)由于HelloFriend先声明,所以会优先使用 HelloFriend中的log4j-1.2.14.jar。
2.依赖的排除
说明
A项目依赖于B项目,B项目中所依赖的jar包是compile范围;B项目中的依赖jar包就可以传递A项目中;
注意:scope定义了依赖的范围,默认是compile,即使不指定默认也是compile
A项目中如果希望排除掉B项目中传递过来的jar包:可以按照如下配置:
A项目中配置对B项目的依赖:
<dependency>
<groupId>com.mqf.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
使用
案例1:
HelloFriend中声明了对log4j的依赖
MakeFriend依赖了HelloFriend,那么MakeFriend会 自动依赖HelloFriend中compile范围的log4j
也可以排除HelloFriend中compile范围的log4j
在MakeFriend的pom中加入以下配置即可:
案例2:
-
在MakeFriend中加入对 dbcp的依赖,那么dbcp会自动下载与其相关的pool.jar包
-
如果想要排除对commons-pool-1.5.4.jar的依赖,可以加入以下配置:
3.依赖自动消失
3. 统一的版本管理
说明
项目中会对很多第三方框架的jar包进行依赖:
同一个框架的jar包版本应该是一致的,如果希望修改框架的版本时,每一个jar包的版本都需要进行改变;
如果手动一个一个修改配置依赖,太麻烦;可以设置属性标签,定义jar包的版本,然后通过${}表达式来进行引用;
二 、 使用案例
- 定义属性
声明统一的版本号:
<properties>
<spring.version>4.1.1.RELEASE</spring.version>
</properties>
- 通过${}进行版本依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
3.使用示例
4. 依赖范围
说明
maven的依赖范围主要是对
常用的依赖范围有以下三种:
compile
test
provide
主要从对主程序是否有效、对测试程序是否有效、是否参与打包与部署三个方面对比以上三种依赖范围: | type | 对主程序是否有效 | 对测试程序是否有效 | 是否参与打包与部署 | 是否传递 |
---|---|---|---|---|---|
compile | Y | Y | Y | Y | |
test | N | Y | N | N | |
provided | Y | Y | N | N |
举例:
commons-dbutils是compile范围,对主程序、测试程序都有效,参与程序的打包,并且向下传递:
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.3</version>
<scope>compile</scope>
</dependency>
测试
测试test范围的依赖是否对主程序有效
由于junit是 测试范围的依赖,只对测试程序有效,如果将junit的相关依赖包放
主程序,那么将会出错;
在主程序加入junit的相关依赖包地址,发现报错,因为无法使用:
运行测试命令:
提示主程序找不到junit的依赖包,所有test范围依赖只对测试程序有效:
测试test范围依赖是否参与打包
在测试之前需要先引入处理打包的插件,该插件会将第三方依赖包,加入到打包文件:
<build>
<plugins>
<!-- 项目打包插件 -->
<plugin>
<artifactId> maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<!--设置程序入口,不要设置测试程序,因为package 不会打包测试程序 -->
<mainClass>com.mqf.maven.Hello</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
设置成功后:
运行打包命令进行测试,看看junit会不会被打包到文件
查看打包好的文件
解压打包好的文件发现log4j和dbuils被加入到了打包文件,证明test范围的Junit不会参与打包
查看配置好的程序入口
运行打包好的程序测试:
provided范围依赖的作用
我们在使用javaweb项目的时候,创建的jsp和servlet是需要tomcat中的servlet-API依赖包,当该javaweb项目打包后,部署在tomcat服务器上的时候 , tomcat服务器会自动提供servlet-api依赖包,所有我们在打包javaweb项目的时候,不需要把servlet-api加入打包文件。
可以作如下配置:
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1.3-b06</version>
<scope>provided</scope>
</dependency>
19. 继承
多个子工程中依赖同样的jar包,但是采用test范围;由于test范围没有传递性;所以,每一个工程都需要对test范围的jar包进行单独依赖;
而如果希望修改多个工程中所依赖test范围的jar包版本,那么,一个一个项目去修改太麻烦,这时可以应用继承解决。
继承的使用:
(1)定义一个父工程,父工程packaging必须是pom
<packaging>pom</packaging>
项目的打包类型:pom、jar、war
packing默认是jar类型,
<packaging>pom</packaging> ---------> 父类型都为pom类型
<packaging>jar</packaging> ---------> 普通项目打jar包,一般普通项目设置jar
<packaging>war</packaging> ---------> web项目一般都是打war包,web项目的话设置war
(2)在父工程中定义依赖的jar包,属于test范围:
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<!-- test范围表示测试的依赖范围,这个范围的依赖,我们的test中的程序是可以使用;而main中的程序是
不可使用的; 如果是部署到Tomcat下的应用程序,依赖的jar包不能部署到Tomcat环境下的 -->
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
(3)在各个子工程中对父工程进行继承:
<parent> <groupId>com.mqf.maven</groupId> <artifactId>MavenParent</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../MavenParent/pom.xml</relativePath> </parent> |
---|
(4)在各个子工程中对父工程中的包进行依赖,但是,不需要配置版本号和范围(与父工程的版本号和范围一致)
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> |
---|
(5)如果希望修改版本,只需要修改父工程中的依赖jar包版本就可以了,那么,各个子工程中的jar包版本就都变了
(6)一个子工程只能继承一个父工程.
案例
- 父项目加入让子项目依赖的jar包配置
子项目继承父项目(继承后自动使用父类往外暴露的jar包)
HelloFriend项目中的pom:
MakeFriend的pom:
MakeFriend继承了Parent就可以选择使用父工程的pom中暴露的jar包:
20. 项目聚合(一键安装)
聚合:
如果有多个工程需要安装,一个一个工程进行安装,太麻烦了;可以利用聚合,将多个工程管理起来,实现一键安装。
(也就是将一个父工程进行安装,其他被聚合的工程也同时进行安装)
①在父工程中定义modules标签
_<!--_ _项目聚合_ _-->_
<modules>
<module>../Hello</module>
<module>../HelloFriend</module>
<module>../MakeFriend</module>
</modules>
执行安装命令后
21. 酷站
如果项目中需要某个依赖包,但是又不知道坐标怎么写,以下网站可以去搜索我们需要的依赖包,找到后,复制坐标到我们项目的pom.xml文件即可
我们可以到http://mvnrepository.com/搜索需要的jar包的依赖信息
22. 创建maven版web工程
创建Maven的Web工程,需要选择packaging 的值为war
安装普通普通maven项目转web项目的插件JBLJavaToWeb
找到后直接安装
先创建一个普通的maven项目
选中创建的项目右键,选中JblJavaToWeb
创建成功后的项目结构
在pom中加入servlet-api和jsp-api相关依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1.3-b06</version>
<scope>provided</scope>
</dependency>
23. 项目部署tomcat
项目部署tomcat的方式有两种:
1.使用本地的tomcat
2。使用tomcat插件
1. 使用本地的tomcat
点击
点击+
点击fix
如果修改了jsp,需要更新一下资源
2. 使用tomcat插件
修改pom.xml添加tomcat插件的配置
<**build**>
<**plugins**>
<**plugin**>
<**groupId**>org.apache.tomcat.maven</**groupId**>
<**artifactId**>tomcat7-maven-plugin</**artifactId**>
<**version**>2.2</**version**>
<**configuration**>
_<!--__端口控制__-->_ <**port**>8080</**port**>
_<!--__项目路径控制意味着__http://localhost:8080/abc-->_ <**path**>/WebMaven</**path**>
_<!--__编码__-->_ <**uriEncoding**>UTF-8</**uriEncoding**>
</**configuration**>
</**plugin**>
</**plugins**>
双击tomcat7:run
修改了jsp,不用更新,直接刷新浏览器就可以了
不管是哪一种,如果是修改java代码,都重启tomcat
常见错误
重复双击tomcat&:run,导致同时启动多个tomcat
24. 私服
1. 私服介绍
Maven 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。
建立了 Maven 私服后,当局域网内的用户需要某个构件时,会按照如下顺序进行请求和下载。
请求本地仓库,若本地仓库不存在所需构件,则跳转到第 2 步;
请求 Maven 私服,将所需构件下载到本地仓库,若私服中不存在所需构件,则跳转到第 3 步。
请求外部的远程仓库,将所需构件下载并缓存到 Maven 私服,若外部远程仓库不存在所需构件,则 Maven 直接报错。
此外,一些无法从外部仓库下载到的构件,也能从本地上传到私服供其他人使用。
下图中展示了 Maven 私服的用途。
2. Nexus
Nexus 的全称是 Nexus Repository Manager(Nexus 仓库管理器),是 Sonatype 公司的一个产品。Nexus 是一个强大的仓库管理器,极大地简化了内部仓库的维护和外部仓库的访问。
3. Nexus 仓库分类
Nexus 仓库按照类型(Type)区分,主要分为以下 3 个类型:
代理仓库(proxy):用来代理远程公共仓库,如 Maven 中央仓库。
宿主仓库(hosted):又称 Nexus 本地仓库,该仓库通常用来部署本地项目所产生的构件。
仓库组(group):用来聚合代理仓库和宿主仓库,为这些仓库提供统一的服务地址,以便 Maven 可以更加方便地获得这些仓库中的构件。
为了更加直观的理解仓库组、代理仓库和宿主仓库的概念,我们通过下图展示它们的用途和区别。
由上图可知:
Maven 可以直接从宿主仓库中下载构件。
Maven 也可以从代理仓库中下载构件,代理仓库会从远程仓库下载并缓存构件。
Maven 还可以从仓库组中下载构件,仓库组会从其包含的宿主仓库和代理仓库中获取构件。
4. Nexus安装和使用
nexus的下载链接为:https://download.csdn.net/download/qq_34091529/87967563
链接中包含Nexus 2.x 和 Nexus 3.x 两个版本,直接破解使用即可;
目前 Nexus 分为 Nexus 2.x 和 Nexus 3.x 两个大版本,它们是并行的关系,目前使用最多,运行最稳定的是 Nexus 2.x,下面我们以 Nexus 2.x 为例,演示 Nexus 的安装过程。
- 将下载 Nexus 安装包解压到本地磁盘,可获得 nexus-2.14.20-02 和 sonatype-work 2 个目录,如下图。
图2:Nexus 2.x 目录
其中:
nexus-2.14.20-02:该目录中包含了 Nexus 2.x 运行所需要的文件,如启动脚本、依赖 jar 包等。
sonatype-work:该目录中包含了 Nexus 2.x 生成的配置文件、日志文件等。
- nexus-2.14.20-02 中包含以下目录及文件。
图3:nexus-2.14.20-02 目录及文件列表
nexus-2.14.20-02 目录说明,如下表所示。
子目录 | 说明 |
---|---|
bin | 命令中心(启动命令,关闭命令) |
conf | 配置中心(管理着仓库列表、日志配置,以及安全设置) |
lib | Nexus 的库文件,Nexus 运行时需要的 jar 包所在的目录 |
logs | 存放日志文件 |
nexus | Nexus 应用程序 |
tmp | 存放Nexus 运行时产生的临时文件 |
4. .进入 nexus-2.14.20-02binjsw 文件夹,根须操作系统版本选择合适的目录,由于我的操作系统是 Windows 10 64 位,所以我选择 windows-x86-64 目录,如下图所示。
图4:nexus-2.14.20-02binjsw 目录列表
- 进入 windows-x86-64 目录后可以看到如下文件。
图5:Nexus 启动文件列表
其中:
console-nexus.bat:启动 Nexus 并在 DOS 命令行中展示启动过程。
install-nexus.bat:将 Nexus 安装为 Windows 服务,开机自动启动。
start-nexus.bat:启动 Nexus。
stops-nexus.bat:停止 Nexus。
uninstall-nexus.bat:与 install-nexus.bat 相对应,负责卸载 Nexus 服务。
- 双击运行 install-nexus.bat 安装 Nexus 服务,然后运行 start-nexus.bat 启动服务。
注意:
运行 install-nexus.bat 安装服务,若提示”wrapper | OpenSCManager failed – 拒绝访问。 (0x5)“,只要关闭窗口,以管理员身份运行即可解决。
运行 start-nexus.bat 启动服务,若提示”wrapper | OpenSCManager failed – 拒绝访问。 (0x5)“,只要关闭窗口,以管理员身份运行即可解决。
图6:Nexus 首页
- 点击首页右上角的“Log In”按钮,在登录页面输入用户名和密码(默认分别为:admin 和 admin123 ),最后点击“Log In”按钮登录。
图7:Nexus 登录界面
- 登录成功后,结果如下图。
图8:Nexus 登录成功
5. Nexus仓库属性和分类
Nexus 作为一款 Maven 仓库管理器,仓库(Repository)自然是 Nexus 最核心的概念。Nexus 中提供了许多仓库概念,如代理仓库、宿主仓库以及仓库组等。Nexus 为每一种仓库都提供了丰富的配置参数,方便我们根据自身需要进行定制。
Nexus 仓库属性
点击左边导航栏中的 Repositories,可以看到 Nexus 自带的几个内置仓库,如下图所示。 图1:Nexus 内置仓库列表
在仓库列表中,每个仓库都具有一系列属性:
-
Type:仓库的类型,Nexus 中有 4 中仓库类型:group(仓库组)、hosted(宿主仓库)、proxy(代理仓库)以及 virtual(虚拟仓库)。
-
Format:仓库的格式。
-
Policy:仓库的策略,表示该仓库是发布(Release)版本仓库还是快照(Snapshot)版本仓库。
-
Repository Status:仓库的状态。
-
Repository Path:仓库的路径。
由图 1 可知,Nexus 2.x 默认创建了 6 个仓库,我们称它们为 Nexus 内置仓库。
Maven Central:该仓库用来代理 Maven 中央仓库,其策略为 Release,只会下载和缓存中央仓库中的发布版本的构件。
Releases:策略为 Release 的宿主仓库,用来部署公司或组织内部的发布版本构件。
Snapshots:策略为 Snapshot 的宿主仓库,用来部署公司或组织内部的快照版本构件。
3rd party:策略为 Release 的宿主仓库,用来部署第三方发布版本构件,这些构件一般无法从任何远程仓库中获得。
Public Repositories:该仓库组将上述所有存储策略为 Release 的仓库聚合并通过统一的地址提供服务。
6. 创建仓库
1) 创建 Nexus 宿主仓库
首先,我们需要创建两个宿主仓库,分别用来存储从本地上传到 Nexus 的 Snapshot 和 Release 版本的构件,操作步骤如下。
- 点击左边导航栏中的 Repositories,如下图:
图1:Nexus 导航
- 点击 Nexus 仓库列表上方的 Add… 按钮,在下拉菜单中选择 Hosted Repository,如下图。
图2:添加宿主仓库
- 在宿主仓库配置界面,填写对应信息,然后点击 Save 按钮进行保存,如下图。
图3:配置宿主仓库
宿主仓库配置如下:
配置 | 说明 |
---|---|
Repository ID | 仓库 ID。 |
Repository Name | 仓库名称。 |
Repository Type | 仓库的类型,如 hosted、proxy 等等。 |
Provider | 用来确定仓库的格式,一般默认选择 Maven2。 |
Repository Policy | 仓库的策略。 |
Default Local Storage Location | 仓库默认存储目录,例如 D:nexus-2.14.20-02-bundlesonatype-worknexusindexerbianchengbang_Snapshot_hosted_ctx。 |
Override Local Storage Location | 自定义仓库存储目录。 |
Deployment Policy | 仓库的部署策略。 |
Allow File Browsing | 用来控制是否允许浏览仓库内容,一般选择 true。 |
Include in Search | 用来控制该仓库是否创建索引并提供搜索功能。 |
Publish URL | 用来控制是否通过 URL 提供服务。 |
Not Found Cache TTL | 缓存某构件不存在信息的时间,默认取值为 1440,表示若某一个构件在仓库中没有找到,在 1440 分钟内再次接收到该构件的请求,则直接返回不存在信息,不会再次查找。 |
- 查看 Nexus 仓库列表,可以看到自定义的宿主仓库已经创建完成,如下图。
图4:Nexus 仓库列表
重复以上步骤,再创建一个名称为 bianchengbang_Release_hosted ,策略为 hosted 的宿主仓库。
图5:Nexus 仓库列表-宿主仓库
2) 创建 Nexus 代理仓库
下面我们创建一个代理仓库,用来下载和缓存中央仓库的构件,操作步骤如下。
点击 Nexus 仓库列表上方的 Add… 按钮,在下拉菜单中选择 Proxy Repository,如图 5 所示。
图5:添加代理仓库
在代理仓库配置界面,填写对应信息,然后点击 Save 按钮进行保存,如图 6 所示。
代理仓库配置中,仓库 ID、仓库名称、Provider、Policy 以及 Default Local Storage Location 等配置的含义与宿主仓库相同,不再赘述。需要注意的是,代理仓库的 Repository Type 的取值是 proxy。
代理仓库配置如下表。 | 配置 | 说明 |
---|---|---|
Remote Storage Location | 远程仓库或中央仓库的地址,它是 Nexus 代理仓库最重要得配置,必须输入有效值,通常取值为 https://repo1.maven.org/maven2/。也可以使用阿里云镜像: https://maven.aliyun.com/nexus/content/groups/public | |
Download Remote Indexes | 是否下载远程仓库的索引。 | |
Auto Blocking Enabled | 是否启用自动阻止,即当 Nexus 无法连接中央仓库或远程仓库时,是否一直等待。取值为 true 表示不再等待,直接通知客户端无法连接,并返回。 | |
File Content Validation | 是否启用文件内容校验。 | |
Checksum Policy | 配置校验和出错时的策略,用户可以选择忽略、警告、记录警告信息或拒绝下载等多种策略。 | |
Artifact Max Age | 构件缓存的最长时间,对于发布版本仓库来说,默认值为 -1,表示构件缓存后,就一直保存着,不再重新下载。对于快照版本仓库来说,默认值为 1440 分钟,表示每隔一天重新缓存一次代理的构件。 | |
Metadata Max Age | 仓库元数据缓存的最长时间。 | |
Item Max Age | 项目缓存的最长时间。 |
3) 创建 Nexus 仓库组
下面我们将创建一个仓库组,并将刚刚创建的 3 个仓库都聚合起来,操作步骤如下。
点击仓库列表上方的 Add… 按钮,在下拉菜单中选择 Repository Group,如下图。
图7:Nexus 添加仓库组
在仓库组配置界面,填写对应信息,并将 bianchengbang_central_proxy、bianchengbang_Release_hosted 和 bianchengbang_Snapshot_hosted 3 个仓库添加到仓库组中,最后点击 Save 按钮进行保存,如下图。
图8:Nexus 仓库组配置
查看 Nexus 仓库列表,可以看到 bianchengbang_repository_group 仓库组已经创建完成,如下图。
图9:Nexus 仓库列表-仓库组
7. 索引
我们知道,Maven 中央仓库为用户提供了多达数十万构件,而 Nexus 可以代理所有的远程仓库(包括 Maven 中央仓库),可见 Nexus 仓库中构件的数量相当庞大。用户想要在这么多构件中,快速的查找自己所需的构件,一个最直接有效的方式就是:搜索。
Nexus 作为一款成熟的仓库管理工具,它通过维护仓库的索引提供了构件搜索功能,以便帮助用户方便快速地找到所需构件。
本节我们将详细为您介绍 Nexus 索引以及构件搜索功能。
索引
Nexus 能够遍历仓库的所有内容,搜集它们的坐标,校验和以及所包含的 Java 类等信息,然后以索引( nexus-indexer) 的形式保存起来。Nexus 索引保存在 Nexus 安装目录下 sonatype-worknexusindexer 目录中,该目录下每个子目录都代表 Nexus 中的一个仓库,用来存放各个仓库的索引 ,如下图所示。
大多数的远程公共仓库(例如,中央仓库)都维护了一个这样的索引,因此本地的 Nexus 在下载到这个索引后,就能在此基础上为用户提供构件搜索和浏览等服务。需要注意的是,并不是所有的公共仓库都提供了索引 ,对于那些没有提供索引的仓库来说,我们是无法对其进行搜索的。
1) 下载索引
Nexus 索引下载功能默认是关闭的,如果想在 Nexus 中搜索远程仓库中的构件,就需要先开启索引下载功能。
以 bianchengbang_central_proxy 代理仓库(代理 Maven 中央仓库)为例,在图 2 所示的位置就可以控制它的索引下载功能,true 表示开启索引下载,false 表示关闭索引下载。
开启索引下载功能后,点击导航栏中 Scheduled Tasks 链接,查看调度任务列表。若 Nexus 正在下载索引,我们就能看到如图 3 所示的任务,其任务状态为 Running。在索引下载完毕后,该任务就会消失。
图3:Nexus 调度任务列表
由于 Maven 中央仓库的内容较多,其索引文件比较大,因此 Nexus 下载该文件所需的时间较长,需要我们耐心等待。
索引下载完成后,点击仓库列表中的 bianchengbang_central_proxy 代理仓库,然后在列表下方选择 Browse Index 选项卡,我们可以看到该仓库内容的树形结构,如图 4 所示。
2) 构件搜索
Nexus 通过维护索引,为用户提供了关键字搜索、类名搜索、坐标搜索等多种搜索功能,通过这些功能,页面中能够清晰地展示出结果构件的坐标以及所属仓库。用户可以直接下载相应的构件,也可以直接复制构件的 XML 依赖声明,到项目中使用。
在 Nexus 界面左边导航栏中有一个搜索框,在搜索框内输入所需构件的关键字,单击搜索按钮就能快速得到搜索结果,如图 5 所示。
图5:Nexus 搜索功能
搜索结果页中的每一行代表一类构件,其中包含了 Group、Artifact、版本、流行版本、以及下载链接等信息。点击其中某一行,下方就会出现该构件的详细信息,其中不但包含构件的坐标等基本信息,还包含一段 XML 依赖声明,我们可以将这段 XML 依赖声明直接复制到项目的 POM 中使用,如图 6 所示。
图6:Nexus 搜索结果详情
点击右侧的 Artifact 选项卡,还能看到构件的大小、上传时间、最后修改时间、仓库中的相对位置、校验和等信息,如图 7 所示。
图7:Nexus 搜索详情页 Artifact
除了关键字搜索外,Nexus 还提供了一些高级搜索功能,例如类名搜索、GAV 搜索以及“校验和”搜索。我们可以通过点击搜索页左上角的下拉菜单,选择高级搜索功能。
图8:Nexus 高级搜索功能
Nexus 还具有以下高级搜索功能:
类名搜索(Keyword Search):搜索包含某个 Java 类的构件。
GAV 搜索(GAV Search):通过设置 Group、Artifact、版本等信息进行搜索。
校验和搜索(Checksum Search):通过使用“校验和”搜索构件。
这些搜索功能的使用都十分的简单,我们可以根据自己的需求选择合适的搜索功能。
8. 从Nexus下载构件
Nexus 作为最流行的 Maven 私服之一,使用它主要目的之一:代理远程仓库,即当 Maven 需要下载构件到本地仓库使用时,不再请求外部的远程仓库,而直接从 Nexus 中下载。本节我们将介绍如何配置 Maven 从 Nexus 下载构件。
将 Nexus 的代理仓库配置到 Maven 项目中,用它们代替外部的远程仓库,即可实现 Maven 从 Nexus 下载构件。
1) 在 pom.xml 中配置
在 Maven 项目的 pom.xml 中增加以下配置,可以为当前项目配置 Nexus 上的 bianchengbang_central_proxy 代理仓库。
<!--声明一个或多个远程仓库 -->
<repositories>
<!-- 声明一个 Nexus 私服上的仓库 -->
<repository>
<!--仓库id -->
<id>nexus</id>
<!-- 仓库的名称 -->
<name>nexus</name>
<!--仓库的地址 -->
<url>http://localhost:8082/nexus/content/repositories/bianchengbang_central_proxy/</url>
<!-- 是否开启该仓库的 release 版本下载支持 -->
<releases>
<enabled>true</enabled>
</releases>
<!-- 是否开启该仓库的 snapshot 版本下载支持 -->
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<!-- 声明一个或多个远程插件仓库 -->
<pluginRepositories>
<!--声明一个 Nexus 私服上的插件仓库 -->
<pluginRepository>
<!--插件仓库 id -->
<id>nexus</id>
<!--插件仓库 名称 -->
<name>nexus</name>
<!-- 配置的插件仓库的地址 -->
<url>http://localhost:8082/nexus/content/repositories/bianchengbang_central_proxy/</url>
<!-- 是否开启该插件仓库的 release 版本下载支持 -->
<releases>
<enabled>true</enabled>
</releases>
<!-- 是否开启该插件仓库的 snapshot 版本下载支持 -->
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
其中,在 repositories 元素下可以使用 repository 子元素声明一个或多个远程仓库,一个 repository 元素对应一个远程仓库。
repository 各个子元素含义如下表。
子元素 | 含义 |
---|---|
id | 仓库的唯一标识。需要注意的是,Maven 中央仓库的 id 为 central,如果其他的仓库也使用该 id,就会覆盖中央仓库的配置。 |
name | 仓库的名称。 |
url | 仓库的地址,该地址一般都是基于 HTTP 协议的,通过浏览器即可访问该地址,浏览仓库中的构件。 |
releases/snapshots | 用来控制 Maven 对于发布和快照版本构件的下载。它们都有一个 enabled 子元素,enabled 的取值为 true,表示开启发布版或快照版的下载支持,否则表示关闭下载支持。 |
在 pluginRepositories 元素下可以使用 pluginRepository 子元素声明一个或多个远程插件仓库(包括私服上的仓库),一个 pluginRepository 元素对应一个远程插件仓库。pluginRepository 下所有子元素的含义均与与 repository 的子元素相同,这里就不再做过多赘述了。
示例**:**
将以上配置加入 Maven 项目 Root 的 POM 文件中,并手动清空本地仓库的所有依赖构件(目的是为了让 Maven 重新获取构件)。
打开命令行窗口,跳转到 Root 所在的目录下,执行以下 mvn 命令。
mvn clean install
执行结果如下。
图1: 使用 Nexus 私服构建结果
由图 1 的构建过程可以看出,Root 项目构建所需的构建是从 Nexus 私服的 banchengbang_central_proxy 代理仓库中下载的,而不是从 Maven 中央仓库去下载。
2) 在 setting 中配置
在 pom.xml 中配置 Nexus ,只对当前项目有效,在实际应用中,我们往往希望能够通过一次配置就能让本机中的所有 Maven 项目都使用 Nexus。此时,您可能会想到在 Maven 的 setting.xml 文件中进行配置,但 setting.xml 是不支持直接配置 repositories 和 pluginRepositories 。所幸 Maven 提供了 profile 机制,能够让我们将仓库配置放在 profile 中。
<profiles>
<profile>
<id>nexus</id>
<!--声明一个或多个远程仓库 -->
<repositories>
<!-- 声明一个 Nexus 私服上的仓库 -->
<repository>
<!--仓库id -->
<id>nexus</id>
<!-- 仓库的名称 -->
<name>nexus</name>
<!--仓库的地址 -->
<url>http://localhost:8082/nexus/content/repositories/bianchengbang_central_proxy/</url>
<!-- 是否开启该仓库的 release 版本下载支持 -->
<releases>
<enabled>true</enabled>
</releases>
<!-- 是否开启该仓库的 snapshot 版本下载支持 -->
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<!-- 声明一个或多个远程插件仓库 -->
<pluginRepositories>
<!--声明一个 Nexus 私服上的插件仓库 -->
<pluginRepository>
<!--插件仓库 id -->
<id>nexus</id>
<!--插件仓库 名称 -->
<name>nexus</name>
<!-- 配置的插件仓库的地址 -->
<url>http://localhost:8082/nexus/content/repositories/bianchengbang_central_proxy/</url>
<!-- 是否开启该插件仓库的 release 版本下载支持 -->
<releases>
<enabled>true</enabled>
</releases>
<!-- 是否开启该插件仓库的 snapshot 版本下载支持 -->
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
以上配置中使用了一个 id 为 nexus 的 profile,这个 profile 中包含了与仓库相关的配置,同时配置中还使用了一个 activeProfiles 元素将 id 为 nexus 的 profile 激活。当本机有 Maven 项目构建时,profile 中的仓库配置就会应用到项目中。
示例**:**
将以上配置分别添加到 Maven 安装目录conf 和本地仓库目录下的 setting.xml 中,并将 Root 项目 POM 文件中的 repositories 和 pluginRepositories 等仓库设置删除。
打开命令行窗口,跳转到 Root 项目下,执行以下 mvn 命令。
mvn clean install
执行结果如下。
3)setting.xml 中添加镜像**:**
Nexus 私服通常会与镜像(mirror)结合使用,使 Nexus 成为所有远程仓库的私服,这样不仅可以从 Nexus 中获取所有所需构件,还能将配置集中到 Nexus 私服中,简化 Maven 本身的配置。
我们可以创建一个匹配任何仓库的镜像,镜像的地址为 Nexus 中仓库的地址,这样 Maven 对于任何构件的下载请求都会被拦截跳转到 Nexus 私服中,其具体配置如下。
<!-- 配置只有maven项目下载依赖都会从私服下载 -->
<mirrors>
<mirror>
<id>nexus</id>
<name>nexus name</name>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8082/nexus/content/groups/bianchengbang_repository_group/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>central</id>
<url>http://localhost:8082/nexus/content/repositories/bianchengbang_central_proxy/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://localhost:8082/nexus/content/repositories/bianchengbang_central_proxy/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
仓库和插件仓库的配置中,它们的 id 取值都是 central,即它们的设置覆盖了 Maven 中央仓库,但此时这里的 URL 已经无法起到任何作用,因为镜像的匹配规则是 *,所有的请求都已经被拦截,跳转到 Nexus 私服的地址。
9. 部署构件到Nexus
如果仅仅是为了代理远程的公共仓库,那么 Nexus 的代理仓库就完全能够满足需要,但是我们知道,Nexus 除了代理仓库外,还有另一种仓库:宿主仓库。
宿主仓库的主要作用是存储公司或组织内部的构件,以及一些无法从公共仓库获取的第三方构件(JDBC 驱动),供用户下载使用。用户可以通过配置 Maven 将构件自动部署到 Nexus 宿主仓库,也可以在 Nexus 界面手动上传构件。
1) 使用 Maven 部署构件到 Nexus
日常开发中,快照版本构件可以直接部署到 Nexus 中策略为 Snapshot 的宿主仓库中,而最终发布的版本则应该部署到 Nexus 中策略为 Release 的宿主仓库中。
使用 Maven 将构件部署到 Nexus 宿主仓库中主要分为 3 步:
配置项目的 POM 文件。
在 setting.xml 中配置认证信息。
使用 mvn 命令部署构件。
1. 下面我们通过一个实例来详细介绍如何使用 Maven 部署构件到 Nexus 宿主仓库。
- 配置项目的 POM 文件
创建一个名为 test-upload-snapshot 的 Maven 项目,并在其 POM 文件中添加如下配置。
<project>
<distributionManagement>
<repository>
<id>bianchengbang_Release_hosted</id>
<url>http://localhost:8082/nexus/content/repositories/bianchengbang_Release_hosted </url>
</repository>
<snapshotRepository>
<id>bianchengbang_Snapshot_hosted</id>
<url>http://localhost:8082/nexus/content/repositories/bianchengbang_Snapshot_hosted</url>
</snapshotRepository>
</distributionManagement>
</project>
以上配置说明如下:
distributionManagement 元素:负责将指定的构件部署到 Nexus 指定的仓库中。
repository 元素:distributionManagement 的子元素,用于定义部署 Release 版本的构件被部署的仓库。它有 2 子元素:id 和 url ,其中 id 为 Nexus 仓库的唯一标识,url 为 Nexus 宿主仓库的 url。
snapshotRepository 元素:distributionManagement 的子元素,用于定义部署 Snapshot 版本的构件被部署的仓库。它也有 2 子元素:id 和 url ,且与 repository 中含义一致。
2. 在 setting.xml 中配置认证信息
最初版本的 Nexus 没有为宿主仓库提供任何的安全措施。如果宿主仓库开启了部署功能,任何人可以连接并部署构件至这个仓库,这显然是极不安全的。因此,现在的 Nexus 中增加了权限认证,Nexus 对于匿名用户是只读的,若想部署构件到 Nexus 中,则需要在 setting.xml 中配置如下认证信息。
<settings>
...
<servers>
<server>
<id>bianchengbang_Release_hosted</id>
<username>admin</username>
<password>admin123</password>
</server>
<server>
<id>bianchengbang_Snapshot_hosted</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>
</settings>
注意:以上配置中,server 元素中的 id 必须和 pom.xml 中 distributionManagement 元素对应仓库的 id 保持一致。Maven 在部署构件时,会先根据 id 查找用户名称和密码进行认证和登录,然后将构件部署到对应得宿主仓库。
3. 使用 mvn 命令部署构件
完成以上配置之后,就可以使用 Maven 命令将构件部署到宿主仓库了,操作步骤如下。
1)打开命令行窗口,跳转到 test-upload-snapshot 项目得目录下,执行如下 Maven 命令。
mvn clean deploy
2) Maven 命令执行结果如下图。
[INFO] Scanning for projects…
[INFO]
[INFO] —————< net.biancheng.www:test-upload-snapshot >—————
[INFO] Building test-upload-snapshot 0.0.1-SNAPSHOT
[INFO] ——————————–[ jar ]———————————
[INFO]
[INFO] — maven-clean-plugin:2.5:clean (default-clean) @ test-upload-snapshot —
[INFO] Deleting D:eclipse workSpace 3test-upload-snapshottarget
[INFO]
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 2.342 s
[INFO] Finished at: 2021-03-22T11:03:44+08:00
[INFO] ————————————————————————
在 Nexus 界面的仓库列表选中 bianchengbang_Snapshot_hosted 宿主仓库,在下方的 Browse Index 选项卡中,可以看到 test-upload-snapshot 构件已经被部署到该仓库中,如图 1 所示。
2) 手动上传构件
有些 Jar 文件(如 Oracle 的 JDBC 驱动)由于许可证等原因,无法存放在公开仓库中。此外,还有一些小型的开源项目,它们没有将自己的构件分发到公共仓库中,也没有维护自己的仓库,因此这些构件是无法从公共仓库中获得的。若 Maven 项目中需要这类构件,我们就需要将构件下载到本地,然后手动上传到 Nexus 私服。
我们还是以 Maven 项目 App-Core-lib 为例,将其打包后手动上传到 Nexus 内置宿主仓库 3rd party 中,具体步骤如下。
- 打开命令行窗口,跳转到 App-Core-lib 的目录下,执行如下 mvn 命令,对项目进行打包。
mvn clean package
2.打包完成后,进入 App-Core-libtarget 目录,可以看到 Maven 已经将该项目打包成了一个 jar 文件,如图 2 所示。
- 在 Nexus 界面的仓库列表中选择 3rd party 仓库,在下方选择 Artifact Upload 选项卡,其中 GAV Definition 用于定义上传构件的坐标信息。
GAV Definition 中提供了两种定义构件坐标的方式:
若该构件通过 Maven 构建产生的,则可以选择 From POM,Nexus 会自动从 POM 中获取构件的坐标。
若该构件来自第三方,则只能选择 GAV Parameters,手动定义构件的坐标。
以上 2 种方式操作时会略有不同,下面我们分别对它们进行介绍。
From POM
若该构件是通过 Maven 构建产生的,那么可以在 GAV Definition 下拉列表中,选择 From POM,然后指定该构件所属项目的 pom.xml,Nexus 会自动从 pom.xml 中获取构件的坐标。最后点击页面最下方的 Upload Artifact(s) 按钮,将构件上传到仓库中,如图 3 所示。
GAV Paramters
若构件不是通过 Maven 构建的,而是来自第三方(例如 Oracle 的 JDBC 驱动),则只能在 GAV Definition 下拉列表中,选择 GAV Parameters 手动定义构件的坐标。
定义好坐标后,点击 Select Artifact(s) to Upload… 按钮选择要上传的构件,然后点击 Add Artifact 按钮将其加入上传列表中。最后点击页面最下方的 Upload Artifact(s) 按钮,将构件上传到仓库中,如图 4 所示。
在仓库列表中选中 3rd party 宿主仓库,在下方的 Browse Index 选项卡中,可以看到构件已经被部署到该仓库中,如图 5 所示。