各位读者朋友,大家好,本文是《SpringBoot实战》专题的第一篇:多模块应用精讲,本系列文章将以实际的业务需求为落脚点,逐个攻破开发工作中的技术难点,全面提升你的技术能力、业务能力。
本系列文章将涉及到但不限于推荐系统、分布式文件存储、缓存、权限控制等业务场景以及Hadoop、Spark、Redis、Elasticsearch搜索引擎、Redis等技术热点,如果你有意深耕Java技术 ,提升竞争力,欢迎你订阅本专题。

一、本文主题
本文中讲涉及到如下问题:
- 什么是maven多模块应用?
- 什么业务场景下使用多模块?
- 如何搭多模块应用?
- 多模块应用中配置文件没有生效,如何解决?
- 多模块应用打包时如何配置,如何打包?
二、开发环境
- Jdk1.8
- maven3.6.3
- Eclipse2018
- SpringBoot2.1.16
上述开发环境仅作为参考,具体的编辑器、Java版本或者SpringBoot版本可根据个人喜好设置。
三、实战
01 什么是多模块应用?
多模块应用有一个比较严谨的名字:maven聚合工程,当然,开发过程中也有的人称之为SpringBoot多模块应用,总之,能理解就好。但这里要强调的是,将应用切割成多个模块并管理起来,是依托于maven这个项目管理工具,和SpringBoot并没有关系。
02 什么场景下可以使用多模块应用?有什么优点?
关于多模块应用的优点,很多人说多模块应用结构清晰,可以加快开发快速。我并不这样认为:首先,单体应用也可以把项目结构划分的很清晰;其次,开发速度一方面取决于工作量,另一方面取决于业务的复杂度,不是简单的搭建一个多模块应用就可以加快速度的。
多模块应用的核心在于将中大型的应用按照业务逻辑切割开,提高代码复用度以及服务器资源利用率。
- 通过父工程管理公共的依赖,子模块直接引用,将诸如数据库交互模块,工具类模块,公共业务方法模块隔离成独立模块,其它模块可以直接引用,这样便提高了代码的复用度。
- 单体应用时,只有一个进程在使用服务器资源,加大了应用内部的资源压力,也限制了资源利用率的提高。多模块应用时,可以有多个启动入口,如面向管理员的后台、面向用户的前台单独启动,多个进程使用服务器资源,既提高了资源利用率,也降低了应用内部的压力。
所以,如果项目体量小,仅涉及简单的增删改查,那么就没必要使用多模块应用。如果项目体量中等,一个业务模块都可以单独抽取为一个应用的时候,就可以使用多模块应用。当然,如果继续增大项目体量以及业务复杂度,就可以使用微服务开发,将各模块分布式部署。
03 如何搭建多模块应用(以Eclispe为例讲解)?
031 构建父模块
在https://start.spring.io/网站上快速构建一个SpringBoot应用,下载解压后导入Eclipse作为父工程(仅起到管理子模块的应用,不在父工程中写代码,可以删除src目录),打开pom.xml文件,配置打包方式,结果如下
<groupId>cn.zk</groupId>
<artifactId>multimodule</artifactId>
<version>1.0</version>
<!-- 配置打包方式 -->
<packaging>pom</packaging>
<name>multimodule</name>
<description>This is multi-module springboot project!</description>
032 删除父模块中不需要的文件夹
- 右键src目录,删除该目录,对于JRE System Library和Maven Dependencies,需要右键-->build path-->remove移除

033 新建数据库交互模块
- 右键父工程,new project-->maven module,简单填写dao模块信息后,点击确定

此时,父工程pom文件中会多出一个模块的配置信息。

034 新建数据库交互模块
- 配置子模块的jre版本为1.8
- 打开dao模块pom文件,配置dao模块信息,添加依赖
<!-- 子模块的基本信息 -->
<groupId>com.xz.multimodule</groupId>
<artifactId>dao</artifactId>
<!-- 配置打包方式 -->
<packaging>pom</packaging>
<name>dao</name>
<description>This is multi-module springboot project!</description>
<!-- 父模块的基本信息 -->
<parent>
<groupId>com.xz</groupId>
<artifactId>multimodule</artifactId>
<version>1.0</version>
</parent>
<!-- 配置Java版本 -->
<properties>
<java.version>1.8</java.version>
</properties>
<!-- 添加相关依赖 -->
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
- 在独立的dao模块中新建需要的package以及配置文件(父模块下的dao文件夹不用处理)

- 配置MySQ连接信息、druid以及mybatis连接信息
spring:
datasource:
# 配置MySQL基本连接信息
name: search
url: jdbc:mysql://localhost:3306/search?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=UTF-8
username: root
password: root
#配置druid连接池
driverClassName: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#下划线自动转驼峰
mybatis:
configuration:
map-underscore-to-camel-case: true
table:
auto: update
到此,dao模块配置完毕,在其他模块直接引用即可。
035 新建service模块,并引用dao模块
- 接下来,依照建立dao模块的方法建立处理公共业务方法的service模块,在service模块的配置文件中添加如下信息,引用dao模块
<!-- 子模块的基本信息 -->
<groupId>com.xz.multimodule</groupId>
<artifactId>service</artifactId>
<!-- 配置打包方式 -->
<packaging>pom</packaging>
<name>service</name>
<description>This is multi-module springboot project!</description>
<parent>
<groupId>com.xz</groupId>
<artifactId>multimodule</artifactId>
<version>1.0</version>
</parent>
<!-- 添加相关依赖 -->
<dependencies>
<!-- 引用dao模块 -->
<dependency>
<groupId>com.xz.multimodule</groupId>
<artifactId>dao</artifactId>
<version>1.0</version>
</dependency>
<!-- commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
036 新建面向用户的home模块,作为启动入口
- home模块的建立方法和其它子模块一样,除了配置home模块本身的信息,还需要引用dao模块和service模块,由于home是启动模块,需要引入web依赖,过程中我们使用了thymeleaf作为模板引擎,所以thymeleaf的依赖也一并引入
<dependencies>
<!-- 引入dao模块 -->
<dependency>
<groupId>com.xz.multimodule</groupId>
<artifactId>dao</artifactId>
<version>1.0</version>
</dependency
<!-- 引入service模块 -->>
<dependency>
<groupId>com.xz.multimodule</groupId>
<artifactId>service</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
- 接下来就是给home模块建立必要的package以及文件夹,如下所示

由于我们使用了mybatis,可以在启动类中统一配置MapperScan的扫描路径,相当于在该路径下每个类上都添加了@Mapper注解,如果MapperScan的扫描路径有多个,则添加{}后,各路径间用逗号隔开。
@SpringBootApplication
@MapperScan({"com.xz.dao.base.mysql.repo","com.xz.dao.base.es.repo"})
public class HomeApplication {
public static void main(String[] args) {
SpringApplication.run(HomeApplication.class, args);
}
}
037 启动SpringBoot
第一次启动该项目时,会提示如下内容,提示配置的数据源无效
Failed to configure a DataSource: 'url' attribute ...
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby)...
If you have database settings to be loaded from a ....
你是否会感到疑惑呢,明明在dao模块配置了数据源,并且home模块也引入了dao模块的依赖,为何数据源无效?到此,你应该想到,当SpringBoot中有多个配置文件时,可以再启动入口的配置文件中配置激活哪一个配置文件:
#home模块的application.yml配置文件中添加如下配置
spring:
profiles:
active: dev
再次启动,还是会遇到相同的错误提示,难道我们的配置文件写错了吗?其实你不用疑惑,spring.profiles.active不生效的原因是dao模块和home模块的配置文件重名了,spring.profiles.active=dev激活的是home模块下的配置文件,并没有激活dao模块的配置文件。
此时,将dao模块下的配置文件改为application-dao_dev.yml,用spring.profiles.active=dao_dev即可激活dao中的配置文件,再次启动即可。
spring:
profiles:
active: dev,dao_dev
038 项目打包
项目打包前,需要在父模块和启动模块中配置打包信息,
- 打开父模块pom文件,新增如下配置信息
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<!--跳过单元测试 -->
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
在home模块的pom.xml中配置启动类入口
<build>
<finalName>home</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<fork>true</fork>
<executable>true</executable>
<nainClass>com.xz.multimodule.home.HomeApplication</nainClass>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
最后进入命令行界面,切换到该项目的根目录
#打包命令
mvn clean package
#在home模块的target目录下找到打包形成的jar文件
#启动jar文件
java -jar home.jar
04 总结
上文中介绍了什么是多模块应用,如何构建多模块应用,以及多模块应用的坑点,大家在实战的过程中要注意如下两点
- 父工程中也可以看到子模块的目录,配置文件等,但父工程中仅起到管理模块的作用,不要通过父工程为子模块新建package或者书写子模块代码。
- 多个配置文件重名时,有必要改名,并在启动模块的application.yml中通过后缀激活。
网友评论