什么是Maven?
翻译为专家,内行。Maven是跨平台的项目管理工具。主要服务于基于Java平台的项目构建,项目管理和项目信息管理。那么怎么样才算是理想的项目构建呢?理想的项目构建就是必须具备高度自动化,跨平台,可重用的组件,标准化这些特性。
什么是依赖?为什么要进行依赖管理?
- 所谓的依赖就是自动下载。进行依赖管理主要是为了统一的对这些依赖进行管理。
都有哪些项目信息?
-项目名称描述,开发者信息,开发人员信息,项目的版本号等等。
什么项目构建?
- 所谓的项目构建就是对项目进行清理、编译、测试、报告、打包、部署等一系列的过程称为项目的构建如下图所示:
Maven模型
如下图所示:
它将每一个项目都当成了一个对象POM,通过依赖管理Dependency从仓库中进行存取。通过插件对Maven的生命周期进行管理,生命周期的每一个阶段都由相应的插件进行支持。由不同的命令激活不同的插件进行工作。
Maven的主要内容主要包括以下几个部分:
- 为什么要使用Maven
- Maven的安装与配置
- 第一个Maven相关概念
- Maven与Eclispe整合-Nexus
- 部署构建至Nexus
为什么使用Maven?
项目构建的工具有很多 IDE、Eclipse、Ant、Maven
不使用IDE和Eclipse构建项目的原因?
- 手工操作较多,编译、测试、部署等工作都是独立的,很难一步完成。
- 每个人的IDE配置都不同,很容易出现本地代码换个地方编译就出错。
不使用Ant的原因?
- 没有一个约定的目录结构
- 必须明确让Ant做什么,什么时候做然后编译,打包。
- 没有生命周期,必须定义目标及其实现的任务序列。
- 没有集成依赖管理。
使用Maven的原因?
- 拥有约定的目录结构,知道你的代码在哪里,放到哪。
- 拥有一个生命周期,例如执行mvn install 就可以自动执行编译,测试,打包等构建过程。
- 只需要定义一个pom.xml,然后将源码放到默认的目录,Maven帮你自动处理其他事情。
- 拥有依赖管理,仓库管理。
Maven的安装
(一) Windows系统安装Maven:
1、检查JDK安装的情况(需要1.6以上)
echo %JAVA_HOME%
java -version
2、对apache-maven-3.0.3-bin.zip进行解压,例如解压到如下目录(解压目录路径中最好不要包含中文)
3.设置系统环境变量,MAVEN_HOME
4、设置环境变量Path,将%MAVEN_HOME%\bin加入Path中,一定要注意使用分号 ; 与其他值隔开。
5、验证安装是否成功,打开cmd窗口,输入mvn -v进行查看
(二) Mac系统安装Maven的方式
1、打开终端,查看JDK的安装情况,查看JDK版本
liuliuxundeMacBook-Pro:~ liuxun$ echo $JAVA_HOME /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home liuliuxundeMacBook-Pro:~ liuxun$ java -version java version "1.8.0_102" Java(TM) SE Runtime Environment (build 1.8.0_102-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
2、将maven包解压到用户目录下 如下图所示
3、配置变量 MAVEN_HOME以及Path变量
使用vi编辑器编辑 ~/.bash_profile 文件,即vi ~/,bash_profile配置如下:
然后 输入 :wq 保存并退出。
4、重启终端 输入 mvn -v
需要注意的是:Mac 查看变量 需要在变量前加$号。另外设置Path的时候 多个变量间使用:分开。
Maven的配置
Maven安装目录分析
bin:含有mvn运行的脚本。
boot:含有plexus-classworlds类加载器框架。
conf:含有setting.xml配置文件
lib: 含有Maven运行时所需要的Java类库。
LISTENSE.txt,NOTICE.txt,README.txt针对Maven的版本,第三方软件等简要介绍。
初始化配置:
设置MAVEN_HOME环境变量: 已设置, 升级时只需要下载最新版本,解压后重新设置MAVEN_HOME环境变量即可。
设置MAVEN_OPTS环境变量:-Xms128m -Xmx512m 设置Maven仓库占用的空间大小。
配置用户范围的settings.xml:
MAVEN_HOME/conf/settings.xml全局的配置文件
~/.m2/settings.xml: 与默认仓库对应的配置文件。
默认仓库: 当前用户C:\users\[username]\.m2\repository
一般可以自定义用户的仓库 而不再使用默认仓库 配置方法 在
MAVEN_HOME/conf/settings.xml配置中设置路径执行仓库目录
<localRepository>/Users/liuxun/maven_repository/repository</localRepository>
然后将此全局的配置文件保存,并复制到自己仓库的同级目录
本地仓库同级目录的settings.xml文件的内容必须和全局的settings.xml配置文件完全一致。
注意:
用户级别的仓库在全局配置中一旦设置,全局配置将不再生效 专用用户设置的仓库,否则使用默认路径仓库。
遵守Maven的约定
src/main/java ——存放项目的.java文件
src/main/resources ——存放项目的资源文件,如spring,hibernate配置文件
src/test/java —— 存放所有测试的.java文件,例如Junit测试类
src/test/resources —— 测试的资源文件
target —— 项目的输出位置
pom.xml —— maven项目核心配置文件
Maven的简单入门
第一个简单示例:
第一步:首先建立MavenHelloWorld项目同时建立Maven约定的目录结构。
MavenHelloWorld
第二步:在/src/main/java/my/test/maven目录下新建文件HelloWorld.java
package my.test.maven; public class HelloWorld { public String sayHello(String name){ return "Hello World :" + name + "!"; } }
第三步:在/src/test/java/my/test/maven目录下新建测试文件HellTest.java
package my.test.maven; import org.junit.Test; import static junit.framework.Assert.*; public class HelloTest { @Test public void testHello(){ HelloWorld hello = new HelloWorld(); String results = hello.sayHello("maven"); assertEquals("Hello maven!",results); } }
第四步:在项目MavenHelloWorld 根目录新建pom.xml
<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"> <!-- 版本:4.0.0 --> <modelVersion>4.0.0</modelVersion> <!-- 组织名称:暂时使用 组织名称+项目名称 作为组织名称 --> <!-- 组织名称:实际名称 按照访问路径规范设置,通常以功能作为名称:eg: junit spring --> <groupId>my.test.maven</groupId> <!-- 项目名称 --> <artifactId>HelloWorld</artifactId> <!-- 当前项目版本号:同一个项目开发过程中可以发布多个版本,此处标示0.0.1版 --> <!-- 当前项目版本号:每个工程发布后可以发布多个版本,依赖时调取不同的版本,使用不同的版本号 --> <version>0.0.1</version> <!-- 名称:可省略 --> <name>Hello</name> <!-- 依赖关系 --> <dependencies> <!-- 依赖设置 --> <dependency> <!-- 依赖组织名称 --> <groupId>junit</groupId> <!-- 依赖项目名称 --> <artifactId>junit</artifactId> <!-- 依赖版本名称 --> <version>4.9</version> <!-- 依赖范围:test包下依赖该设置 --> <scope>test</scope> </dependency> </dependencies> </project>
第五步:
a) 打开cmd或Mac终端命令行,进入Hello项目根目录(包含pom.xml的目录)
b) 执行mvn compile命令
执行完毕后,生成了maven工程编译完成后字节码文件的生成目录target
c) 在终端中继续输入mvn clean命令
执行完毕后,字节码生成目录被删除
d) 在cmd或终端输入mvn test命令
执行完毕后,字节码生成目录中生成了被测试类与测试类的编译字节码和测试执行过程日志与详细报告。
e) cmd或终端中输入mvn clean compile命令
组合指令,先执行clean,再执行compile,通常应用于上线前执行,清除测试类
f) cmd或终端输入mvn clean test
组合指令,先执行clean,再执行test,通常用于测试环节
g) cmd或终端输入mvn clean package命令
组合指令,先执行clean,再执行package,将项目打包,通常应用于发布前。
执行过程:
清理——清理环境
编译——编译源码
测试——测试源码
打包——将编译的非测试类打包
h) cmd或终端输mvn clean install 查看仓库,当前项目被发布到仓库中
组合指令,先执行clean,再执行install,将项目打包,通常应用于发布前。
执行过程:
清理——清空环境
编译——编译源码
测试——测试源码
打包——将编译的非测试类打包
部署——将打好的包发布到资源仓库中
第二个简单示例
第六步:新建第二个项目模块HelloFriend目录以及约定的目录结构。
第七步:在项目HelloFriend根目录创建pom.xml
<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>my.test.maven</groupId> <artifactId>HelloFriend</artifactId> <version>0.0.1-SNAPSHOT</version> <name>HelloFriend</name> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> <dependency> <groupId>my.test.maven</groupId> <artifactId>HelloWorld</artifactId> <version>0.0.1</version> <scope>compile</scope> </dependency> </dependencies> </project>
第八步:在src/main/java/my/test/maven目录下新建文件HelloFriend.java
package my.test.maven; import my.test.maven.HelloWorld; public class HelloFriend { public String sayHelloToFriend(String name){ HelloWorld hw = new HelloWorld(); String str = hw.sayHello(name)+" I am "+this.getMyName(); System.out.println(str); return str; } public String getMyName(){ return "MAVEN"; } }
第九步:在src/test/java/my/test/maven目录下新建测试文件HelloFriendTest.java
package my.test.maven; import static junit.framework.Assert.assertEquals; import org.junit.Test; import my.test.maven.Hello; public class HelloFriendTest { @Test public void tesHelloFriend(){ HelloFriend helloFriend = new HelloFriend(); String results = helloFriend.sayHelloToFriend("Jock"); assertEquals("Hello World Jock! I am MAVEN",results); } }
第十步:在HelloFriend目录下执行命令mvn package 系统报错说没有找到依赖
第十一步:需要重新构建HelloWorld第一个项目并安装到数据仓库,在命令行HelloWorld根目录下执行mvn clean install
第十二步:重新再HelloFriend目录下执行命令mvn package
运行成功
MyEclipse上Maven的配置 打开偏好设置 搜索Maven 配置如下
Maven的核心概念
坐标、依赖管理、仓库管理、生命周期、插件和目标、聚合继承
什么是坐标?
- 在平面几何中坐标可以标识平面中唯一的点。
Maven坐标主要组成
- groupId:定义当前Maven项目隶属项目。
- artifactId:定义实际项目中的一个模块。
- version:定义当前项目的当前版本。
- packaging:定义该项目的打包方式 默认是jar 还可以设置为war、pom、maven-plugin等
Maven为什么使用坐标?
- Maven世界拥有大量构建,我们需要找一个用来唯一标识一个构建的统一规范。
- 拥有了统一规范,就可以将查找工作交给机器。
依赖管理—依赖范围
依赖声明主要包含如下元素
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies>
其中依赖范围scope 用来控制依赖和编译,测试,运行的classpath的关系,主要的是三种依赖关系如下:
1.compile:默认编译依赖范围。对于编译,测试,运行三种classpath都有效
2.test:测试依赖范围。只对测试classpath有效
3.provided:已提供的依赖范围。对于编译,测试的classpath都有效,但对于运行无效。因为已经由容器提供。例如:servlet-api
4.runtime:运行时提供。例如:jdbc驱动
如何进行依赖配置?
传递性依赖和可选依赖,排除依赖。
依赖管理—传递依赖
Two中使用One,Three中使用Two,称Two是Three的直接依赖,称One是Three的间接依赖。
C—>B B—>A 称C直接依赖B,称C间接依赖A
依赖管理—依赖范围对传递依赖的影响
列是第一直接依赖,行是第二直接依赖
A—>B:第一直接依赖
B—>C:第二直接依赖
A—>C:间接依赖的依赖范围受到第一直接依赖和第二直接依赖的影响。如上图所示。
依赖管理—可选依赖
<optional> true/false 如果为true表示为可选依赖 不会被传递,默认是false是向下传递的。例如A—>B B—>C 如果在B中配置自身的依赖包C为可选依赖,那么C不会被传递到A中。A中就看不到C的依赖包 也不能使用C的内容。实际上可选依赖就是设置自己所依赖的某个包 是否可以向下传递。是在<dependency>标签对中进行设置
依赖管理—排除依赖
方式是 在<dependency>具体某个依赖标签对中设置<exclusions>表示所要排除的多个间接依赖 在<exclusions>中的<exclusion>标签对中设置坐标表示具体所要排除的依赖。这种方式的排除其实是在自己的pom文件中将直接依赖传递过来的某些不需要的间接依赖给排除掉(只有在直接依赖所对应的pom文件中没有设置可选依赖即可选依赖为false的情况下才有可能设置排除,因为只有间接依赖被传递过来
才有可能进行排除)
注意:排除依赖不需要所包含的间接依赖只需要添加坐标 直接进行类别排除,不需要添加版本号。
依赖管理—依赖冲突
如果直接与间接依赖中包含同一坐标不同版本的资源依赖,以直接依赖的版本为准(就近原则)
如果直接依赖中包含同一个坐标不同版本的资源依赖,以配置顺序下方的版本为准,即以最后配置的为准。
生命周期
何为生命周期?
- Maven生命周期就是为了对所有的构建过程进行抽象和统一,包括项目清理、初始化、编译、打包、测试,部署等几乎所有的构建步骤。
Maven的三大生命周期:
- clean:清理项目的
- default:构建项目的
- site:生成项目站点的
生命周期概述:
- 生命周期Maven有三套相互独立的生命周期,注意:是三套,而且相互独立,这三套生命周期分别是:
- Clean Lifecycle:在进行真正的构建之前进行一些清理工作。
- Default Lifecycle:构建的核心部分,编译、测试、打包、部署等等。
- Site Lifecycle:生成项目报告,站点,发布站点。
- 切记:它们是相互独立的,仅仅调用clean来清理工作目录,仅仅调用site来生成站点。当然可以组合使用直接运行mvn clean install site 运行所有这三套生命周期。
生命周期clean:
- clean生命周期每套生命周期都由一组阶段(phase)组成,我们平时在命令行输入的命令总会对应一个特定的阶段。比如,运行mvn clean,这个的clean是Clean生命周期的一个阶段。有Clean的生命周期,也有clean阶段,Clean生命周期一共包含三个阶段:
- pre-celan:执行一些需要在clean之前完成的工作。
- clean:移除上一次构建生成的文件。
- post-clean:执行一些需要在clean之后立刻完成的工作。
- mvn clean中的clean就是Clean生命周期中的一个阶段,在一个生命周期中,运行某个阶段的时候,它之前的所有阶段都会被执行,也就是说,mvn clean等同于mvn pre-clean clean,如果我们运行mvn post-clean 那么pre-clean和clean都会被执行。这是Maven的一个规则,可以大大简化命令行的输入。
生命周期default
- Default生命周期Default生命周期是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 将最终的包复制到远程的仓库,以让其它开发人员与项目共享。
- 运行任何一个阶段的时候,它前面的所有阶段都会被运行,这也就是为什么我们运行mvn install 的时候,代码会被编译,测试,打包。此外,Maven的插件机制是完全依赖
- Maven的生命周期的,因此理解生命周期至关重要。
生命周期site:
- Site生命周期pre-site 执行一些需要在生成站点文档之前完成的工作
- site 生成项目的站点文档
- post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy 将生成的站点文档部署到特定的服务器上
- 这里经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,Manager比较喜欢,文档及统计数据自动生成,很好看。
插件目标
- Maven的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
- 每个插件都能实现多个功能,每个功能就是一个插件目标。
- Maven的生命周期与插件目标相互绑定,以完成某个具体的构建任务。
- 例如compile就是插件maven-compiler-plugin的一个插件完成的
POM中插件配置方式示例如下:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>2.2.1</version> <executions> <execution> <goals> <goal>jar-no-fork</goal> </goals> <phase>verify</phase> </execution> </executions> </plugin> </plugins> </build>
继承:
继承为了消除重复,我们把很多相同的配置提取出来
例如:grouptId,version等
父工程设置为被继承
<packaging>pom</packaging>
子工程继承父工程
省略父工程中定义的坐标除访问名称中的所有设定,添加继承父工程
<parent>
<groupId>…</groupId>
<artifactId>… </artifactId>
<version>… </version>
<relativePath>../父工程项目名</relativePath>
</parent>
父工程统一管理子工程依赖版本
<dependencyManagement>
<dependencies>
//添加公共依赖包
</dependencies>
</dependencyManagement>
子工程仅仅添加依赖包,无需添加版本,版本由父工程继承而来
为了进一步便于管理,将所有的版本管理设置在一起,设置为系统属性值
<properties>
<junit.version>4.9</junit.version>
……
</properties>
引用使用${junit.version}格式进行,只能在依赖范围设置
父工程统一管理子工程依赖关系
如果所有子工程都需要依赖某些包,父工程可以通过设置依赖,将依赖关系传递到子工程中
<dependencies>
//添加公共依赖包
</dependencies>
父工程统一管理子工程依赖关系
如果所有子工程都需要依赖某些包,父工程可以通过设置依赖,将依赖关系传递到子工程中
<dependencies>
//添加公共依赖包
</dependencies>
需要注意的是:<dependencyManagement>只是管理子工程依赖包的版本 依赖关系是不会传递到子工程的,只是子工程在添加对应依赖时不用写对应依赖的版本号了 由父工程统一定义管理。 而<dependencies>是公共依赖,会传递到子工程中,子工程中不用再添加对应的公共依赖。
聚合
何为聚合?
如果我们想一次构建多个项目模块,那我们就需要对多个项目模块进行聚合,一般在父工程的pom文件中进行配置。
<modules>
<module>../子项目名称1</module>
<module>../子项目名称2</module>
<module>../子项目名称3</module>
</modules>
继承与聚合的关系
聚合主要为了快速构建项目
继承主要为了消除重复
仓库管理
何为Maven仓库?
用来统一存储所有Maven共享构建的位置就是仓库
Maven仓库布局
根据Maven坐标定义每个构建在仓库中唯一存储路径
大致为:groupId/artifactId/version/artifactId-version.packaging
仓库的分类
本地仓库
~/.m2/repository/
每个用户只有一个本地仓库
远程仓库
中央仓库:Maven默认的远程仓库,不包含版权资源
http://repo1.maven.org/maven2
私服:是一种特殊的远程仓库,它是架设在局域网内的仓库
项目演示各种依赖关系
新建四个项目One Two WThree ZParent 其中Two中依赖One WThree中依赖Two 都继承自ZParent
项目One中
One.java
package liuxun.maven.One; public class One { public String say(String name){ return "Hello "+name+" one"; } }
OneTest.java
package liuxun.maven.One; import org.junit.Test; import junit.framework.Assert; public class OneTest { @Test public void testSay(){ One one = new One(); String result = one.say("liuxun"); Assert.assertEquals("Hello liuxun one", result); } }
One/pom.xml
<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> <!-- 群组ID:单位域名反写 --> <!-- <groupId>liuxun.maven</groupId> --> <!-- 项目ID:一个单位只有一个域名,但是一个单位可以做多个项目 也可以理解为组件 --> <artifactId>One</artifactId> <!-- 版本号:用于描述开发过程的阶段性标志 --> <!-- <version>0.0.1-SNAPSHOT</version> --> <!-- 如果打包默认是jar文件 可以设置为ejb ear war jar maven-plugin等 --> <packaging>jar</packaging> <!-- 继承 --> <parent> <groupId>liuxun.maven</groupId> <artifactId>ZParent</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 如果想不进行install父工程 能进行找到的话 必须设置相对路径 --> <relativePath>../ZParent</relativePath> </parent> <!-- 显示的名称 可以省略不写 --> <name>One</name> <!-- 也可以省略不写 --> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <!-- 依赖管理 --> <dependencies> <!-- 具体的依赖 --> <!-- 可以将通用的依赖添加到父工程中 --> <!-- <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> --> <!-- <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> --> <!-- 如果配置了直接依赖的多个版本 1?以最下面 最后一次的配置为准 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> </dependencies> <build> <plugins> <!-- 声明具体的插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>2.2.1</version> <!-- 声明插件的执行位置 --> <executions> <!-- 具体的执行位置 --> <execution> <goals> <goal>jar-no-fork</goal> </goals> <!-- 生命周期中的某个阶段 --> <phase>test</phase> </execution> </executions> </plugin> </plugins> </build> </project>
Two项目中
Two.java
package liuxun.maven.Two; import liuxun.maven.One.One; public class Two { public String say(String name){ One one = new One(); String result = one.say(name); return result+" two"; } }
TwoTest.java
package liuxun.maven.Two; import org.junit.Test; import junit.framework.Assert; public class TwoTest { @Test public void testSay(){ Two two = new Two(); String res = two.say("liuxun"); Assert.assertEquals("Hello liuxun one two", res); } }
Two/pom.xml
<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> <artifactId>Two</artifactId> <packaging>jar</packaging> <!-- 继承 --> <parent> <groupId>liuxun.maven</groupId> <artifactId>ZParent</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 如果想不进行install父工程 能进行找到的话 必须设置相对路径 --> <relativePath>../ZParent</relativePath> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> <!-- 直接依赖会覆盖传递过来的依赖 再往下传递时以生效的依赖向下传递--> <!-- 传递到WThree时 log4j的版本为1.2.16 --> <!-- <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> --> <dependency> <groupId>liuxun.maven</groupId> <artifactId>One</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 设置自己的依赖是否向下传递 --> <!-- <optional>true</optional> --> </dependency> </dependencies> </project>
项目WThree中
Three.java
package liuxun.maven.WThree; import liuxun.maven.Two.Two; public class Three { public String say(String name){ Two two = new Two(); String result = two.say(name); return result+" three"; } }
ThreeTest.java
package liuxun.maven.WThree; import org.junit.Test; import junit.framework.Assert; public class ThreeTest { @Test public void testSay(){ Three three = new Three(); String result = three.say("liuxun"); Assert.assertEquals("Hello liuxun one two three", result); } }
WThree/pom.xml
<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>liuxun.maven</groupId> <artifactId>WThree</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>WThree</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> <dependency> <groupId>liuxun.maven</groupId> <artifactId>Two</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> <!-- 设置排除 --> <!-- 排除依赖必须基于直接依赖中的间接依赖设置可选依赖为false --> <!-- 因为只有直接依赖中设置可选依赖向下传递,才有可能进行排除 --> <!-- 设置当前依赖中是否使用间接依赖 --> <!-- <exclusions> 具体排除 <exclusion> <groupId>liuxun.maven</groupId> <artifactId>One</artifactId> </exclusion> </exclusions> --> </dependency> </dependencies> </project>
父项目ZParent中
ZParent/pom.xml
<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>liuxun.maven</groupId> <artifactId>ZParent</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 必须设置为pom 声明此为父工程 专门做配置的 --> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <abc>1.2.17</abc> <junit.version>4.9</junit.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${abc}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> </dependencies> <modules> <module>../One</module> <module>../Two</module> <module>../WThree</module> </modules> </project>
右键父工程中的pom.xml Run As——>Maven build .. 添加参数 clean test 运行结果如下
Maven私服
在一个项目中有很多人开发,项目所依赖的包大致一样,可以建立一台私服专门从Maven远程仓库进行读取。所有的开发人员都可以从私服中进行下载了。
私服的安装与配置
第一步:下载nexus-2.9.0.war 然后拷贝到Tomcat下的webapps
第二步:启动Tomcat
第三步:访问http://localhost:8080/nexus-2.9.0/ 显示如下
第四步:点击右上角的login 输入username: admin 和password:admin123 登录
第五步:登录成功
第六步:点击左侧Views/Repositories中的Repositories
Nexus内置仓库说明
(1) Maven Central:该仓库代理Maven中央仓库,其策略为Release,因此只会下载和缓存中央仓库中的发布版本构件
(2) Releases:这是一种策略为Release的宿主类型仓库,用来部署组织内部的发布版本构件。
(3) Snapshots:这是一个策略为Snapshots的宿主类型仓库,用来部署组织内部的快照版本构件。
(4)3rd party:这是一个策略为Release的宿主类型仓库,用来部署无法从公共仓库获得的第三方发布版本构件。
(5)Public Repositories:该仓库组将上述所有策略为Release的仓库聚合并通过一致的地址提供服务。
第七步:创建宿主目录和代理仓库
Hosted:本地仓库,通常我们会部署自己的构件到这一类型的仓库。
包括3rd party仓库,Releases仓库,Snapshots仓库
Proxy:代理仓库,它们被用来代理远程的公共仓库,如maven中央仓库。
Group:仓库组,用来合并多个hosted/proxy仓库,通常我们配置maven依赖仓库组。
第八步:创建仓库组
点击Public Repositories仓库,在Configurations栏中选取需要合并的仓库,点击箭头加到左边保存即可
第九步:下载index索引并进行构建搜索(GAV搜索)
配置索引位置(根据自己的用户名进行查找) 在如下目录进行覆盖
/Users/liuxun/sonatype-work/nexus/indexer
配置好以后 重启服务器 刷新页面如下
第十步:配置所有构建均从私服下载
编辑 MANEN_HOME/conf/setting.xml
10.1找到<mirrors>标签在内部配置 私服策略
<mirrors> <mirror> <!--此处配置所有的构建均从私有仓库中下载 *代表所有,也可以写central --> <id>nexus</id> <mirrorOf>*</mirrorOf> <url>http://localhost:8080/nexus-2.9.0/content/groups/public/</url> </mirror> </mirrors>
这个url其实是公共群组的策略
可以在nexus服务器上找到 如下图
10.2在setting.xml中找到<profiles>标签 进行配置
<profiles> <profile> <id>nexus</id> <!--所有请求均通过镜像 --> <repositories> <repository> <id>central</id> <!-- 这个网址根本没有实际作用 因为上面已经配置所有下载的地址 但是不能删除 不然会报节点错误 --> <url>http://central</url> <releases><enabled>true</enabled></releases> <snapshots><enabled>true</enabled></snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>central</id> <!-- 这个网址根本没有实际作用 因为上面已经配置所有下载的地址 但是不能删除 不然会报节点错误 --> <url>http://central</url> <releases><enabled>true</enabled></releases> <snapshots><enabled>true</enabled></snapshots> </pluginRepository> </pluginRepositories> </profile> </profiles>
10.3 配置nexus发布版本的权限在setting.xml中找到<servers> 配置如下
<!-- 设置发布时的用户名和密码 --> <server> <id> releases </id> <username>admin</username> <password>admin123</password> </server> <server> <id> snapshots </id> <username>admin</username> <password>admin123</password> </server>
注意:在发布项目时 配置的发布id要和上面的一致
10.4启用nexus私服策略 在setting.xml中找到<activeProfiles>标签进行配置
<activeProfiles> <!-- 启用nexus私服策略 --> <activeProfile>nexus</activeProfile> </activeProfiles>
然后保存 复制一份将与本地仓库同级目录下的setting.xml替换 保持一致
最后需要在项目的pom.xml中进行配置 部署构建到nexus,包含release和snapshot。
就拿上面的项目为例 在ZParent/pom.xml中添加如下配置(一般都是在父工程的pom文件中添加发布配置):
<distributionManagement> <repository> <id>releases</id> <name>Internal Releases</name> <url>http://localhost:8080/nexus-2.9.0/content/repositories/releases/</url> </repository> <snapshotRepository> <id>snapshots</id> <name>Internal Snapshots</name> <url>http://localhost:8080/nexus-2.9.0/content/repositories/snapshots/</url> </snapshotRepository> </distributionManagement>
其中两个url分别也是从私服的主页上拷贝的 发布的时候 就会发布到releases和snapshots中
重启服务器
然后分别运行ZParent One Two 使用命令 clean deploy
后观察
OK 执行完毕
可以在私服上的找到 /Users/liuxun/sonatype-work/nexus/storage/snapshots/liuxun/maven/One
在实际开发中,一般都由项目经理将setting.xml发给我们,我们只需要修改里面的本地仓库路径 即可 然后分别覆盖全局与本地仓库的setting.xml