关于版本选择:JDK(1.8)、SpringBoot(2.6.3)、MyBatis-Spring-Boot(2.2.2)、Maven(3.9.6)
新建Spring Boot多模块工程
模块设计
Spring Boot各模块及模块设计如下:
cnc-test-start :启动配置、web相关入口
cnc-test-common:通用类功能,日志处理、异常、通用工具等。
cnc-test-persistence:数据库持久化相关
cnc-test-service:业务逻辑部分
为什么要设计这么多模块:
1、方便代码组织,提高代码可读性,企业级服务代码量一般都不会少,试想如果整个代码放在一起,查找起来是不是很不方便,分层后先判断要查找的代码再哪一层,就大大减少了查找成本。
2、方便管理maven依赖,父工程中管理公共依赖,每一层管理各自的依赖,减少重复依赖及依赖版本不统一等各种问题。
依赖关系,默认上层依赖下层:

- Web 端:前端部分,所有业务请求均由前端发起,前端请求后端返回业务数据进行页面渲染。
- 开放API:对外提供的开放接口,根据业务需要决定是否需要该层。
- Start(Web层):主要是Web端请求入口,接收请求数据并返回响应数据,各类请求参数校验,或者不复用的业务简单处理等。
- Service 层:相对具体的业务逻辑服务层。
- Persistence 层:数据访问层,与底层 MySQL进行数据交互。
- Common层:整个系统公共的部分,比如全局异常处理、登录鉴权、业务日志打印、通用工具封装等等都放在该层。
- 第三方服务:包括与其他服务的集成(根据需要)。
- 外部数据接口:外部(应用)数据存储服务提供的接口(根据需要)。
- 数据库存储系统:存储业务数据的数据库,如MySQL等。
通过Maven创建各模块
1、新建父工程
打开IDEA,新建工程,按如下配置,注意1处的地址需要修改下,不然选择不了Java8,Name、Group、Artifact可自行命名:

Spring Boot 没有2.6.3的版本可供选择,可以先选择2.6.13的,后面在代码里再改为2.6.3的:

由于这是个父级工程,具体代码都在每个子模块中写,所以可以将src文件夹删除,HELP.md改为README.md,最终的目录格式如下:

整理pom.xml,最终如下:
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 将spring boot版本改为2.6.3 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 父项目的坐标,如果子项目没有规定某个坐标的值如version,则父项目的值即为其的值 -->
<groupId>com.cxzx</groupId>
<artifactId>cnc-test</artifactId>
<version>${cncproject.version}</version>
<name>cnc-test</name>
<description>cnc-test</description>
<!-- 打包方式 -->
<packaging>pom</packaging>
<!-- 子模块管理 -->
<modules>
</modules>
<!-- 统一版本号 可以理解为父项目及其子项目的公共变量 -->
<properties>
<cncproject.version>0.0.1-SNAPSHOT</cncproject.version>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<!-- 统一依赖定义 定义整个项目依赖的版本,子工程中需要使用,直接引用不用带版本号,解决不同子工程引入
相同依赖而版本号定义的不同的问题-->
<dependencyManagement>
</dependencyManagement>
<build>
<!-- 统一插件、jar包构建等相关 -->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
</excludes>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- maven仓库改为阿里云的提供下载速度 -->
<repositories>
<repository>
<id>aliyunmaven</id>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
</project>
2、创建子模块(common层)
工程名上右键:

按如下配置:

删掉无关文件,最终目录结构如下,注意把CncTestCommonApplication.java删掉(启动相关类及配置在start层),test文件夹也要删掉,一般企业应用都要求快速迭代,所以很少写单元测试:
整理pom.xml,最终如下:
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test</artifactId>
<version>${cncproject.version}</version>
</parent>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-common</artifactId>
<name>cnc-test-common</name>
<description>cnc-test-common</description>
<dependencies>
</dependencies>
</project>
3、创建子模块(persistence层)

删除无用文件:

整理pom.xml最终如下:
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test</artifactId>
<version>${cncproject.version}</version>
</parent>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-persistence</artifactId>
<name>cnc-test-persistence</name>
<description>cnc-test-persistence</description>
<dependencies>
</dependencies>
</project>
4、新建子模块(service层)
新建:

删除无用文件:

整理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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test</artifactId>
<version>${cncproject.version}</version>
</parent>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-service</artifactId>
<name>cnc-test-service</name>
<description>cnc-test-service</description>
</project>
5、新建子模块(starter层)

勾选Spring Web:

整理文件结构:

整理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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test</artifactId>
<version>${cncproject.version}</version>
</parent>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-start</artifactId>
<name>cnc-test-start</name>
<description>cnc-test-start</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
6、梳理个层间的依赖
父工程中定义各个模块信息:
xml
<!-- ........ 省略 -->
<!-- 子模块管理 -->
<modules>
<module>cnc-test-start</module>
<module>cnc-test-common</module>
<module>cnc-test-persistence</module>
<module>cnc-test-service</module>
</modules>
<!-- ........ 省略 -->
<!-- 统一依赖定义 定义整个项目依赖的版本,子工程中需要使用,直接引用不用带版本号,解决不同子工程引入
相同依赖而版本号定义的不同的问题-->
<dependencyManagement>
<dependencies>
<!-- ........ 省略 -->
<!-- 定义内部模块 -->
<dependency>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-common</artifactId>
<version>${cncproject.version}</version>
</dependency>
<dependency>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-starter</artifactId>
<version>${cncproject.version}</version>
</dependency>
<dependency>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-persistence</artifactId>
<version>${cncproject.version}</version>
</dependency>
<dependency>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-service</artifactId>
<version>${cncproject.version}</version>
</dependency>
<!-- ........ 省略 -->
</dependencies>
</dependencyManagement>
<!-- ........ 省略 -->
start层引入common和service依赖:
xml
<!-- ........ 省略 -->
<dependencies>
<dependency>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-common</artifactId>
</dependency>
<dependency>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-service</artifactId>
</dependency>
<!-- ........ 省略 -->
</dependencies>
<!-- ........ 省略 -->
service层引入common和persistence依赖:
xml
<!-- ........ 省略 -->
<dependencies>
<dependency>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-common</artifactId>
</dependency>
<dependency>
<groupId>com.cxzx</groupId>
<artifactId>cnc-test-persistence</artifactId>
</dependency>
<!-- ........ 省略 -->
</dependencies>
<!-- ........ 省略 -->
5、启动工程:
先执行1处的reload project

打开CncTestStartApplication 启动工程,Console打印如下信息说明启动成功:

Spring Boot多环境配置
开发Spring Boot应用时,根据软件开发的不同周期,代码会被部署到不同的环境上,比如开发测试环境、预发环境、生产环境,每个环境的数据库地址、服务器端口等配置信息是不一样的,如果在不同的环境打包时都要频繁的修改配置,必将非常繁琐且容易出错。Spring Boot提供的解决思路是提供多种配置文件,启动时通过指定参数来决定读取哪份配置。
在Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识,比如:
application.properties:默认配置
application-dev.properties:开发环境
application-pre.properties:开发环境
application-prod.properties:生产环境
因此,我们也在start层下新建多种配置文件:

具体加载哪个配置,可以在application.properties文件中通过spring.profiles.active属性来设置,其值对应{profile}值:

最终部署时可以通过jar启动参数:-Dspring-boot.run.profiles=prod指定。
集成swagger调式页面
前后端分离架构中,前端后端独立开发,后端开发中对于接口是否正常运行需要调试。Swagger是一款RESTFUL接口的文档在线自动生成+功能测试功能软件。Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。而Knife4j是基于swagger做了增强,可以比swagger更友好的显示接口文档。
1、父pom中定义Knife4j版本
xml
<!-- ........ 省略 -->
<!-- 统一版本号 可以理解为父项目及其子项目的公共变量 -->
<properties>
<!-- ........ 省略 -->
<knife4j.version>4.3.0</knife4j.version>
</properties>
<!-- 统一依赖定义 定义整个项目依赖的版本,子工程中需要使用,直接引用不用带版本号,解决不同子工程引入
相同依赖而版本号定义的不同的问题-->
<dependencyManagement>
<dependencies>
<!-- knife4j(API 文档工具) -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- ........ 省略 -->
swagger调式页面属于公共功能,所以放到了common层。
2、start层中定义bean扫描路径
CncTestStartApplication.java中加入注解:@ComponentScan({"com.cxzx.cnctest.*"})

2、common层开发代码
common层的pom中引入依赖:
xml
<!-- ........ 省略 -->
<dependencies>
<!-- knife4j(API 文档工具) -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<!-- ........ 省略 -->
新建config目录:


config包下新建Knife4jConfig类:

完整代码如下:
kotlin
package com.cxzx.cnctest.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
/**
* @author 某角落的IT打杂工
* @version 1.0
* @description: TODO
* @date 2024/4/22 21:19
*/
@Configuration
@EnableSwagger2WebMvc
@Profile("dev")
public class Knife4jConfig {
@Bean("webApi")
public Docket createApiDoc() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(buildApiInfo())
// 分组名称
.groupName("分组1接口文档")
.select()
// 这里指定 Controller 扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.cxzx.cnctest.start"))
.paths(PathSelectors.any())
.build();
return docket;
}
/**
* 构建 API 信息
* @return ApiInfo
*/
private ApiInfo buildApiInfo() {
return new ApiInfoBuilder()
.title("企业级服务-demon测试接口文档") // 标题
.description("企业级服务-demon测试接口文档") // 描述
.termsOfServiceUrl(" ") // API 服务条款
.contact(new Contact("某角落的IT打杂工", " ", "[email protected]")) // 联系人
.version("1.0") // 版本号
.build();
}
}
@Profile("dev") 注解用于标明仅开发环境开启。
重新启动工程:

出现如下信息说明启动成功:

浏览器打开http://localhost:8080/doc.html:
具体如何调式,后面开发接口时再进行说明。