一、依赖管理
依赖:当前项目运行需要的jar包
(一)依赖传递
以下面三个模块为例
01依赖02和03,03依赖02,这时在01的pom中可以只写03的依赖,因为03已经包含02的依赖了。01就间接依赖02
(二)可选依赖&排除依赖
以下两个操作都不需要指定版本
可选依赖:在当前项目的需要的坐标里添加<optional>
坐标,配置后这个依赖就不能再被间接依赖,只能被直接依赖。
<!-- 比如我有一个junit依赖,当别人导入我的模块时,不希望被别人使用到这个依赖,就可以用可选依赖 -->
<!-- 可选依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<optional>true</optional>
</dependency>
排除依赖:在当前项目,不希望用某一个jar包的某个间接依赖,在这个jar包的坐标里配置<exclusions>
排除掉这个依赖。
<!-- 比如我想用自己的mybatis版本,不希望用MavenModule03的mybatis,这时就用排除依赖 -->
<dependency>
<groupId>com.fn</groupId>
<artifactId>MavenModule03</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
(三)依赖范围
二、分模块开发与设计
思路:将单体的Controller、Service、DAO(Mapper)、Pojo全都使用Maven拆分出来,通过Maven的pom引入对应的依赖(如Mapper需要Pojo就在pom加上dependency)。各个Maven模块的dependency和application就根据自身需要来进行添加。
注意:
- 在dependency其他模块时,记得先install其他模块。
- 每个模块的包名路径和单体的一样。
总结:
- 模块中仅包含当前模块对应的功能类与配置文件。
- spring核心配置根据模块功能不同进行独立制作。
- 当前模块所依赖的模块通过dependency加入到当前模块才可以使用。
(一)Mapper(Dao)拆分
- 新建Maven工程。
- Mapper接口。
- Mapper.xml文件。
- 关于数据层的application(取名为application-dao防止和service以及controller重名)。
- 关于数据层的pom依赖。
- 如果有拆分Pojo,在pom里添加上pojo的依赖,打包的时候记得先install Pojo再打包。
(二)Service拆分
- 新建Maven工程。
- Service接口。
- ServiceImpl。
- 关于业务层的application(取名application-service)。
- 关于业务层的pom依赖。
- 添加Mapper的dependency,不需要添加Pojo的dependency,因为Mapper有依赖传递了。
- 如果有单元测试,单元测试的
@ContextConfiguration
需要添加Mapper和Service的application。
(三)Controller拆分
- 新建Maven工程 。
- Controller接口。
- 自定义异常等。
- 关于控制层的application(取名application-controller)。
- 关于业务层的pom依赖。
- 添加Service的dependency。
(四)重难点:配置文件&QA
- 以前common里如config等文件放在哪里?
哪里需要用到就放哪里,如MP的config就放在Mapper模块。 - 如果需要加载所有模块的application,用通配符
*
。
三、聚合与继承
(一)聚合
为什么需要聚合?
使用多模块开发时,可以使用聚合来一次性构建(compile)全部模块,不然就要手动多次的去构建很多模块(对顶层的模块进行install,其余模块也会跟随install)。
- 创建一个Maven模块(…_parent),设置打包类型为
pom
注意:每个Maven工程都有对应的打包方式,默认为jar,web工程打包方式是war。 - 使用
<modules>
设置当前聚合工程所管理的子模块名称。 - 聚合的install会先install最底层的,再一层层向上install。
在pom.xml
中整体配置如下:
<groupId>com.fn</groupId>
<artifactId>MavenModule10</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>../MavenModule01</module>
<module>../MavenModule02</module>
<module>../MavenModule03</module>
</modules>
依赖传递与聚合的区别:
- 依赖传递:通过pom说明我现在
需要使用哪些模块
(哪些jar包)。 - 聚合:子模块太多,通过pom统一管理子模块(如一次install所有子模块)。
- 继承:子模块太多,假如每个子模块都要用junit,那每个子模块都要加一次junit的依赖;这时就可以在父模块添加junit的依赖(指明
version
),在子模块需要引入依赖时只指明groupId
和artifactId
。
(二)继承
为什么需要继承?
- 比如当有多个模块都使用了spring-webmvc的坐标,那每个模块都要写一遍,繁琐。
- 比如有三个模块,前两个模块用了一样的jar包,这时能不能快捷导入坐标。
- 使用继承,当某个坐标需要更改版本号时,只需修改一次,全部模块都可以更改版本。
Maven继承:描述了两个工程之间的关系,子工程可以继承父工程的配置信息,常用于依赖关系的继承。可以简化配置、减少版本冲突
- 子工程中,使用
<parent>
标签,让子工程继承父工程(一般继承和聚合写在一个文件)
<parent>
<groupId>com.fn</groupId>
<artifactId>MavenModule10</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 下面这个标签让子工程快速找到父工程,不写也可以 -->
<relativePath>../MavenModule10/pom.xml</relativePath>
</parent>
-
父工程中,
<dependencies>
里的内容表示所有模块都会用到的坐标。 -
父工程中,
<dependencyManagement>
里的内容表示子工程可选择使用的坐标(不强制使用)。 -
子工程中,对于选择使用的坐标,和原来一样使用
<dependency>
标签导入就行,但是不要指定版本号,版本由父工程同一提供,这样就是使用父工程的可选坐标。
四、属性
(一)入门
- 父工程中,使用
<properties>
标签定义属性(相当于pom中的变量),然后自定义属性名称,以Spring的所有坐标为例。
<!-- 定义属性,管理版本 -->
<properties>
<!-- 标签名是自定义的 -->
<spring.version>5.2.10.RELEASE</spring.version>
<logback.version>1.2.3</logback.version>
</properties>
- 坐标中使用属性,以Spring为例
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring整合JUnit -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
(二)配置文件加载属性
以jdbc.properties
为例
- 在
<properties>
中定义属性。
<properties>
<spring.version>5.2.10.RELEASE</spring.version>
<logback.version>1.2.3</logback.version>
<!-- 下面是属性 -->
<jdbc.url>jdbc:mysql://127.0.0.1:3306/db1?serverTimezone=UTC</jdbc.url>
</properties>
- 配置文件
jdbc.properties
中,用${内容}
代替原有内容。 - 使用
<build>
添加一个插件,用来扩大属性的作用范围。
<!-- 新增插件,扩大属性的作用范围 -->
<build>
<resources>
<resource>
<!-- 配置文件在哪个目录下 -->
<directory>${project.basedir}/MavenModule01/src/main/resources</directory>
<!-- 开启过滤规则,能够识别${} -->
<filtering>true</filtering>
</resource>
</resources>
</build>
(三)版本管理
版本的命名规则:
五、多环境配置与应用
(一)多环境开发
- 定义多环境
<!-- 配置多环境 -->
<profiles>
<!-- 定义开发环境 -->
<profile>
<!-- id唯一 -->
<id>env_dep</id>
<!-- 在这里来定义需要的属性 -->
<properties>
<jdbc.url>jdbc:mysql://127.1.1.1:3306/db1?serverTimezone=UTC</jdbc.url>
</properties>
<!-- 默认启动哪个环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 生产环境 -->
<profile>
<!-- id唯一 -->
<id>env_pro</id>
<properties>
<jdbc.url>jdbc:mysql://127.2.2.1:3306/db1?serverTimezone=UTC</jdbc.url>
</properties>
<!-- 默认启动哪个环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 测试环境 -->
<profile>
<!-- id唯一 -->
<id>env_test</id>
<properties>
<jdbc.url>jdbc:mysql://127.3.3.1:3306/db1?serverTimezone=UTC</jdbc.url>
</properties>
<!-- 默认启动哪个环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
- 使用多环境
mvn 指令 -P 环境的id
eg:mvn install -P pro_env
(二)配置文件管理
在开发maven项目时,一般都会把配置文件放到src/main/resources目录下,针对这个目录,maven的<resources>
对其进行单独的配置。
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<!-- 将以下文件包含在编译打包中 -->
<include>**/*.properties</include>
<include>**/*.yml</include>
<include>**/*.xml</include>
</includes>
<excludes>
<!-- 以下文件不参与编译打包,如果includes和excludes冲突,以excludes为准 -->
<exclude>event/**</exclude>
<exclude>env/**</exclude>
</excludes>
<!-- filtering是否开启替换标签,若文件中有类似${key}这样的配置,就会根据maven的配置进行覆盖(从profiles里替换),让其使用真实值来填写,true表示开启替换,false表示不开启替换,无此标签表示不开启替换 -->
<filtering>true</filtering>
</resource>
<resource>
<!-- 第一段排除了event和env的配置文件,下面单独进行配置 -->
<directory>src/main/resources/event</directory>
<!-- 开启占位标签替换 -->
<filtering>true</filtering>
<includes>
<!-- profiles的properties标签配置了event.active标签,maven打包时勾选了profiles的标签,那么通过占位符会打包指定文件,如果profiles的文件都没勾选,则event文件夹所有配置都不会打包 -->
<include>event-${event.active}.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources/env</directory>
<filtering>true</filtering>
<includes>
<include>bootstrap-${env.active}.yml</include>
</includes>
</resource>
</resources>
上述例子的编译结果:
maven的pom.xml中resources标签介绍
(三)跳过测试
应用场景:功能更新想上线测试一部分,但还没写完,这时不跳过测试就打包不了、或者快速打包的场景。
方式一:
方式二:
- pom的
<build>
中添加一个插件
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<!-- 如果为true,则和方式一没区别 -->
<skipTests>false</skipTests>
<!-- includes是包含哪些测试用例 -->
<includes>
<include>**./BookServiceTest.java</include>
</includes>
<!-- excludes是排除哪些测试用例 -->
<excludes>
<!-- 跳过哪些测试用例 -->
<exclude>**./BookServiceTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
这个插件的名称和版本通过一次打包或者编译后可以查看到:
方式三:
六、私服
(一)私服简介
- 用于解决团队内部的资源共享与资源同步问题
- 私服的实现软件有很多,推荐一个Nexus,貌似要上楼梯才能下。
- cmd启动
nexus.exe /run nexus
- 浏览器访问
http://localhost:8081
etc/nexus-default.properties
可以改端口- nexus.exe所在目录的
nexus.vmoptions
修改服务器运行时的配置。
(二)私服仓库分类
(三)本地仓库访问私服的配置
- 网页上创建两个仓库
设置>>Repository>>Repositories>>Create repository>>maven2(hosted)>>fn-relase和fn-snapshot - maven-public>>将两个仓库添加到这个仓库组
- maven的
settings.xml
文件中,在<servers>
标签中将两个仓库添加,在<mirrors>
标签中
<server>
<id>fn-relase</id>
<username>admin</username>
<password>admin</password>
</server>
<server>
<id>fn-snapshot</id>
<username>admin</username>
<password>admin</password>
</server>
<mirror>
<id>maven-public</id>
<!-- 所有操作都进这里拿jar包 -->
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
(四)资源上传与下载
- 父工程的pom中
<distributionManagement>
<repository>
<id>fn-release</id>
<url>http://localhost:8081/repository/fn-release/</url>
</repository>
<snapshotRepository>
<id>fn-snapshot</id>
<url>http://localhost:8081/repository/fn-snapshot/</url>
</snapshotRepository>
</distributionManagement>
- 将私服中的远程仓库地址改为阿里的
网页中>>选择maven-central代理中央仓库>>Remote storage>>http://maven.aliyun.com/nexus/content/groups/public/
>>save - 使用
mvn deploy
或者点击deploy
,这时就走的私服
七、生命周期与插件
(一)生命周期
多个插件组合成一个流程,形成生命周期。
如下所示,每一行都是一件事,这每一行都有一个插件去实现该功能;
比如在执行compile生命周期时,该生命周期就是将上面的一个个插件组合起来形成生命周期。
(二)插件
默认maven都有一些常用插件,并且插件都有对应的功能作用,不用在pom声明插件。
但我们可以主动修改某个插件所需要执行的功能(如下)。