1. 搭建準(zhǔn)備&使用場景
- IDE: InteliJ IDEA
- JDK: 1.8
- SpringBoot: 2.0.3.RELEASE
- 使用場景: 中小型項(xiàng)目, API 和后臺管理 分開部署
2. 模塊說明

- config: 配置中心模塊
- bizz-support: 業(yè)務(wù)支持模塊, 存放根據(jù)表生成的通用 Service, Mapper
- framework-support: 框架支持模塊
- api: API 接口模塊
- manage: 后臺管理模塊
3. 模塊搭建
3.1 parent
- 使用 IDEA 或者 官網(wǎng)的 Spring initializr創(chuàng)建一個空項(xiàng)目multi-module-springboot, 刪除多余文件.
- pom.xml 中將 packaging 改成 pom 提供 依賴版本管理
- <dependencies> 標(biāo)簽外面嵌套一層 <dependencyManagement>
- 刪除 <build>
3.2 api
1. Spring initializr 創(chuàng)建一個項(xiàng)目, 父模塊引入 spring-boot-starter-web, api 對應(yīng)配置
且設(shè)置父模塊為multi-module-springboot
2. 新建 Controller
@RestController
@RequestMapping("/api")
public class HelloRestfulController {
@GetMapping({"/", "index", "index.html"})
public Map adminIndex() throws Exception {
return new HashMap(3) {{
put("code", 0);
put("message", "成功");
put("data", "Hello World!");
}};
}
3. 測試完成
$ curl http://localhost:8766/api/
{"message":"成功","data":"Hello World!","code":0}
3.3 manage
1. 如創(chuàng)建 3.2 api 模塊一樣創(chuàng)建 manage 模塊
2. 添加 thymeleaf 依賴
<springboot.version>2.0.3.RELEASE</springboot.version>
<nekohtml.version>1.9.22</nekohtml.version>
<thymeleaflayout.version>2.3.0</thymeleaflayout.version>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<!--<editor-fold desc="THYMELEAF 頁面模板引擎">-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>${springboot.version}</version>
<!-- 排除掉默認(rèn)的版本 -->
<exclusions>
<exclusion>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
</exclusion>
<exclusion>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>${nekohtml.version}</version>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
<version>${thymeleaflayout.version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>${thymeleaf.version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf.version}</version>
</dependency>
<!--</editor-fold>-->
3. resources 下面新建 templates/home.html
4. application.properties 配置 thymeleaf
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
5. 新建 Controller
package com.logictech.manage;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author JG.Hannibal
* @since 2018/7/4 14:25
*/
@Controller
public class HelloViewController {
@GetMapping({"/hello"})
public String adminIndex(ModelMap model) throws Exception {
model.addAttribute("text", "Hello World!");
return "home";
}
}
6. 測試完成
$ curl http://localhost:8765/hello
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>Hello World!</div>
<div>Hello World!</div>
</body>
</html>
3.4 config
1. 工程右鍵, 新建 Maven 子模塊 config (該次不是Spring initializr), 因?yàn)樵摴こ套鳛?resources root, 所以將除了pom.xml 的文件全部刪除.
2. 新建 profile 文件夾, 便于不同環(huán)境的發(fā)布部署
cd config
vi src/main/resources/dev/application.properties src/main/resources/prod/application.properties src/main/resources/test/application.properties
3. 每個application中加入配置內(nèi)容
#每個配置文件自己的 profile, 例: env=dev
env=*
#這邊端口每個配置文件不一樣就可以
server.port=876*
# 之前配置的模板引擎的配置一致
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
該版本對其他編輯器支持度太差,優(yōu)化為由Maven實(shí)現(xiàn)該功能。詳細(xì)見4.
4. IDEA設(shè)置為 resources root

4.使用 maven-remote-resources-plugin 進(jìn)行Maven的配置文件模塊分離
4.1 config模塊內(nèi)pom.xml添加 maven-remote-resources-plugin 插件,配置如下:
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.7.0</version>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*.properties</include>
<include>**/*.yml</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
在config目錄下執(zhí)行命令mvn clean package,見編譯后的文件是否有/classes/META-INF/maven/remote-resources.xml,有則添加插件成功。最終編譯目錄如下:
├── classes
│ ├── META-INF
│ │ └── maven
│ │ └── remote-resources.xml
│ ├── dev
│ │ ├── application.properties
│ │ ├── log4j2.yml
│ │ └── message
│ │ └── messages.properties
│ ├── prod
│ │ ├── application.properties
│ │ ├── log4j2.yml
│ │ └── message
│ │ └── messages.properties
│ └── test
│ ├── application.properties
│ ├── log4j2.yml
│ └── message
│ └── messages.properties
4.2 api、manage 模塊進(jìn)行 遠(yuǎn)程配置模塊 消費(fèi)的配置,在對應(yīng)模塊下pom.xml添加以下內(nèi)容,resourceBundle 的值為你的config包的groupId:artifactId:version(應(yīng)該不會有人把我寫的老老實(shí)實(shí)填進(jìn)去吧...)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.7.0</version>
<configuration>
<resourceBundles>
<resourceBundle>com.logictech:config:${project.version}</resourceBundle>
</resourceBundles>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
隨后,還是走一步測一步 mvn clean package,見編譯后目錄,若含有maven-shared-archive-resources 目錄則添加插件成功,然后查看classes目錄,也可以看見 config下的resources也添加進(jìn)來了。結(jié)果如下圖
/Users/JG.Hannibal/Projects/multi-module-springboot/manage/target
├── classes
│ ├── dev
│ │ ├── application.properties
│ │ ├── log4j2.yml
│ │ └── message
│ ├── prod
│ │ ├── application.properties
│ │ ├── log4j2.yml
│ │ └── message
│ ├── templates
│ │ └── home.html
│ └── test
│ ├── application.properties
│ ├── log4j2.yml
│ └── message
這邊存在一個問題,springboot 默認(rèn)是使用classpath下面路徑下的配置文件的,這邊比標(biāo)準(zhǔn)工程多了一級${profile},這邊處理方案很多,不認(rèn)為我的方案為最佳方案,所以這里還是存疑,歡迎討論建議,有最終答案后會再更新文章!
5. 測試, 將 api 工程中resources/application.properties 刪除, 依賴引入 config, 改寫 Controller, 將 env 打印出來.
@RestController
@RequestMapping("/api")
public class HelloRestfulController {
@Value("${env}")
private String env;
@GetMapping({"/", "index", "index.html"})
public Map adminIndex() throws Exception {
return new HashMap(3) {{
put("code", 0);
put("message", "成功");
put("data", "This Active Profile is: [" + env + "]");
}};
}
}
6. 修改啟動環(huán)境變量, 將 config 路徑配置到我們的子模塊內(nèi),測試完成.
java -jar api-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
--spring.config.location=classpath:${spring.profiles.active}/
$ curl http://localhost:8765/api/
{"message":"成功","data":"This Active Profile is: [dev]","code":0}
manage 模塊的改造和 api 一致
存在一個問題, 即 運(yùn)行 api 模塊時, Maven 找不到 config-0.0.1-SNAPSHOT.jar
只需要到 Maven 界面, 將 Nexus的勾選去掉即可.
3.5 framework-support
1. 新建 Maven 子模塊 framework-support, 添加spring-boot-starter-web依賴, config 依賴
這邊我們先實(shí)現(xiàn) Controller 的一個 AOP, 所以引入spring-aop 包括AspectJ
<!--<editor-fold desc="AOP">-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!--</editor-fold>-->
2. 編寫 ControllerLoggerAop
3. 將 framework-support 的包 添加 到 API 的主函數(shù)ComponentScan 里去, API 添加 framework-support依賴.
4. 測試完成
$ curl http://localhost:8766/api/
{"message":"成功","data":"This Active Profile is: [prod]","code":0}
##########| URL : http://localhost:8766/api/
##########| HTTP_METHOD : GET
##########| IP : 127.0.0.1
##########| CLASS_METHOD : com.logictech.api.HelloRestfulController.adminIndex
##########| ARGS : []
====================================================
##########| RESPONSE : {message=成功, data=This Active Profile is: [prod], code=0}
====================================================
3.6 bizz-support
1. 創(chuàng)建Maven子模塊 bizz-support, 根據(jù)需要創(chuàng)建依賴
2. 創(chuàng)建 CommonConst
public class CommonConst {
public static final String PROJECT_NAME = "MULTI_MODULE_SPRING_BOOT";
}
3. api 模塊改寫 Controller, 測試完成
@RestController
@RequestMapping("/api")
public class HelloRestfulController {
@Value("${env}")
private String env;
@GetMapping({"/", "index", "index.html"})
public Map adminIndex() throws Exception {
return new HashMap(3) {{
put("code", 0);
put("message", "成功");
put("data", "This Active Profile is: [" + env + "], Project Name: [" + PROJECT_NAME + "]");
}};
}
}
$ curl http://localhost:8766/api/
{"message":"成功","data":"This Active Profile is: [prod], Project Name: [MULTI_MODULE_SPRING_BOOT]","code":0}
4. 總結(jié)

還是就最開始那張圖來講, 該工程分為大體分為三塊:
- config: 配置中心, 可供后期改造成分布式的配置中心
- support: 支持中心, 核心模塊, framework-support 和 bizz-support 其實(shí)可以放一起
但是更清晰一點(diǎn),后期可以把 bizz-support 改造成 rbc服務(wù). - business: 業(yè)務(wù)模塊, 展現(xiàn)層
相同的層級的配置可以類比配置.
另外, 寫得沒有面面俱到, 多模塊工程V0.0.1版本, 后期會繼續(xù)完善.