项目之间的依赖关系梳理:
依赖主要是根据maven来定位的,而maven的坐标主要由GAV(groupid,artifactid,version)构成。
例如:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
</dependency>
一组GAV构成了一个Maven的坐标,基于此,Maven就可以在本地或者远程仓库中找到对应的jar文件。
在定义maven的依赖的时候,也有一些很实用的技巧。
1. 依赖归类
当我们在一个项目总引用了许多依赖,而很多依赖的groupid是相同的,例如spring的一堆jar包依赖(诸如:org.spring.framework:spring-core, org.spring.framework:beans, org.spring.framework:spring-web, org.spring.framework:spring-mock),这些的groupid相同,而artifactid不同,version即版本也不同,为了将其进行统一的升级,逐个替换起版本号显然很愚蠢。
这时,我们定义一个maven属性,命名为spring.version,并赋值,这样在这个pom.xml中我们就可以使用${spring.version}的方式来引用该属性,当替换版本时,只需要修改spring.version的值就好了。
2. 依赖范围
有些jar包并不是一直需要的,例如junit测试包,只需要在运行测试的时候用上,将junit的jar包打入最终的发布包也不好,这显然让发布包无畏的增加了大小。这时,我们就可以对这个依赖加上scope属性,例如:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</test>
</dependency>
这样,junit对于主源码classpath不可用,但是对于测试源码classpath可用,且不会被打包。
主要的依赖范围和其作用如下:
+ compile(缺省),主源码classpath可用,测试源码classpath可用,会被打包
+ test,主源码不可用,测试源码可用,不会被打包
+ runtime,主源码不可用,测试源码可用,会被打包
+ provided,主源码可用,测试源码可用,不会被打包。例如:java.servlet-api是开发时必须的,但是不能打包,因为web容器会提供servlet-api,如果打包就会产生依赖冲突。
3. 分类器
在使用分类器的依赖下,相应的maven仓库中会下载的文件命名模式是:artifactid-version-classifer-packaging,其实,很容易发现很多文件都是默认构件的分类器扩展。
另外,分类器还可以用来声明对test构件的依赖,这样可供依赖的资源就会更加丰富
例如:
<dependency>
<groupId>org.myorg.myapp</groupId>
<artifactId>core</artifactId>
<version>${project.version}</version>
<classifier>test</classifier>
</dependency>
比如,我们在一个核心模块的src/test/java中声明了一些基础类,然后我们发现这些测试基础类对于很多其它模块的测试类都有用。没有分类器,我们是没有办法去依赖src/test/java中的内容的,因为这些内容不会被打包到主构件中,它们单独的被打包成一个模式为--test.jar的文件。而用上面的方法,我们就可以使用分类器来依赖这样的test构件。
4. 依赖管理
终于到了今天的重头戏,我学习maven依赖的目的就是弄明白一个多模块项目中模块间的依赖关系。
在多模块的项目中,很多模块的依赖是重复的,而重复就意味着会有潜在问题(当在整个项目中,引入不同的依赖版本,就会产生依赖冲突),而依赖管理就是用来解决这种重复依赖的问题的。
正确的做法:
首先,在父模板中使用dependencyManagement配置依赖;实际上,dependencyManagement实际上并不会真正引入任何依赖,dependencies才会,但是,当父模块中配置了某个依赖之后,子模块只需要使用简单的groupid和artificatid就能自动继承相应的父模块依赖配置。
然后,在子模块中使用dependencies添加依赖。
例子:
父模块中声明如下:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>a-parent</artifactId>
<version>1.0.0</version>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.2</version>
</dependency>
...
<dependencies>
</dependencyManagement>
子模块中声明如下:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>a-parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>project-a</artifactId>
...
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>
如何寻找自己需要的maven依赖呢?
Sonatype提供的服务器,且该仓库搜索的后台使用了Nexus–最强大的maven仓库管理器
mvnbrowser
mvnrepository仓库搜索服务
而对于公司的项目,一般会搭建自己的maven私服,这样只需要对外下载一次maven的jar包,然后就可以实现公司内网的访问(因为很多公司内网,尤其是开发网,设置了禁止外网访问)。