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]。![]
file

什么是构建

构建就是以我们编写的 Java 代码、框架配置文件、国际化等其他资源文件、JSP 页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。

构建过程的几个主要环节

①**清理:删除以前的编译结果,为重新编译做好准备。
**编译:将 Java 源程序编译为字节码文件。
③**测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
**报告:在每一次测试后以标准的格式记录和展示测试结果。
⑤**打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java 工程对应 jar 包,Web 工程对应 war 包。
**安装:在 Maven 环境下特指将打包的结果——jar 包或 war 包安装到本地仓库中。
⑦**部署**:将打包的结果部署到远程仓库或将 war 包部署到服务器上运行。

 自动化构建

我们为什么还要使用 Maven 这样的构建工具呢?我们来看一个小故事:

这是阳光明媚的一天。托马斯向往常一样早早的来到了公司,冲好一杯咖啡,进入了自己的邮箱——很 不幸,QA小组发来了一封邮件,报告了他昨天提交的模块的测试结果——有 BUG。“好吧,反正也不是第一 次”,托马斯摇摇头,进入IDE,运行自己的程序,编译、打包、部署到服务器上,然后按照邮件中的操作 路径进行测试。“嗯,没错,这个地方确实有问题”,托马斯说道。于是托马斯开始尝试修复这个 BUG,当他 差不多有眉目的时候已经到了午饭时间。
下午继续工作。BUG 很快被修正了,接着托马斯对模块重新进行了编译、打包、部署,测试之后确认没 有问题了,回复了 QA 小组的邮件。
一天就这样过去了,明媚的阳光化作了美丽的晚霞,托马斯却觉得生活并不像晚霞那样美好啊。

让我们来梳理一下托马斯这一天中的工作内容 :

3. Maven的下载和安装

  1. 下载地址:Maven – Introduction

  2. 点击下载

  1. 下载历史版本

下一步:

下载即可

安装maven核心程序

1、解压maven核心程序安装包,放在一个非中文无空格的文件夹中

  1. 配置maven的相关环境变量

 新增环境变量名:MAVEN_HOME 或者 M2_HOME;

变量值为安装目录bin目录的上一级目录;

                

 Path:%M2_HOME%bin            

  

  1. 验证:运行 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

 命令执行后会有一个下载,

  1. 下载完指定的插件,并编译了主程序后的日志:

  

 3. 主程序编译后文件存放的目录

  

发现刚才所写的文件都给我们编译好了。编译函的文件存在于classes中

  

  1. 运行mvn test-compile 编译测试程序

可以查看编译好的测试程序

  1. 运行mvn test 运行测试程序进行测试

注:mvn test命令执行的是test目录中,类名是***Test.java中带有@Test注解的方法

8.  关于联网下载的问题

  1.  Maven的核心程序中仅仅定义了抽象的生命周期,但是具体的工作必须由特定的插件来完成。而插件本身并不包含在Maven的核心程序中。
  2. 当我们执行的Maven命令需要用到某些插件时,Maven核心程序会首先到本地仓库中查找。
  3. 本地仓库的默认位置︰C:Users[登录当前系统的用户名].m2repository
  4. Maven核心程序如果在本地仓库中找不到需要的插件,那么它会自动连接外网,到中央仓库下载。
  5. 如果此时无法连接外网,则构建失败。
  6. 由于maven默认的本地仓库的目录是C:Users[登录当前系统的用户名].m2repository,当然也可以进行修改,步骤如下: 

              [1]找到Maven解压目录confsettings.xml

              [2]在settings.xml文件中找到localRepository标签

              [3]将/path/to/local/repo从注释中取出

              [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.**生命周期与插件是相互绑定的。**

  1. 执行生命周期命令时,需要通过插件来完成。
  2. compile和test-compile都通过同一个插件完成的。
  3. 目标:就是插件所需要做的事情,例如: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工程

  1. 选中Maven选项

  1. 定义坐标

  1. 创建成功

  1. test中加入资源文件夹resource

  1. 最终项目

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:

  1. 在MakeFriend中加入对 dbcp的依赖,那么dbcp会自动下载与其相关的pool.jar包         

  2. 如果想要排除对commons-pool-1.5.4.jar的依赖,可以加入以下配置:      

3.依赖自动消失

        

 3. 统一的版本管理

说明

项目中会对很多第三方框架的jar包进行依赖:

同一个框架的jar包版本应该是一致的,如果希望修改框架的版本时,每一个jar包的版本都需要进行改变;

如果手动一个一个修改配置依赖,太麻烦;可以设置属性标签,定义jar包的版本,然后通过${}表达式来进行引用;

二 、 使用案例

  1. 定义属性

声明统一的版本号:

<properties>
<spring.version>4.1.1.RELEASE</spring.version>
</properties>
  1. 通过${}进行版本依赖:
<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的依赖范围主要是对标签中的标签中的值的设置; scope的默认依赖范围是compile;

常用的依赖范围有以下三种:

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)一个子工程只能继承一个父工程.

案例

  1.  父项目加入让子项目依赖的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 的安装过程。

  1. 将下载 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 生成的配置文件、日志文件等。

  1. 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 目录列表

  1. 进入 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 服务。

  1. 双击运行 install-nexus.bat 安装 Nexus 服务,然后运行 start-nexus.bat 启动服务。

注意:

运行 install-nexus.bat 安装服务,若提示”wrapper  | OpenSCManager failed – 拒绝访问。 (0x5)“,只要关闭窗口,以管理员身份运行即可解决。

运行 start-nexus.bat 启动服务,若提示”wrapper  | OpenSCManager failed – 拒绝访问。 (0x5)“,只要关闭窗口,以管理员身份运行即可解决。

  1. 访问 http://localhost:8081/nexus,结果如下图,则表示服务启动成功,否则表示服务启动失败
     

图6:Nexus 首页

  1. 点击首页右上角的“Log In”按钮,在登录页面输入用户名和密码(默认分别为:admin 和 admin123 ),最后点击“Log In”按钮登录。
     

图7:Nexus 登录界面

  1. 登录成功后,结果如下图。
     

图8:Nexus 登录成功

5. Nexus仓库属性和分类

Nexus 作为一款 Maven 仓库管理器,仓库(Repository)自然是 Nexus 最核心的概念。Nexus 中提供了许多仓库概念,如代理仓库、宿主仓库以及仓库组等。Nexus 为每一种仓库都提供了丰富的配置参数,方便我们根据自身需要进行定制。

Nexus 仓库属性

点击左边导航栏中的 Repositories,可以看到 Nexus 自带的几个内置仓库,如下图所示。​ 图1:Nexus 内置仓库列表

在仓库列表中,每个仓库都具有一系列属性:

  1. Type:仓库的类型,Nexus 中有 4 中仓库类型:group(仓库组)、hosted(宿主仓库)、proxy(代理仓库)以及 virtual(虚拟仓库)。

  2. Format:仓库的格式。

  3. Policy:仓库的策略,表示该仓库是发布(Release)版本仓库还是快照(Snapshot)版本仓库。

  4. Repository Status:仓库的状态。

  5. 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 版本的构件,操作步骤如下。

  1. 点击左边导航栏中的 Repositories,如下图:

图1:Nexus 导航

  1. 点击 Nexus 仓库列表上方的 Add… 按钮,在下拉菜单中选择 Hosted Repository,如下图。
     

图2:添加宿主仓库

  1. 在宿主仓库配置界面,填写对应信息,然后点击 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 分钟内再次接收到该构件的请求,则直接返回不存在信息,不会再次查找。
  1. 查看 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 宿主仓库。

  1. 配置项目的 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 中,具体步骤如下。

  1. 打开命令行窗口,跳转到 App-Core-lib 的目录下,执行如下 mvn 命令,对项目进行打包。

mvn clean package

2.打包完成后,进入 App-Core-libtarget 目录,可以看到 Maven 已经将该项目打包成了一个 jar 文件,如图 2 所示。

  1. 在 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 所示。