身边有几位刚使用Maven的同窗表示——在一个叫"pom.xml"的文件里声明一个依赖就不用去手动添加jar了,感受这东西和本身手动管理依赖没太大区别。
固然,并非这样,在此记录dependency那些事儿。html
一个依赖能够按照maven的坐标标准进行定义。
好比:java
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
上面是最多见的坐标属性,偶尔也会看到有classifier
。
下面简单说明一下标签:git
引入Junit依赖时一般须要声明test scope:github
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
大概能猜出是测试时使用该依赖,但不彻底正确。
Maven编译代码时须要使用classpath,但classpath不止一种,而是:web
Maven会根据须要使用不一样的classpath,而scope能够用来控制依赖与这三种classpath之间的关系。 spring
一般会使用前三种。
scope不只用来控制依赖与classpath之间的关系,还会对依赖的传递性产生影响。
传递性依赖? 好比A依赖B,B依赖C,则A对于B是直接依赖,对于C是传递性依赖。
A对B、B对C的依赖范围决定了A对C的依赖范围。
如何决定? 下面给出一个关系表,垂直表示第一依赖,水平表示第二依赖,交叉单元格为传递性依赖。apache
compile | test | provided | runtime | |
compile | compile | runtime | ||
test | test | test | ||
provided | provided | provided | provided | |
runtime | runtime | runtime |
考虑一下这样的依赖关系,A-> C -> D(1.0)和A-> B -> D(2.0)
此时应该如何处理? 引入两种D依赖是不可能的。
Maven有依赖调节原则:api
对于上面的例子,A-> C -> D(1.0)和A-> B -> D(2.0)的路径长度相同,但前者声明早于后者,所以加入的传递性依赖则是D(1.0)。安全
另外,还须要考虑这样一个场景。
A依赖B、B依赖X和Y,X和Y都是可选依赖,即<optional>true</optional>
,且4个都是compile。
此时,X和Y则不会被传递,对A是不可见的。mvc
但依赖调节并不解决全部问题,咱们还须要exclusions来进行排除依赖。
例如这样一个状况,工程中引入了A,A依赖B,可是B的版本过旧。
此时可使用exclusions排除该传递性依赖,并显示声明一个最新版本的B依赖。
好比这样:
<dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>4.2.1</version> <exclusions> <exclusion> <artifactId>bcmail-jdk14</artifactId> <groupId>bouncycastle</groupId> </exclusion> <exclusion> <artifactId>bcprov-jdk14</artifactId> <groupId>bouncycastle</groupId> </exclusion> <exclusion> <artifactId>bctsp-jdk14</artifactId> <groupId>bouncycastle</groupId> </exclusion> </exclusions> </dependency>
用于统一管理属性,好比咱们引入不少spring framework:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.0.3 RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.3 RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>4.0.3 RELEASE</version> </dependency>
可见版本都是同样的,想更改版本时再一个一个修改太麻烦。
properties能够解决这一问题:
<properties> <spring.version>4.0.3.RELEASE</spring.version> </properties>
引入spring能够改成:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency>
这样确实简介了很多,但你可能仍然讨厌XML。
兴许,之后咱们不会再用XML写构建文件。
咱们可能会用一些插件(好比Polyglot for Maven)或者其余的什么东西(好比Gradle)。
能够把Maven的仓库分为两种:
Maven寻找一个dependency时会先从本地仓库查找,若是找不到则在远程仓库查找,发现则下载到本地仓库使用。
若是都查找失败,会提示build failure。
或者,咱们也能够把本地的jar放到本地仓库中:
mvn install:install-file -Dfile=jar包的路径 -DgroupId=个人groupId -DartifactId=个人artifactId -Dversion=个人version -Dpackaging=jar
本地仓库默认路径是用户目录下的.m2/repository/
;
该路径能够在settings.xml
中修改,好比:
<localRepository> /usr/local/maven/repository </localRepository>
那么远程仓库又在哪里?
打开$M2_HOME/lib/maven-model-builder-3.2.1.jar里的 org/apache/maven/model/pom-4.0.0.xml
看到远程仓库的设置以下:
<repositories> <repository> <id>central</id> <name>Central Repository</name> <url>http://repo.maven.apache.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
固然,咱们也能够配置其余远程仓库,好比这样:
<repositories> <repository> <id>opensesame</id> <name>Alibaba OpenSource Repsoitory</name> <url>http://code.alibabatech.com/mvn/releases/</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
配置远程仓库时也须要注意一些选项
daily
interval : X
:每隔X分钟间差warn
,另外有fail
和ignore
为何区分release和snapshot? 不能只经过版本号进行区分吗?
试想一下这样的场景,假设有A和B两个模块,A依赖B,且B还没有开发完成。
如何让B模块每次更新后让A的开发人员获取?
每次更新后提示A的开发人员从VCS上pull下来构建?
或者不停地换版本号? 确实,就算B有了变化,但version也是依赖的标识之一。
若是依赖是snapshot则能解决这样的问题,snapshot发布时会加上一个时间戳,每次构建A的时候会检查B是否最新,间差更新策略就是上面的updatePolicy
。
另外,也能够执行mvn clean install-U
强制更新。
远程仓库不都是想访问就访问的,有些仓库出于安全考虑,须要提供认证信息才能够访问。
认证必须在settings.xml
中设置,下面是一个例子:
<servers> <server> <id>server001</id> <username>my_login</username> <password>my_password</password> <privateKey>${user.home}/.ssh/id_dsa</privateKey> <passphrase>some_passphrase</passphrase> <filePermissions>664</filePermissions> <directoryPermissions>775</directoryPermissions> <configuration></configuration> </server> </servers>