三.聚合和继承
我们的项目已经从以前的单模块,变成了现在的多模块开发。项目一旦变成了多模块开发以后,就会引发一些问题,在这一节中主要学习两个内容聚合
和继承
,用这两个知识来解决下分模块后的一些问题。
3.1 聚合
3.1.1 什么是聚合
-
分模块开发后,需要将这四个项目都安装到本地仓库,目前我们只能通过项目Maven面板的install 来安装,并且需要安装四个,如果我们的项目足够多,那么一个个安装起来还是比较麻烦的
-
如果四个项目都已经安装成功,当 ssm_pojo 发生变化后,我们就得将 ssm_pojo 重新安装到maven 仓库,但是为了确保我们对 ssm_pojo 的修改不会影响到其他项目模块,我们需要对所有的模块进行重新编译,那又需要将所有的模块再来一遍
项目少的话还好,但是如果项目多的话,一个个操作项目就容易出现漏掉或重复操作的问题,所以我们就想能不能抽取一个项目,把所有的项目管理起来,以后我们要想操作这些项目,只需要操作这一个项目,其他所有的项目都走一样的流程,这个不就很省事省力。
这就用到了我们接下来要讲解的聚合,
-
所谓聚合: 将多个模块组织成一个整体,同时进行项目构建的过程称为聚合
-
聚合工程:通常是一个不具有业务功能的"空"工程(有且仅有一个pom文件)
-
作用:使用聚合工程可以将多个工程编组,通过对聚合工程进行构建,实现对所包含的模块进行同步构建
-
当工程中某个模块发生更新时,必须保障工程中与已更新模块关联的模块同步更新,此时可以使用聚合工程来解决批量模块同步构建的问题。
-
3.1.2 聚合的实现步骤
步骤1: 创建一个空的maven项目
步骤2: 将项目的打包方式改为pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<packaging>pom</packaging>
</project>
说明: 项目的打包方式,我们接触到的有三种,分别是
-
jar:默认情况,说明该项目为java项目
-
war:说明该项目为web项目
-
pom:说明该项目为聚合或继承项目(后面会讲)
步骤3: pom.xml添加所要管理的项目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<packaging>pom</packaging>
<!--设置管理的模块名称-->
<modules>
<module>../maven_02_ssm</module>
<module>../maven_03_pojo</module>
<module>../maven_04_dao</module>
</modules>
</project>
步骤4:使用聚合统一管理项目
测试发现,当maven_01_parent
的compile
被点击后,所有被其管理的项目都会被执行编译操作。这就是聚合工程的作用。
说明:聚合工程管理的项目在进行运行的时候,会按照项目与项目之间的依赖关系来自动决定执行的顺序,和配置的顺序无关。
聚合的知识我们就讲解完了,最后总结一句话就是,聚合工程主要是用来管理项目。
3.2 继承
3.2.1 什么是继承
我们已经完成了使用聚合工程去管理项目。接下来,我们再来分析下,多模块开发存在的另外一个问题,重复配置
的问题,我们先来看张图:
-
spring-webmvc
、spring-jdbc
在三个项目模块中都有出现,这样就出现了重复的内容 -
spring-test
只在 ssm_crm 和 ssm_goods 中出现,而在 ssm_order 中没有,这里是部分重复的内容 -
我们使用的 spring 版本目前是
5.2.10.RELEASE,
假如后期要想升级spring版本,所有跟Spring相关jar包都得被修改,涉及到的项目越多,维护成本越高
面对上面的这些问题,我们就得用到接下来要学习的==继承==
-
所谓继承: 描述的是两个工程间的关系,与java中的继承相似,子工程可以继承父工程中的配置信息,常见于依赖关系的继承。
-
作用:
-
简化配置
-
减少版本冲突
-
3.3.2 继承的实现步骤
步骤1: 创建一个空的Maven项目并将其打包方式设置为pom。
因为这一步和前面maven创建聚合工程的方式是一摸一样,所以我们可以单独创建一个新的工程,也可以直接和聚合公用一个工程。实际开发中,聚合和继承一般也都放在同一个项目中,但是这两个的功能是不一样的。
步骤2: 在子项目中设置其父工程
分别在 maven_02_ssm,
maven_03_pojo,
maven_04_dao
的pom.xml中添加其父项目maven_01_parent
<!--配置当前工程继承自parent工程-->
<parent>
<groupId>com.itheima</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-RELEASE</version>
<!--设置父项目pom.xml位置路径-->
<relativePath>../maven_01_parent/pom.xml</relativePath>
</parent>
步骤3: 优化子项目共有依赖导入问题
-
将子项目共同使用的jar包都抽取出来,维护在父项目的pom.xml中
-
删除子项目中已经被抽取到父项目的pom.xml中的jar包,如在
maven_02_ssm
的pom.xml中将已经出现在父项目的jar包删除掉
删除完后,你会发现父项目中有依赖对应的jar包,子项目虽然已经将重复的依赖删除掉了,但是刷新的时候,子项目中所需要的jar包依然存在。
当项目的<parent>
标签被移除掉,会发现多出来的jar包依赖也会随之消失。
步骤4: 优化子项目依赖版本问题
如果把所有用到的jar包都管理在父项目的pom.xml,看上去更简单些,但是这样就会导致有很多项目引入了过多自己不需要的jar包。
那么针对这种情况,我们该如何管理优化呢?
1. 在父工程mavne_01_parent的pom.xml来定义依赖管理
<dependencyManagement>标签只是对依赖的版本进行管理,并不是真正的把依赖引入项目。
<!--定义依赖管理-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
2. 将maven_02_ssm的pom.xml中的junit依赖删除掉,刷新Maven
刷新完会发现,在maven_02_ssm项目中的junit依赖并没有出现,所以我们得到一个结论:
==<dependencyManagement>
标签不真正引入jar包,而是配置可供子项目选择的jar包依赖==
子项目要想使用它所提供的这些jar包,需要自己添加依赖,并且不需要指定<version>
3. 在maven_02_ssm的pom.xml添加junit的依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
这里就不需要添加版本了,这样做的好处就是当父工程dependencyManagement标签中的版本发生变化后,子项目中的依赖版本也会跟着发生变化。
3.3 聚合与继承的区别
3.3.1 聚合与继承的区别
两种之间的作用:
-
聚合用于快速构建项目,对项目进行管理
-
继承用于快速配置和管理子项目中所使用jar包的版本
聚合和继承的相同点:
-
聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中
-
聚合与继承均属于设计型模块,并无实际的模块内容
聚合和继承的不同点:
-
聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
-
继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己
3.3.2 IDEA构建聚合与继承工程
现在有一个稍微麻烦的地方就是聚合和继承的工程构建,需要在聚合项目中手动添加modules
标签,需要在所有的子项目中添加parent
标签,万一写错了咋办?
其实对于聚合和继承工程的创建,IDEA已经能帮助我们快速构建,具体的实现步骤为:
步骤1:创建一个Maven项目
创建一个空的Maven项目,可以将项目中的src
目录删除掉,这个项目作为聚合工程和父工程。
步骤2:创建子项目
该项目可以被聚合工程管理,同时会继承父工程。
创建成功后,maven_parent即是聚合工程又是父工程,maven_web中也有parent标签,继承的就是maven_parent,对于难以配置的内容都自动生成。
四. 属性
4.1 属性
4.1.1 问题分析
讲解内容之前,我们还是先来分析问题:
前面我们已经在父工程中的dependencyManagement标签中对项目中所使用的jar包版本进行了统一的管理,但是如果在标签中有如下的内容:
你会发现,如果我们现在想更新Spring的版本,你会发现我们依然需要更新多个jar包的版本,这样的话还是有可能出现漏改导致程序出问题,而且改起来也是比较麻烦。
问题清楚后,我们需要解决的话,就可以参考咱们Java基础所学习的变量,声明一个变量,在其他地方使用该变量,当变量的值发生变化后,所有使用变量的地方,就会跟着修改,即:
4.1.2 解决步骤
步骤1: 父工程中定义属性
<properties>
<spring.version>5.2.10.RELEASE</spring.version>
<junit.version>4.12</junit.version>
<mybatis-spring.version>1.3.0</mybatis-spring.version>
</properties>
步骤2: 修改依赖的version
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</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-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
4.2 配置文件加载属性
Maven中的属性我们已经介绍过了,现在也已经能够通过Maven来集中管理Maven中依赖jar包的版本。但是又有新的需求,就是想让Maven对于属性的管理范围能更大些,比如我们之前项目中的jdbc.properties
,这个配置文件中的属性,能不能也来让Maven进行管理呢?
答案是肯定的,具体的实现步骤为:
步骤1: 父工程定义属性
<properties>
<jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_db</jdbc.url>
</properties>
步骤2: jdbc.properties文件中引用属性
在jdbc.properties,将jdbc.url的值直接获取Maven配置的属性
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=${jdbc.url} jdbc.username=root jdbc.password=root
步骤3: 设置maven过滤文件范围
Maven在默认情况下是从当前项目的 src\main\resources
下读取文件进行打包。现在我们需要打包的资源文件是在maven_02_ssm下,需要我们通过配置来指定下具体的资源目录。
<build>
<resources>
<!--设置资源目录-->
<resource>
<directory>../maven_02_ssm/src/main/resources</directory>
<!--设置能够解析${},默认是false -->
<filtering>true</filtering>
</resource>
</resources>
</build>
说明:directory路径前要添加 ../
的原因是 maven_02_ssm 相对于父工程的 pom.xml 路径是在其上一层的目录中,所以需要添加。
修改完后,注意 maven_02_ssm 项目的 resources 目录就多了些东西,如下:
步骤4: 测试是否生效
测试的时候,只需要将maven_02_ssm项目进行打包,然后观察打包结果中最终生成的内容是否为Maven中配置的内容。
上面的属性管理就已经完成,但是有一个问题没有解决,因为不只是maven_02_ssm项目需要有属性被父工程管理,如果有多个项目需要配置,该如何实现呢?
方式一:
<build>
<resources>
<!--设置资源目录,并设置能够解析${}-->
<resource>
<directory>../maven_02_ssm/src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>../maven_03_pojo/src/main/resources</directory>
<filtering>true</filtering>
</resource>
...
</resources>
</build>
可以配,但是如果项目够多的话,这个配置也是比较繁琐
方式二:
<build>
<resources>
<!--
${project.basedir}: 当前项目所在目录,子项目继承了父项目,
相当于所有的子项目都添加了资源目录的过滤
-->
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
4.2.1 可能出现的bug
打包的过程中如果报如下错误:
原因就是Maven发现你的项目为web项目,就会去找web项目的入口web.xml[配置文件配置的方式],发现没有找到,就会报错。
解决方案1:在maven_02_ssm项目的src\main\webapp\WEB-INF\
添加一个web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
</web-app>
解决方案2: 配置maven打包war时,忽略web.xml检查
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
4.2.2 Maven的内置属性
上面我们所使用的都是Maven的自定义属性,除了${project.basedir},它属于Maven的内置系统属性。在Maven中的属性分为:
-
自定义属性(常用)
-
内置属性
-
Setting属性
-
Java系统属性
-
环境变量属性
具体如何查看这些属性:
在cmd命令行中输入mvn help:system
具体使用,就是使用 ${key}
来获取,key为等号左边的,值为等号右边的,比如获取红线的值,对应的写法为 ${java.runtime.name}
。
4.3 版本管理
关于这个版本管理解决的问题是,在Maven创建项目和引用别人项目的时候,我们都看到过如下内容:
这里面有两个单词,SNAPSHOT和RELEASE,它们所代表的含义是什么呢?
我们打开Maven仓库地址https://mvnrepository.com/
在我们jar包的版本定义中,有两个工程版本用的比较多:
-
SNAPSHOT(快照版本)
-
项目开发过程中临时输出的版本,称为快照版本
-
快照版本会随着开发的进展不断更新
-
-
RELEASE(发布版本)
-
项目开发到一定阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的
-
即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本
-
除了上面的工程版本,我们还经常能看到一些发布版本:
-
alpha版:内测版,bug多不稳定内部版本不断添加新功能
-
beta版: 公测版,不稳定(比alpha稳定些),bug相对较多不断添加新功能
-
纯数字版
对于这些版本,大家只需要简单认识下即可。