本篇博客需要学习的东西如下:
分模块开发的意义是什么?
能够使用聚合工程快速构建项目
能够使用继承简化项目配置
能够根据需要配置生产,开发,测试环境,并在各个环境间切换运行

一个maven工程的一组标识:
groupId:例如com.itdong
artifactId:就是项目名
version:版本号
打包方式:jar,war,pom

回过头想:这不也是一个jar包坐标的一组标识吗。

一,分模块开发与设计

一个项目一个模块?
不是一个项目应该是多个模块。

一个项目应该是被根据功能划分成多个模块。

按照层级或者功能都可以。

主要是,如何让一个多模块的项目能像一个整体的项目一样运行。
如果是在一个团队中做一个开发应该怎么办,因为在不同的机器上,怎么保证我的模块能被项目中的其他模块引用。或者说我可以引用其他人开发的模块。

模块引用模块:
每一个模块都是一个maven工程,也就是说,都有pom配置文件,模块是怎么被引用的呢?其实就是将该模块当成是jar包一样。

maven工程想要被真正的运行,真正执行的是maven工程中的生命周期。
至少要compile编译通过,为什么模块引用模块不能通过编译呢?
模块是被另一个模块当成了jar包,而我们maven工程讲究的是一个jar包和项目分离,也就是说,当前的模块虽然在pom中是被引用了,但是事实上并没有真正的在中央仓库,还是私服或者是本地中存在。编译时就会有错误。
maven工程中有一个生命周期叫install安装,就是将当前的模块安装到我们的本地仓库中。
也就是说,只有当被引用的模块真的在仓库存在,才能被真的引用,不然的话,只是说,ide识别了,不会爆红罢了。

二,依赖管理

依赖的传递:

直接依赖和间接依赖,直接依赖就是直接当前pom中的jar包,间接依赖就是直接依赖中的依赖,也就是说,一个分模块的项目中,同一种jar包可能会被引用好多好多次。
万一相同的jar包的版本不一样怎么办?
称之为依赖冲突。
在直接依赖中,后写的为准。
在间接依赖中,层级高的为准。如果同层级,先写的为准。
maven显示的最后是什么版本,就是冲突之后的最终结果。

但是,不同模块是由不同的团队开发的。不同的团队使用的jar包版本不同,这样的依赖冲突是不可能避免的,对于一个项目而言,最好就是将模块中使用的版本进行一个统一。这其实就是boot工程的一个好处。

可选依赖:

就是
A引用B, B引用C
在B中引用C时,B自然可以使用到C,此时如果没有在B引用C时做特殊的手脚,A自然也可以使用到C,
但是B如果不想让A知道自己使用的了C,那么就需要一个特殊的处理,就是在B引用C时,在dependency中加入一个optional,意思就是,这个C只作为B的直接引用,但是不作为A的间接引用。

所以,可选依赖就是,B可以决定向上层屏蔽哪些依赖。

那么对于A而言呢?
A不想有B中的某一个依赖,但是B却没有屏蔽,那么A如何自己控制呢?

排除依赖

在A引用B时的dependency中加入一个exclusions
exclusions是一个exclusion组,每一个exclusion就是配置B中要配置的一个依赖。
此时发现不用写版本,A自然会去找B中的依赖版本精准排除。

三,聚合与继承

聚合

多模块的项目中,对于上层的模块来说,是需要随着低层模块的更新而重新构建的。也就说,当一个多模块的项目有变动时,应该有一种聚合的手段将所有模块一起再构建,不然十分的难受,难道一个一个再手动的install一遍吗?显然这样是很麻烦的。

管理模块:
compile所有模块一起,install也是所有模块一起。
将多个模块组织成一个整体,同时进行项目的构建的过程叫做聚合。
这个管理的模块也叫做聚合工程,通常是一不具有业务功能的空的模块,只有一个pom文件。

聚合工程的打包方式:
不是jar也不是war
而是pom

在pom中设置管理的模块名称。
使用modules
包含一组module
使用路径来搜索,
当前路径的上一层
../
就是上一层,这一层也就是模块的根路径。

那么聚合工程的一键构建和模块间相互引用的顺序和modules中的书写顺序有什么关系吗?
只和模块间的依赖关系有关。

继承

第一个问题是,模块间依赖重复的问题:
一个项目,模块间的依赖重复了呢?

第二个问题,既然这些模块依赖重复了,那么我们项目中如果要更新某一个依赖的版本。那么是不是需要一个一个模块中改呢?

模块之间也有一种父子关系。
引用关系是避免不了依赖的重复和冲突的。
依赖冲突目前可以使用可选依赖和排除依赖解决。
但是依赖重复是没有办法解决的?

而继承就可以进一步解决这两个问题,简化配置,减少冲突。

一般就是将聚合工程作为所有模块的一个父工程。
只需要在模块中声明一下,是聚合工程的子模块就可以了。
使用parent声明。
除了gav
还有一个relativepath
相对路径指定父模块。
也是使用的../

父工程中还提供了一个更加人性化的设计:
dependenyManagement
意思是提供的依赖不会被强制的继承,可以让子类选择继不继承,由于版本已经在父工程中被指定好了。所以,子工程如果想要继承,不需要再指定版本号。

四,属性管理

事实上属性并不一定就是分模块开发的内容了。
而是说,在聚合工程中使用属性可以配合继承的原理,将抽取出来的依赖再进一步的解耦,将版本的信息单拎出来。方便后期的维护。

但是,就算不是分模块开发的项目,pom的属性设置也是有很大的意义的,只要设置成非pom文件也能用的话,不也就可以用以jdbc连接信息的解耦。
太简单了

设置和使用
但是pom中的属性是配置进了maven,只能是在项目的模块间的pom文件中使用,如果不当当只想在pom文件中使用,例如jdbc.properties,就要配置,扩大maven的控制范围。

开启资源文件的目录加载属性的过滤器。

还有一个注意点:
主要是web工程要注意,因为war的install方式必须要有web.xml这个文件。

扩展:
maven的五级属性:
1.自定义(常用)
2.内置属性
3.Setting属性
4.java系统属性
5.环境变量属性

jar包的版本:

五,多环境配置与应用


在聚合工程的pom文件中,配置install时加载的多环境情况区分
其实就是一个profiles

六,私服

nexus

分仓库
解决快照版本和正式版本的混乱,还有通用非开发依赖的仓库,第一次去找中央仓库,以后就不用。截断开发和中央仓库的联系。
还有仓库组
解决访问仓库时的麻烦。

一个项目对应一个仓库组,一个仓库组中会有若干个宿主仓库。所有的项目都是公用代理仓库的。

也就是说,仓库组是用来给团队开发共享的。

配置是在哪里呢?
在maven的配置文件setting.xml