Maven学习

仓库

本地仓库:

maven项目实际目录下,是不存放依赖文件的,当编译或者测试需要用到依赖文件时,maven基于仓库坐标会去对应的仓库查找依赖项,首先在本地仓库中找,然后下载到本地仓库再使用,若本地仓库与远程仓库均没有,报错。构件只有在本地仓库,才能被maven项目使用,构件如何进入本地仓库:远程仓库下载,本地项目mvn install。

远程仓库:

本地仓库只有一个,远程仓库可以有多个:中央仓库、私服、其他公共库

中央仓库:是maven自带的默认远程仓库,里面包含了绝大多数流行开源Java构件,这就是maven可以开箱即用的原因。

私服:架设在局域网的远程仓库,maven需要下载构件时,请求私服,私服有就返回,没有,则从外部远程仓库下载,缓存到私服,然后返回给maven用户。 

其他公共库:如java.net maven库

maven的一些约定在超级pom中,超级pom的位置是:/lib/maven-model-builder-xxx.jar中的org/apache/maven/model/pom-4.0.0.xml,超级pom是任何项目都会继承的pom,里面包含了中央仓库地址,插件仓库地址,项目的一些约定等。

代码块

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xmlns="http://maven.apache.org/POM/4.0.0"

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <!--组织标识,定义了项目属于哪个组-->

    <groupId>com.xuexi</groupId>

    <!-- 项目名称,定义当面Maven项目在组中唯一的ID-->

    <artifactId>honour</artifactId>

    <!-- 项目当前的版本号-->

    <version>1.0.0-SNAPSHOT</version>

    <!-- POM模型版本-->

    <modelVersion>4.0.0</modelVersion>

    <!-- 打包的格式,可以为:pom , jar , maven-plugin , ejb , war , ear , rar , par -->

    <packaging>war</packaging>

   

    <properties>

    <!-- 为pom定义一些常量,在pom中的其它地方可以直接引用-->

    </properties>



    <dependencyManagement>

    <!-- 对所依赖jar包进行版本管理的管理器-->

    </dependencyManagement>



<dependencies>

    <!-- 对所依赖jar包进行版本管理的管理器-->

    </dependencies>

   

  <!--工程源码目录结构&输出目录--!>

    <build>

    <plugins>

给出构建过程中所用到的插件。

    <!-- -->

    </build>



    <profiles>

    <!-- -->

    </profiles> 

  </project>

 

dependencies>dependencyManagement

在dependencyManagement下申明的dependencies,Maven并不会去实际下载所依赖的jar包,而是在dependencyManagement中用一个Map记录了jar的三维坐标。

而仅仅是被dependencies包裹的元素,Maven是会去仓库实际下载所需要的jar包的,而至于需要下载什么

版本的jar包就有两种判断途径:

1:如果dependencies里的dependency自己没有声明version元素,那么maven就会倒dependencyManagement里面去找有没有进行过版本声明,如果有,就继承它,如果没有就会报错,告诉你必须为dependency声明一个version

2:如果dependencies中的dependency声明了version,那么无论dependencyManagement中有无对该jar的version声明,都以dependency里的version为准。

dependencies与dependencyManagement的依赖继承

  1. dependencies即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)。dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。

如果不在子项目中声明依赖,是不会从父项目中继承下来的;

  1.  
  2. 只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;
  3. 如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

 

常用命令汇总

命令

 

说明

 

mvn archetype:generate -DgroupId=packageName -DartifactId=projectName  -Dversion=x.x-SNAPSHOT

创建Maven项目

 

mvn compile

 

编译源代码

 

mvn test-compile

 

编译测试代码

 

mvn test 

 

运行测试

 

mvn package

 

打包

 

mvn -Dtest package

clean install -Dmaven.test.skip=true

 

打包但不测试

 

mvn install

 

在本地库repository中安装该项目的jar包

 

mvn clean

 

清除产生的项目

 

mvn eclipse:eclipse

生成eclipse项目

 

mvn idea:idea

生成idea项目

 

 

scope 标签

Dependency scope 是用来限制 Dependency 的作用范围的, 影响maven项目在各个生命周期时导入的package的状态。

编号

 

参数

 

说明

 

编号

 

参数

 

说明

 

1

 

compile

默认的scope,表示 dependency 可以在所有生命周期中使用。而且这些 dependencies 会传递到依赖的项目中。适用于所有阶段,会随着项目一起发布(会将依赖的项目打成jar包,放入本项目的Lib里

 

2

 

provided

表明了dependency 由JDK或者容器提供。期望JDK、容器或使用者会提供这个依赖。如servlet.jar。这个scope 只能作用在编译和测试时(编译需要而发布不需要),同时没有传递性(不会将包打入本项目中,只是依赖过来

 

3

 

runtime

表示dependency不作用在编译时,但会作用在运行和测试时,如JDBC驱动,适用运行和测试阶段。

比如在测试别的功能的阶段,还没有编写mysql,所以编译的时候不会用到这个包。即使加了这个依赖,但是由于编译的时候没有用到,那么生成的target下的lib中是没有对应的jar包的。所以标记runtime

 

4

 

test

表示dependency作用在测试时,不作用在运行时。 只在测试时使用,用于编译和运行测试代码。不会随项目发布。

 

5

 

system

跟provided 相似,但是在系统中要以外部JAR包的形式提供,maven不会在repository查找它。

 

6

 

import

只使用在 <dependencyManagement> 中,表示从其它的 pom 中导入 dependency 的配置

 

 

一、基本原则

1、依赖路径最短优先原则

一个项目Demo依赖了两个jar包,其中A-B-C-X(1.0) , A-D-X(2.0)。由于X(2.0)路径最短,所以项目使用的是X(2.0)。

2、pom文件中申明顺序优先

如果A-B-X(1.0) ,A-C-X(2.0) 这样的路径长度一样怎么办呢?这样的情况下,maven会根据pom文件声明的顺序加载,如果先声明了B,后声明了C,那就最后的依赖就会是X(1.0)。

3、同一个pom明确版本

如果在A工程中先依赖了junit4.9的版本, 然后下面又在依赖了junit4.8 的版本, 那么,按照就近原则,越下面越近, 最后使用的是junit4.8 的版本.

总结: maven的依赖如果发生了冲突, 服从就近原则.

4、优先级

本pom版本(覆写优先)> 父pom版本 > dependencyManagement版本 > 间接依赖版本(申明优先)

可选依赖

假如项目 A 存在这样的依赖关系,A->B、B->X(可选)、B->Y(可选optional:标记依赖是否可选),依赖将不会得以传递,即 X、Y 将不会对 A 有任何影响。

在理想的情况下,是不应该使用可选依赖的。使用可选依赖的原因是某一个项目实现了多个特性,但违背了单一指责原则。

备注:调用方的jar版本必须大于服务方要求的jar版本,否则可能会报出java.lang.NoSuchMethodError

 

二、依赖复用:消除多模块依赖配置重复

1、继承

POM中配置了继承,当前模块与父模块使用同样的groupId和version时,就可以将<groupId>和<version>元素删除,因为它们可以从父模块继承而来,重复配置没有什么意义。

<parent>

<groupId>com.example</groupId>

<artifactId>fun-parent</artifactId>

<version>1.0.6</version>

</parent>

 

2、dependencyManagement

问题:在父模块中配置dependencies,那样所有子模块都自动继承,但这么做是有问题的,例如你将模块C的依赖spring-aop提取到了父模块中,但模块A和B虽然不需要spring-aop,但也直接继承了。

dependencyManagement就没有这样的问题,dependencyManagement只会影响现有依赖的配置,但不会引入依赖

这样不会给任何子模块引入依赖,但如果某个子模块需要使用JUnit和Log4j的时候,我们就可以简化依赖配置。

3、特殊情况

在配置项目依赖的时候,我们也应当一直显式地写明依赖版本,以避免Maven在不同的时刻引入不同版本的依赖而导致项目构建的不稳定。

 

三、增还是删

有时候这个答案是很显然的,当你的POM中存在一些依赖或者插件配置,但实际代码没有用到这些配置的时候,应该尽早删掉它们以免给人带来困惑。

第二个不常用的方法就是创建一个空包。空包的坐标和你需要隔离的Jar包坐标一样,deploy的公司的私服上面。项目中这个空包申明在pom文件靠前的地方,这样依据maven依赖原则,这个空包会优先被使用,后面所有无论是直接依赖还是间接依赖的相同坐标的jar包都不会被使用了。空包比exclusion的好处就是不用在所有间接依赖的地方去exclusion。

<exclusions>

<exclusion>

<groupId>com.ibm.icu</groupId>

<artifactId>icu4j</artifactId>

</exclusion>

</exclusions>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值