1.分模块开发
将原始模块按照功能拆分成若干个子模块,方便模块间的相互调用,接口共享:比如有订单和商品两个模块,它们都需要使用到商品的模型类,如果在这两个模块中都写模型类,就会出现重复代码,维护也比较麻烦,于是就可以将
domain
抽取出来作为独立模块,其他模块就可以像添加第三方jar
包一样使用抽取的模块
流程分析
- 环境准备:代码参考Maven_02_ssm(该代码经由Springmvc_11_page修改)
- 抽取
domain
层:
- 创建Maven_03_pojo
- 将Maven_02_ssm中的
domain
层抽取到Maven_03_pojo- 在Maven_02_ssm的pom.xml中添加Maven_03_pojo的坐标
- 将模块安装到本地仓库:执行
maven
中的install
命令(如果直接编译Maven_02_ssm会报错,因为此时会去配置的本地仓库找Maven_03_pojo对应的jar
包,还没安装肯定找不到)- 抽取
dao
层:与抽取domain
层类似
- 创建Maven_04_dao
- 将Maven_02_ssm中的
domain
层抽取到Maven_04_dao- 在Maven_02_ssm的pom.xml中添加Maven_03_pojo的坐标;在Maven_04_dao的pom.xml添加Maven_03_pojo的坐标以及
Mybatis
的依赖- 将模块安装到本地仓库
2.依赖管理
依赖传递
A
依赖B
和C
,B
和C
又分别依赖了其他jar
包,则在A
项目中就可以使用上面所有jar
包
因为有依赖传递的存在,就会导致
jar
包在依赖的过程中出现冲突,如果解决?
- 当同级配置了相同资源的不同版本,后配置的覆盖先配置的
- 当依赖中出现相同的资源时,层级越深,优先级越低;层级越浅,优先级越高(比如上图中
E1
和E2
是版本不同的同个jar
包,因为E1
层级浅,所以A
会依赖E1
)- 当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的
可选依赖和排除依赖
可选依赖是隐藏当前工程所依赖的资源,隐藏后对应资源将不具有依赖传递:
<!--Maven_04_dao中的pom.xml 下面配置将Maven_04_dao中依赖的Maven_03_pojo设置为可选依赖,此时Maven_04_dao会对外隐藏该依赖 即Maven_04_dao依旧存在Maven_03_pojo依赖,但是在Maven_02_ssm就不会存在Maven_03_pojo依赖(也就用不了了) 因为Maven_02_ssm经过Maven_04_dao的传递依赖才依赖到Maven_03_pojo,此时Maven_04_dao把Maven_03_pojo隐藏了 --> <dependency> <groupId>com.psj.Maven</groupId> <artifactId>Maven_03_pojo</artifactId> <version>1.0-SNAPSHOT</version> <!--可选依赖是隐藏当前工程所依赖的资源,隐藏后对应资源将不具有依赖传递--> <optional>true</optional> </dependency>
排除依赖指主动断开依赖的资源,被排除的资源无需指定版本:
<!--Maven_02_ssm中的pom.xml 此时Maven_02_ssm不想依赖Maven_04_dao中所依赖的Maven_03_pojo 注意:不需要写版本号 --> <dependency> <groupId>com.psj.Maven</groupId> <artifactId>Maven_04_dao</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>com.psj.Maven</groupId> <artifactId>Maven_03_pojo</artifactId> </exclusion> </exclusions> </dependency>
综上所述,
A
依赖B
,B
依赖C
,现在要想办法让A
不去依赖C
:
- 可选依赖是在
B
上设置<optional>
, 前提是A
不知道有C
的存在- 排除依赖是在
A
上设置<exclusions>
, 前提是A
知道有C
的存在,想主动将其排除掉
3.聚合和继承
聚合
假如将下图的四个模块都安装到了本地仓库,此时
ssm_pojo
进行修改需要重新安装,因为其他模块也依赖它,意味着其他模块都需要重新编译安装,十分麻烦,该如何优化?使用聚合
聚合即将多个模块组织成一个整体,同时进行项目构建的过程;聚合工程通常是一个不具有业务功能的空工程(有且仅有一个
pom
文件)。在下图中左侧为聚合工程,可以将右侧四个模块进行同步构建:
聚合工程构建过程如下:
- 创建一个空的
maven
项目Maven_01_parent- 将项目的打包方式改为
pom
:
jar
:默认情况,说明该项目为java
项目war
:说明该项目为web
项目pom
:说明该项目为聚合或继承项目<groupId>com.psj.Maven</groupId> <artifactId>Maven_01_parent</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging>
- 在
pom.xml
添加要管理的项目:<modules> <module>../maven_02_ssm</module> <module>../maven_03_pojo</module> <module>../maven_04_dao</module> </modules>
- 使用聚合统一管理项目:点击Maven_01_parent的
compile
后,所有被其管理的项目都会被执行编译操作
继承
下图中三个模块都有的依赖有
spring-webmvc
、spring-jdbc
,也存在部分重复的依赖,如spring-test
,这就出现了大量重复内容,该如何优化?假设此时想升级某个模块中spring
的版本,意味着其他模块中使用了相同jar
包的版本都要修改,维护成本高,该如何解决?使用继承
继承描述的是两个工程间的关系,子工程可以继承父工程中的配置信息
使用继承的过程如下:
- 创建一个空的
maven
项目:还是使用Maven_01_parent- 将项目的打包方式改为
pom
- 在子项目中设置其父工程:在Maven_02_ssm等三个模块中的
pom.xml
中添加其父项目为Maven_01_parent<parent> <groupId>com.psj.Maven</groupId> <artifactId>Maven_01_parent</artifactId> <version>1.0-RELEASE</version> <!--设置父项目pom.xml位置路径--> <relativePath>../Maven_01_parent/pom.xml</relativePath> </parent>
优化子项目共有依赖导入问题:
- 将子项目共同使用的
jar
包都抽取出来维护在Maven_01_parent的pom.xml中- 删除子项目中已经被抽取到Maven_01_parent的pom.xml中的
jar
包优化子项目依赖版本问题:不同模块不一定需要Maven_01_parent中所有的依赖,需要进行依赖管理
- 在Maven_01_parent的pom.xml来定义依赖管理:
<!-- 此时不想让所有子模块都无脑继承junit设置dependencyManagement管理junit(dependency中就不要写junit了) <dependencyManagement>标签不真正引入jar包,而是配置可供子项目选择的jar包依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement>
- 在需要使用依赖的模块中添加相应的依赖:
<!-- 此时Maven_02_ssm模块想使用junit,就直接引入依赖即可,并且不用写版本号 当父工程dependencyManagement标签中的版本发生变化后,子项目中的依赖版本也会跟着发生变化 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency>
综上所示,继承主要完成两个功能:
- 将所有项目公共的
jar
包依赖提取到父工程的pom.xml
中,子项目就可以不用重复编写- 将所有项目的
jar
包配置到父工程的dependencyManagement
标签下,实现版本管理
聚合与继承的区别
- 作用:
- 聚合用于快速构建项目,对项目进行管理
- 继承用于快速配置和管理子项目中所使用
jar
包的版本- 相同点:
- 聚合与继承的
pom.xml
文件打包方式均为pom
(即可以将两种关系制作到同一个pom
文件中)- 聚合与继承均属于设计型模块,并无实际的模块内容
- 不同点:
- 聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
- 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己
4.属性
属性
前面已在父工程的
dependencyManagement
标签中对项目中所使用的jar包版本进行了统一的管理。但如果还有许多依赖包的版本要进行同步,该如何解决?和Java
一样使用变量:
步骤如下:
- 父工程中定义属性:
<properties> <spring.version>5.2.10.RELEASE</spring.version> </properties>
- 修改依赖的
version
:<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency>
配置文件加载属性
Maven
除了管理依赖jar
包的版本,还可以去管理配置文件,比如jdbc.properties
步骤如下:
- 父工程定义属性:
<properties> <jdbc.url>jdbc:mysql://127.0.0.1:3306/xxxx</jdbc.url> </properties>
jdbc.properties
文件中引用属性:该文件在子模块Maven_02_ssm中jdbc.driver=com.mysql.jdbc.Driver jdbc.url=${jdbc.url} jdbc.username=root jdbc.password=root
- 设置
Maven
过滤文件范围:Maven
在默认情况下是从当前项目的src\main\resources
下读取文件进行打包。现在需要打包的资源文件是在子模块下,需要通过配置来指定下具体的资源目录<!--在父工程的pom文件中定义--> <build> <resources> <!--设置资源目录--> <resource> <directory>../Maven_02_ssm/src/main/resources</directory> <!--设置能够解析${},默认是false--> <filtering>true</filtering> </resource> <resource> <directory>../Maven_04_dao/src/main/resources</directory> <!--设置能够解析${},默认是false--> <filtering>true</filtering> </resource> </resources> </build> <!--上面多个resource可以使用下面表述进行简化--> <build> <resources> <!-- ${project.basedir}: Maven的内置属性,表示当前项目所在目录,因为子项目继承了父项目, 相当于所有的子项目都添加了资源目录的过滤 --> <resource> <directory>${project.basedir}/src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build>
版本管理
SNAPSHOT
和RELEASE
代表的含义是啥?
SNAPSHOT
:快照版本,即项目开发过程中临时输出的版本(会随着开发不断更新)RELEASE
:发布版本,即项目开发到一定阶段里程碑后,向团队外部发布较为稳定的版本(后续开发功能时也不会改变当前发布版本内容)alpha
版:内测版,bug
多不稳定,内部版本不断添加新功能beta
版:公测版,不稳定(比alpha
稳定些),bug相对较多,不断添加新功能- 纯数字版
5.多环境配置与应用
多环境开发
当开发完成后,需要把开发的功能部署到测试环境供测试人员进行测试使用,等测试人员测试通过后,会将项目部署到生成环境上线使用。因为不同环境的配置不同(如需要三个数据库的
url
配置),在项目中如何配置?该如何在不同配置间切换呢?
- 父工程配置多个环境,并指定默认激活环境:
<profiles> <!--开发环境--> <profile> <id>env_dep</id> <properties> <jdbc.url>jdbc:mysql://127.1.1.1:3306/xxxx</jdbc.url> </properties> <!--设定是否为默认启动环境--> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <!--生产环境--> <profile> <id>env_pro</id> <properties> <jdbc.url>jdbc:mysql://127.2.2.2:3306/xxxx</jdbc.url> </properties> </profile> <!--测试环境--> <profile> <id>env_test</id> <properties> <jdbc.url>jdbc:mysql://127.3.3.3:3306/xxxx</jdbc.url> </properties> </profile> </profiles>
- 进行环境的切换:
- 在
pom.xml
中进行手动修改- 命令行实现环境切换:在父工程中执行
mvn install -P env_test
跳过测试
在执行
install
指令的时候,Maven
都会按照顺序从上往下依次执行,意味着每次都会执行test
。但功能开发过程中有部分模块还没开发完毕,测试无法通过,导致打包失败,可此时只想打包已开发的部分该怎么办?
IDEA
实现跳过测试:这种方式会跳过所有模块的测试
- 配置插件实现跳过测试:在父工程中的pom.xml中添加测试插件配置
<build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.12.4</version> <configuration> <!-- skipTests:如果为true,则跳过所有测试,如果为false,则不跳过测试 excludes:哪些测试类不参与测试,针对skipTests为false来设置的 includes: 哪些测试类要参与测试,针对skipTests为true来设置的 --> <skipTests>false</skipTests> <!--排除掉不参与测试的内容--> <excludes> <exclude>**/BookServiceTest.java</exclude> </excludes> </configuration> </plugin> </plugins> </build>
- 命令行跳过测试:
mvn 指令 -D skipTests
,其中指令必须包含测试
这一段生命周期(比如complie
就不包含)
6.私服
假设
A
负责ssm_crm
的开发,自己写了个ssm_pojo
模块,A只需要将该模块安装到本地即可使用。此时B
负责的ssm_order
也要用A
写的ssm_pojo
,就需要A
将ssm_pojo
生成的jar
包上传到中央仓库,但是Maven
的中央仓库不允许私人上传自己的jar
包,该怎么办?搭建类似中央仓库的东西-私服
私服和远程仓库的区别:
- 私服(比如
Nexus
)是公司内部搭建的用于存储Maven
资源的服务器,用于解决团队内部的资源共享与资源同步问题(与私服间的上传/下载需要通过本地仓库)- 远程仓库是
Maven
开发团队维护的用于存储Maven
资源的服务器
参考
https://www.bilibili.com/video/BV1Fi4y1S7ix?p=75-89