公司的项目基本都是基于maven的多module项目,controller,service,model,dao等都被分成了不同的module,这样做当然也是为了解耦。
POM中的名词解释
父类工程的pom文件
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId></groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId></groupId>
<artifactId>test</artifactId>
<version>1.0.100</version>
<packaging>pom</packaging>
<name>test</name>
<modules>
<module>common</module>
<module>view</module>
<module>business</module>
</modules>
pom中有以下的元素:
modelVersion: 说明项目描述符遵循哪一个 POM 模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,这是为了当 Maven 引入了新的特性或者其他模型变更的时候,确保稳定性
parent: 父项目的坐标。子项目会继承父项目的 dependencies, properties 等配置,也可以根据需要重写;类似于 java, 只支持单继承,但可以通过 dependencyManagement 突破这个限制,下文会说
groupId: 组织id,由域+组织名(公司名)组成,一般固定
artifactId: 项目名,一般起这个名字
version:版本号,必不可少
packaging: 打包方式,比不可少
modules: 用来说明本级pom中包含几个模块,例如common,view,business都是他的子模块
其中package的方式有3种
// 用于项目中无代码,也不执行任何代码,是为了聚合工程或传递依赖用的,一般用于做父项目/模块(意思是只要有子项目就是pom)
<packaging>pom</packaging>
// 用于把代码打成jar,一般用于兄弟项目/模块之间做依赖
<packaging>jar</packaging>
// 用于把代码达成war,一般用于项目部署
<packaging>war</packaging>
这些module可根据需要在配置来打成jar包。
例如,常见的web项目,有dao、model这些module,这些模块可以设置packaging级别为jar。
module之间可以通过module自己的来进行相互引用或依赖,如下图所示,
<dependency>
<groupId></groupId>
<artifactId>common-service</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>mapper</artifactId>
</dependency>
maven在执行install,packaging是jar的会被打成jar放在target目录下,所有依赖的jar(包括依赖的module,被打成jar)都会被放lib下。
多个module不需要分别执行mvn命令,可以使用聚合(aggregator)来一次构建全部模块
父工程中可被继承的POM元素
父工程中的以下元素可以被子模块继承和使用
groupId项目组ID,项目坐标的核心元素
version :项目版本,项目坐标的核心元素
description项目的描述信息
properties定义一些当前项目使用的变量名称,在子类中可以通过$获取直接使用
dependencies项目的依赖配置
dependencyManagement :项目的依赖管理配置
organnization :项目的组织信息
inceptionYear :项目的创始年份
url :项目的URL地址
developers :项目的开发者信息
repositories:项目的仓库配置 build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
继承parent和子module依赖(dependencies)
在父中通过modules来引用所有需要构建的子模块。
<modules>
<!-- 子模块都写在此处 -->
<module>common-service</module>
<module>mapper</module>
</modules>
继承parent,和java中的继承相当,作用就是复用,子模块可以继承父工程的所有依赖。
例如,若每个子模块都都用的了spring,那么我们是不是每个子模块都需要单独配置spring依赖了?这么做是可以的,但是我们有更优的做法,那就是继承,用parent来实现。也就是在parent中定义spring依赖,parent的所有子module都会继承spring依赖。使用dependencies在父pom中配置spring依赖。
如下所示,
父(account-aggregator)
<modules>
<!-- 模块都写在此处 -->
<module>common-service</module>
<module>mapper</module>
</modules>
<dependencies> <!-- 配置共有依赖 -->
<!-- spring 依赖 -->
<dependency>
<groupId></groupId>
<artifactId>spring-core</artifactId>
<version>4.0.</version>
</dependency>
<!-- junit 依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
子module中的不需要配置spring的依赖信息,会自动继承parent工程的所有依赖。同时
子module中可以配置自己单独使用的依赖,例如如下,
</parent>
<dependencies>
<!-- 配置自己独有依赖 -->
<dependency>
<groupId></groupId>
<artifactId>mail</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>greenmail</artifactId>
<version>1.4.1</version>
<scope>test</scope>
</dependency>
</dependencies>
dependencyManagement配置父工程和子模块之间的依赖
继承可以消除重复,那是不是就没有问题了? 答案是存在问题,假设将来需要添加一个新的子模块util,只是提供一些简单功能,不需要依赖父pom中的spring、junit等库,那么子模块继承父工程以后就会拥有父pom中的spring、junit等依赖,有没有什么办法了?当想在项目中加入一些,不需要父工程中某些依赖库。
Maven提供的 dependentcyManagement 元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活度。在 dependentcyManagement 元素下的依赖声明不会引入实际的依赖,而是定义了依赖的版本,对版本进行同一管理,避免出现版本不一致的情况。
在父中配置dependencyManagement元素
<modules>
<!-- 模块都写在此处 -->
<module>common-service</module>
<module>mapper</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- 配置共有依赖 -->
<!-- spring 依赖 -->
<dependency>
<groupId></groupId>
<artifactId>spring-core</artifactId>
<version>4.0.</version>
</dependency>
······
</dependencies>
</dependencyManagement>
子模块中,配置spring的依赖,不要指定spring的版本,父pom中已经指定。
<dependencies>
<!-- spring 依赖 -->
<dependency>
<groupId></groupId>
<artifactId>spring-core</artifactId>
</dependency>
</dependencies>
使用这种依赖管理机制似乎不能减少太多的POM配置,就少了version(junit还少了个scope),感觉没啥作用呀;其实作用还是挺大的,父POM使用dependencyManagement能够统一项目范围中依赖的版本,当依赖版本在父POM中声明后,子模块在使用依赖的时候就无须声明版本,也就不会发生多个子模块使用版本不一致的情况,帮助降低依赖冲突的几率。如果子模块不声明依赖的使用,即使该依赖在父POM中的dependencyManagement中声明了,也不会产生任何效果。