您的位置:首页 > 编程语言 > Java开发

SpringBoot+maven聚合项目创建与打包部署的完整流程

2022-02-24 15:28 501 查看

1、旧工程改造

1.1 sc-common 中 pom.xml 改造:

1 删掉 pom.xml 中的父模块,把 sc-common 做为父模块
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
&lt;!&ndash; lookup parent from repository &ndash;&gt;
<relativePath/>
</parent>
2 删掉 pom.xml 中的打包插件
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
3 新增打包插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>

$ 为 1.8

4 完整的 build 内容
<!--打 jar 包-->
<build>
<plugins>
<!-- maven聚合项目父工程必须要引用的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin><!--跳过 test,因为 nacos yaml 文件中的的中文打包 test 会报错-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
5 完整的 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的。
这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。 -->
<modelVersion>4.0.0</modelVersion>
<!--项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。-->
<groupId>com.dt.cloud</groupId>
<!-- 构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID。
在某个特定的group ID下,artifact ID也必须是唯一的。-->
<artifactId>sc-common</artifactId>
<!--项目当前版本,格式为:主版本.次版本.增量版本-限定版本号 -->
<version>0.0.1-SNAPSHOT</version>
<!--项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型 -->
<packaging>pom</packaging><!--项目的名称, Maven产生的文档用 -->
<name>sc-common</name>
<!-- 项目的详细描述-->
<description>点通软件的基础模块</description>

<!-- 需要引入的子模块 -->
<modules>
<!-- 启动模块(必须) -->
<module>sc-start</module>
<!-- 初始化模块(必须) -->
<module>sc-initialize</module>
<!-- 密码校验模块 -->
<module>password-check</module>
<!-- 登录认证模块 -->
<module>sc-auth</module>
<!-- 点通有数模块 -->
<module>sc-data-presented</module>
</modules>
<!--项目开发者属性,目前用来做版本声明 -->
<properties>
<!--点通 sc-common 版本 -->
<dt.version>0.0.1-SNAPSHOT</dt.version>
<!-- springboot 版本 -->
<spring-boot.version>2.5.3</spring-boot.version>
<!-- springcloud 版本 -->
<spring-cloud.version>2020.0.3</spring-cloud.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<!-- jdk 版本 -->
<java.version>1.8</java.version>
<!-- 阿里巴巴 fastjson 版本 -->
<fastjson.version>1.2.75</fastjson.version>
<!-- swagger 相关 版本 -->
<springfox-swagger2.version>2.6.1</springfox-swagger2.version>
<springfox-swagger-ui.version>2.6.1</springfox-swagger-ui.version>
<springfox-swagger3.version>3.0.0</springfox-swagger3.version>
<swagger3.version>2.0.0.RELEASE</swagger3.version>
<!-- knife4j 版本 -->
<knife4j.version>3.0.2</knife4j.version>
<!-- 数据库连接池 版本 -->
<druid.version>1.1.22</druid.version>
<!-- 数据库 版本 -->
<mysql.version>8.0.20</mysql.version>
<!-- mybatis-plus相关 版本 -->
<mybatis-plus.version>3.3.2</mybatis-plus.version>
<mybatis-plus-extension.version>3.4.0</mybatis-plus-extension.version>
<!-- junit 单元测试 版本 -->
<junit-test.version>4.12</junit-test.version>
<!-- lombok 版本 -->
<lombok.version>1.18.2</lombok.version>
<!-- nacos 版本 -->
<nacos.version>2.1.2.RELEASE</nacos.version>
<!-- freemarker 版本 -->
<freemarker.version>2.3.30</freemarker.version>
</properties>

<!-- 继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,而是当子项目声明一个依赖(必须描述group ID和 artifact
ID信息),如果group ID和artifact ID以外的一些信息没有描述,则通过group ID和artifact ID 匹配到这里的依赖,并使用这里的依赖信息。-->
<dependencyManagement>
<!--该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。-->
<dependencies>

<!-- SpringBoot的依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${nacos.version}</version>
</dependency>
<!-- 配置中心支持 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${nacos.version}</version>
</dependency>

<!-- mybatis-plus 增强CRUD -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- mybatis-plus-extension 分页插件 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>${mybatis-plus-extension.version}</version>
</dependency>

<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>

<!--swagger3-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox-swagger3.version}</version>
</dependency>
<!--由于使用Swagger,这俩个jar包版本过低,现升级为2.0-->
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
<version>${swagger3.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-metadata</artifactId>
<version>${swagger3.version}</version>
</dependency>
<!-- Knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>

<!--lombok 是一个工具类库,可以用简单的注解形式来简化代码。-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>

<!--freemarker-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-test.version}</version>
<scope>test</scope>
</dependency>

<!-- 校验密码模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>password-check</artifactId>
<version>${dt.version}</version>
</dependency>

<!-- 点通有数模块 -->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-data-presented</artifactId>
<version>${dt.version}</version>
</dependency>

<!-- 登录认证模块 -->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-auth</artifactId>
<version>${dt.version}</version>
</dependency>

<!-- 初始化模块 -->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-initialize</artifactId>
<version>${dt.version}</version>
</dependency>

</dependencies>
</dependencyManagement>

<!--打 jar 包-->
<build>
<plugins>
<!-- maven聚合项目父工程必须要引用的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>

<!--跳过 test,因为 nacos yaml 文件中的的中文打包 test 会报错-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>

</build>

</project>

1.2 sc-common 中 pom.xml 内容介绍

1 packaging

pom.xml 中有一些特殊的地方需要介绍一下。

作为顶级父类,打包方式一定是 pom,其他子项目不写默认是 jar

<!--项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型 -->
<packaging>pom</packaging>
2 modules

作为顶级父类,要把所有子模块引入,其中启动模块: sc-start 和 初始化模块: sc-initialize 是启动项目时必须要有的,其他业务模块根据需要引入,建议全部业务模块都引入,不会影响后续打包操作。

<!-- 需要引入的子模块 -->
<modules>
<!-- 启动模块(必须) -->
<module>sc-start</module>
<!-- 初始化模块(必须) -->
<module>sc-initialize</module>
<!-- 密码校验模块 -->
<module>password-check</module>
<!-- 登录认证模块 -->
<module>sc-auth</module>
<!-- 点通有数模块 -->
<module>sc-data-presented</module>
</modules>
3 dependencyManagement & dependencies

**dependencyManagement:**只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

<dependencyManagement> ... </dependencyManagement>

**dependencies:**是依赖传递,即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)

**注:**依赖声明和依赖传递是不一样的,顶级父类 sc-conmon 中的 pom 只是做一个依赖声明。依赖传递的话,是通过初始化模块 sc-initialize :这里引用一堆的外部包,然后其它项目就引用,就能做到依赖传递。

你可以将自己项目需要用到的所有包或者公共的包都统一管理在 sc-initialize 的 pom.xml 中。

<dependencies>....</dependencies>

总结:

如果父pom中使用的是

<dependencyManagement>
<dependencies>....</dependencies></dependencyManagement>

的方式,则子pom不会自动使用父pom中的jar包,这时如果子pom想使用的话,就要给出groupId和artifactId,无需给出version。

如果父pom中使用的是

<dependencies>....</dependencies>

的方式,则子pom,或者其他依赖的项目会自动使用pom中的jar包。

2、新项目创建

2.1 创建Maven多模块项目

整体模块如下:

1 创建父工程模块

先建立外层父工程 sc-common : File →new →project 选择 Spring Initializr → Next下一步到以下页面填写父工程信息

接下来就是一直 Next 到项目创建完成

工程结构如下,记得配置自己的 maven 相关地址:

接下来,把src整个删掉,父工程不需要,因为父工程你就当它只有一个外壳就完了,然后在把完整的 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的。
这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。 -->
<modelVersion>4.0.0</modelVersion>
<!--项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。-->
<groupId>com.dt.cloud</groupId>
<!-- 构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID。
在某个特定的group ID下,artifact ID也必须是唯一的。-->
<artifactId>sc-common</artifactId>
<!--项目当前版本,格式为:主版本.次版本.增量版本-限定版本号 -->
<version>0.0.1-SNAPSHOT</version>
<!--项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型 -->
<packaging>pom</packaging><!--项目的名称, Maven产生的文档用 -->
<name>sc-common</name>
<!-- 项目的详细描述-->
<description>点通软件的基础模块</description>

<!-- 需要引入的子模块 -->
<modules>
<!-- 启动模块(必须) -->
<module>sc-start</module>
<!-- 初始化模块(必须) -->
<module>sc-initialize</module>
<!-- 密码校验模块 -->
<module>password-check</module>
<!-- 登录认证模块 -->
<module>sc-auth</module>
<!-- 点通有数模块 -->
<module>sc-data-presented</module>
</modules>
<!--项目开发者属性,目前用来做版本声明 -->
<properties>
<!--点通 sc-common 版本 -->
<dt.version>0.0.1-SNAPSHOT</dt.version>
<!-- springboot 版本 -->
<spring-boot.version>2.5.3</spring-boot.version>
<!-- spring-cloud 版本 -->
<spring-cloud.version>2020.0.3</spring-cloud.version>
<!-- spring-security 版本 -->
<spring-security.version>5.5.3</spring-security.version>
<!-- jwt 版本 -->
<jwt.version>0.9.1</jwt.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<!-- jdk 版本 -->
<java.version>1.8</java.version>
<!-- 阿里巴巴 fastjson 版本 -->
<fastjson.version>1.2.75</fastjson.version>
<!-- 阿里巴巴 easyexcel 版本 -->
<easyexcel.version>2.1.6</easyexcel.version>
<!-- swagger 相关 版本 -->
<springfox-swagger2.version>2.6.1</springfox-swagger2.version>
<springfox-swagger-ui.version>2.6.1</springfox-swagger-ui.version>
<springfox-swagger3.version>3.0.0</springfox-swagger3.version>
<swagger3.version>2.0.0.RELEASE</swagger3.version>
<!-- knife4j 版本 -->
<knife4j.version>3.0.2</knife4j.version>
<!-- 数据库连接池 版本 -->
<druid.version>1.1.22</druid.version>
<!-- 数据库 版本 -->
<mysql.version>8.0.20</mysql.version>
<!-- mybatis-plus相关 版本 -->
<mybatis-plus.version>3.3.2</mybatis-plus.version>
<mybatis-plus-extension.version>3.4.0</mybatis-plus-extension.version>
<!-- junit 单元测试 版本 -->
<junit-test.version>2.5.3</junit-test.version>
<!-- lombok 版本 -->
<lombok.version>1.18.2</lombok.version>
<!-- nacos 版本 -->
<nacos.version>2.1.2.RELEASE</nacos.version>
<!-- freemarker 版本 -->
<freemarker.version>2.3.30</freemarker.version>
<!-- redis 版本 -->
<redis.version>2.5.6</redis.version>
<!-- jedis 版本 -->
<jedis.version>3.6.3</jedis.version>
<!-- apache http连接池 httpclient -->
<httpclient.version>4.5.13</httpclient.version>
<jackson-databind.version>2.12.4</jackson-databind.version>
</properties>

<!-- 继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,而是当子项目声明一个依赖(必须描述group ID和 artifact
ID信息),如果group ID和artifact ID以外的一些信息没有描述,则通过group ID和artifact ID 匹配到这里的依赖,并使用这里的依赖信息。-->
<dependencyManagement>
<!--该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。-->
<dependencies>

<!-- SpringBoot的依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${nacos.version}</version>
</dependency>
<!-- 配置中心支持 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${nacos.version}</version>
</dependency>
<!-- springsecurity -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>
<!-- jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>

<!-- mybatis-plus 增强CRUD -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- mybatis-plus-extension 分页插件 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>${mybatis-plus-extension.version}</version>
</dependency>

<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 阿里操作 excel 的 easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>

<!--swagger3-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox-swagger3.version}</version>
</dependency>
<!--由于使用Swagger,这俩个jar包版本过低,现升级为2.0-->
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
<version>${swagger3.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-metadata</artifactId>
<version>${swagger3.version}</version>
</dependency>
<!-- Knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>

<!--lombok 是一个工具类库,可以用简单的注解形式来简化代码。-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>

<!--freemarker-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>${junit-test.version}</version>
<scope>test</scope>
</dependency>

<!-- redis-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${redis.version}</version>
</dependency>
<!-- java操作 redis 的 jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<!-- redis 序列化-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency>

<!-- apache http连接池 httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>

<!-- 校验密码模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>password-check</artifactId>
<version>${dt.version}</version>
</dependency>

<!-- 点通有数模块 -->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-data-presented</artifactId>
<version>${dt.version}</version>
</dependency>

<!-- 登录认证模块 -->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-auth</artifactId>
<version>${dt.version}</version>
</dependency>

<!-- 初始化模块 -->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-initialize</artifactId>
<version>${dt.version}</version>
</dependency>

</dependencies>
</dependencyManagement>

<!--打 jar 包-->
<build>
<plugins>
<!-- maven聚合项目父工程必须要引用的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>

<!--跳过 test,因为 nacos yaml 文件中的的中文打包 test 会报错-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>

</build>

</project>

因为这些子模块还没有创建,所以 pom.xml 中报错是正常的。接下来让我们开始创建子工程模块。

2 创建子模块
  1. 鼠标放在父工程上右键 → new → Module 选择Spring Initaializr 下一步填写子工程信息。

  2. 删除每个子模块中没用的文件,.mvn、.gitignore、daoiml、mvnw、mvnw.cmd文件只留下pom.xml

  3. 除了启动子模块 sc-start,其他子模块都要删除启动类和配置文件

  4. 子模块中的 test 文件夹需要删掉,因为这个模块没有任何业务,不需要单元测试

注:创建父工程是创建一个新的项目,子工程是在父工程上创建新的 Module。别搞错了哦!!!

2.1 启动模块:sc-start

**主要功能:**项目的启动入口,负责其他子模块的引用,项目的打包,项目的配置文件管理。

在启动模块 sc-start --->resource 中引入配置文件和日志文件:

bootstarp.yaml 内容如下:

# -----------启动参数-----------
server-addr: 192.168.124.63:9048
namespace: feature-sr05-island-test
group: service-cool
service-config: sc-password-check.yaml
common-config: sc-common.yaml
# -----------启动参数-----------
server:
address: 0.0.0.0
port: 9002
spring:
application:
name: sc-common #这里和项目名称对应
cloud:
nacos:
config:
server-addr: ${server-addr}
namespace: ${namespace}
# 服务特有配置文件
name: ${service-config}
group: ${group}
file-extension: yaml
shared-configs:
# common配置文件
- data-id: ${common-config}
group: ${group}
refresh: true
discovery:
namespace: ${namespace}
server-addr: ${server-addr}
group: ${group}
service: ${sc.app-name}-${spring.application.name}
loadbalancer:
retry:
enabled: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
url: ${business-database.url:jdbc:mysql://${business-database.host}:${business-database.port}/${business-database.database-name}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8}
username: ${business-database.username}
password: ${business-database.password}
driver-class-name: ${business-database.driver-class-name:com.mysql.cj.jdbc.Driver}
initial-size: 8
min-idle: 1
max-active: 20
max-wait: 60000
time-between-eviction-runsMillis: 60000
min-evictable-idle-timeMillis: 300000
validation-query: select 1 FROM DUAL
pool-prepared-statements: true
max-open-prepared-statements: 20
max-pool-prepared-statement-per-connection-size: 20
filters: stat
connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis: 5000
use-global-data-source-stat: true
# 邮箱配置
mail:
host: smtp.qq.com
username: 1046470145@qq.com
password: gemwiiyxydeebebc
default-encoding: UTF-8
port: 587
properties:
mail:
smtp:
auth: true
socketFactory:
class: javax.net.ssl.SSLSocketFactory
# redis 配置
redis:
database: 0
host: ${redis.host}
lettuce:
pool:
max-active: 8     #最大连接数据库连接数,设 0 为没有限制
max-idle: 8       #最大等待连接中的数量,设 0 为没有限制
max-wait: -1ms    #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制
min-idle: 0       #最小等待连接中的数量,设 0 为没有限制
shutdown-timeout: 100ms
password: ${redis.password}
port: ${redis.port}

config:
server-addr: ${server-addr}

mybatis:
mapper-locations=classpath: mapper/*Mapper.xml

feign:
hystrix:
enabled: false
httpclient:
enabled: true
okhttp:
enabled: false

hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 10000

ribbon:
ConnectTimeout: 50000
ReadTimeout: 50000
OkToRetryOnAllOperations: true
MaxAutoRetriesNextServer: 2
MaxAutoRetries: 1

management:
endpoints:
web:
exposure:
include: '*'

log:
path: logs
logging:
config: classpath:logback-spring.xml
level:
com:
alibaba:
nacos:
client:
naming: error
config:
impl:
ClientWorker: error
#file: /dev/stdout

local-config:
read:
timeout: 5000
debug:
mode: test
log:
mode: console
level: info

swagger:
enable: true
applicationName: sc-common
applicationDescription: 点通公用模块
applicationVersion: v1.0
tryHost: null

mybatis-plus:
configuration:
call-setters-on-nulls: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

# token配置
token:
# 令牌自定义标识
header: Authorization
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期(默认30分钟)
expireTime: 30

logback-spring.xml 内容如下:

<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod="60 seconds">
<contextName>logback</contextName>

<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
<!--日志存储路径-->
<property name="log.path" value="./logs" />

<!--输出到 部署 控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<!-- 时间 | 线程名 | 日志级别 | 类->方法名:行数 : 日志信息 -->
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %t | %highlight(%-5level) | %logger{50}->%M:%L : %msg%n</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>

<!--输出到 idea 控制台-->
<appender name="CONSOLE_DEV" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<!-- 时间 | 线程名 | 日志级别 | 类:行数| 日志信息 -->
<Pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} | %t | %highlight(%-5level) | \(%class{0}.java:%L\) | %msg%n</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>

<!--输出到文档-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${log.path}/info.log</file>
<!--日志文档输出格式-->
<encoder>
<!-- 时间 | 线程名 | 日志级别 | 类->方法名:行数 : 日志信息 -->
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %t | %-5level | %logger{50}->%M:%L : %msg%n</Pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/info/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>

<!--输出到warn日志到文档-->
<appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${log.path}/warn.log</file>
<!--日志文档输出格式-->
<encoder>
<!-- 时间 | 线程名 | 日志级别 | 类->方法名:行数 : 日志信息 -->
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %t | %-5level | %logger{50}->%M:%L : %msg%n</Pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>

<!--开发环境使用-->
<!--        <root level="info">-->
<!--            <appender-ref ref="CONSOLE_DEV" />-->
<!--            <appender-ref ref="FILE" />-->
<!--        </root>-->

<!--部署环境使用使用-->
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
<appender-ref ref="FILE_WARN" />
</root>

</configuration>

替换启动模块中的 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>
<artifactId>sc-common</artifactId>
<groupId>com.dt.cloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>sc-start</artifactId>
<name>start</name>
<description>sc-common 启动类</description>
<!-- 打包方式 -->
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 初始化模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-initialize</artifactId>
</dependency><!-- 校验密码模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>password-check</artifactId>
</dependency>

<!-- 点通有数模块 -->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-data-presented</artifactId>
</dependency>

<!-- 登录认证模块 -->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-auth</artifactId>
</dependency>

<!--SpringCloud 2.4版本 之后不再 优先读取bootstrap文件,导致bootstrap不起作用。
需要在pom.xml文件中引入如下依赖后,就可以正常读取bootstrap.yml配置文件了-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

</dependencies>

<build>
<plugins>

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>-->
</plugins>
<finalName>sc-common</finalName>
</build>

</project>

修改父工程为:

<parent>
<artifactId>sc-common</artifactId>
<groupId>com.dt.cloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>

启动模块打包方式:

<!-- 打包方式 -->
<packaging>jar</packaging>

启动依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

引入初始化模块(未创建,稍后创建):

<!-- 初始化模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-initialize</artifactId>
</dependency>

根据实际情况引入其他业务模块。这里引入哪个模块,就会在打包的时候带上哪个业务模块的代码,可以选择性组装功能。

加入 build 标签内容:

<build>
<plugins>

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>sc-common</finalName>
</build>

给启动加上对应注解:

@EnableDiscoveryClient
/**
* basePackages:指定要扫描的Mapper类的包的路径。
* 如果不通子模块下的 mapper 不在同一个路径下,需要配置多个路径
*/
@MapperScan(basePackages ={"com.dt.**.mapper"})
/**
* scanBasePackages: Spring扫描 @Controller,@Service,@Component,@Repository 等注解的基 础包路径
* 如果不通子模块的包路径不一致,需要配置多个路径,所以建议用统一路径:com.dt.cloud
* exclude: 排除此类的AutoConfig,即禁止 SpringBoot 自动注入数据源配置。
*/
@SpringBootApplication(scanBasePackages = {"com.dt.cloud"}, exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })

public class ScStartApplication {

public static void main(String[] args) {
SpringApplication.run(ScStartApplication.class, args);
}

}

到这里,启动模块就构建完毕了。

2.2 初始化模块:sc-initialize

主要功能:管理所有模块的公共依赖关系,初始化项目的所有 config 如Swagger,mybatisplus,等,初始化项目中所有公共变量,管理公共业务模块,数据库操作模块,bean ,工具类,返回值封装等。

一句话:所有公共的东西都能放这里统一管理,这样就不用每个子模块都实现一遍了。建议超过两个子模块引用的业务就放在这个初始化模块下。其他模块只需要引入 sc-initialize 即可获取他的功能及依赖

创建初始化模块 sc-initialize:

记得删除启动类和配置文件,然后创建对应的功能目录:

引入初始化的 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>
<artifactId>sc-common</artifactId>
<groupId>com.dt.cloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent><artifactId>sc-initialize</artifactId>

<!-- 打包方式 -->
<!--    <packaging>jar</packaging>-->
<description>点通启动类</description>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 配置中心支持 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

<!-- mybatis-plus 增强CRUD -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- Mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<!--swagger3-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox-swagger3.version}</version>
</dependency>
<!--由于使用Swagger,这俩个jar包版本过低,现升级为2.0-->
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-metadata</artifactId>
</dependency>
<!-- Knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>

<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.55</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<!-- jedis 连接池-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- redis 序列化-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-- springsecurity -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<!-- jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- RestTemplate 的 http 连接池-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>

</dependencies>

</project>

  1. 引入所有业务子模块

**注意:**这里第一个模块 (password-check) 需要启动类,其他模块是不需要启动类的,所以要把其他模块的启动类删掉。第一个模块作为启动类,他的 pom.xml 与其他模块也是不同,这个下面再说。

2.3 启动项目:看效果

到这一步,我们就可以把项目运行起来了

此时访问 swagger 文档地址:http://localhost:9003/doc.html ,可以看到,项目整合swagger完全没有问题了,接下来就整点业务子模块。

2.4 业务模块:password-check

重复上面的操作,创建业务子模块 password-check ,删掉多余的文件,得到干净的子模块目录如下:

修改 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>sc-common</artifactId>
<groupId>com.dt.cloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>password-check</artifactId>
<name>password-check</name>
<description>业务子模块 password-check </description>

<dependencies>
<!--引入初始化模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-initialize</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

</project>

接下来,把之前 password-check 模块也业务复制过来即可。由于 password-check 模块与其他模块有很多重复内容,我把它们都提取到初始化模块 sc-initialize 中作为公共内容了。最后的目录如下:

是不是很清爽,也就是说,以后我们写代码,只要基础环境搭建好了,我们就专心写业务代码就好了。在也不用担心模块兼容性,不同配置,不同工具类,不通返回值等等一大堆的问题,也不会出现一堆乱七八糟的依赖,每个模块下还是不同的版本,也不会出现每个模块的返回值不一样,日志配置不同,最后导致做模块整合的时候很痛苦了。

最后我们把需要的业务依赖导入到 pom.xml 中:

像 postgresql 这种数据库依赖,我们也可以考虑放到初始化模块 sc-initialize模块的 pom.xml 中统一管理,但是目前其他模块没有用到 postgresql ,所以就暂时放到 passward-check 业务模块的 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>sc-common</artifactId>
<groupId>com.dt.cloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>password-check</artifactId>
<name>password-check</name>

<description>业务子模块 password-check </description>

<dependencies>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.13</version>
</dependency>

<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.4.6</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-ecs</artifactId>
<version>4.17.6</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dyvmsapi</artifactId>
<version>1.2.2</version>
</dependency>

<!--spring boot actuator 监控组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

<!--Postgre-->
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!--引入初始化模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-initialize</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>

然后我们在重启项目,访问 swagger 看看效果。

可以看到,swagger 中已经成功显示了 password-check 模块中的内容。接下来把其他业务模块都创建出来。

2.4 业务模块:sc-data-presented

同理可得

2.6 业务模块:sc-auth

同理可得

sc-auth 中需要用到 sc-data-presented 模块的业务内容,所以除了引入初始化模块 sc-initialize 模块,还需要额外引入 sc-data-presented :

<!--点通初始化模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-initialize</artifactId>
</dependency>
<!--点通有数模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-data-presented</artifactId>
</dependency>

**注意:**每个模块都可以调用其他模块,但是两个模块之间不能互相调用,比如 sc-auth 中可以调用 sc-data-presented 中的业务,引入 sc-data-presented 依赖即可。但是此时要是 sc-data-presented 也引用 sc-auth 的业务,就会出现相互引用的死循环。解决办法是吧互相调用两方中任意一方的业务放到初始化模块 sc-initialize 中,这样就不会出现互相调用而造成的死循环了。

一句话概括:两个模块之间相互引用会出现依赖死循环

2.7 启动项目:看最终效果

完美,各个模块的功能接口都出来了。

3 整合 flyway

sc-common 引入依赖,进行版本管理

<!-- flyway 自动升级SQL脚本 -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>${flyway.version}</version>
</dependency>

<!-- flyway 版本 -->
<flyway.version>5.2.4</flyway.version>

初始化模块:sc-initialize pom.xml 引入 flyway 依赖

<!-- flyway 数据库脚本升级 -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>

启动模块 sc-start 加入 flyway 配置文件

# flyway 配置
flyway:
# 启用(true)或禁用(false) flyway
enabled: true
# flyway 的 clean 命令会删除指定 schema 下的所有 table, 生产务必禁掉。这个默认值是 false 理论上作为默认配置是不科学的。
clean-disabled: true
# SQL 脚本的目录,多个路径使用逗号分隔 默认值 classpath:db/migration
locations: classpath:db/migration
#  metadata 版本控制信息表 默认 flyway_schema_history
table: flyway_schema_history
# 如果没有 flyway_schema_history 这个 metadata 表, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令
# 设置为 true 后 flyway 将在需要 baseline 的时候, 自动执行一次 baseline。
baseline-on-migrate: true
# 指定 baseline 的版本号,默认值为 1, 低于该版本号的 SQL 文件, migrate 时会被忽略
baseline-version: 1
# 字符编码 默认 UTF-8
encoding: UTF-8
# 是否允许不按顺序迁移 开发建议 true  生产建议 false
out-of-order: false
# 需要 flyway 管控的 schema list,这里我们配置为 flyway.  缺省的话, 使用spring.datasource.url 配置的那个 schema,
# 可以指定多个schema, 但仅会在第一个schema下建立 metadata 表, 也仅在第一个schema应用migration sql 脚本.
# 但flyway Clean 命令会依次在这些schema下都执行一遍. 所以 确保生产 spring.flyway.clean-disabled 为 true
# 简单来说 schemas 就是指定在哪个数据库里面执行 sql 文件,这里可以指定多个,注释掉默认是取 bootstrap.yaml 中配置的数据库
# schemas: service_cool_dev_v1
# 执行迁移时是否自动调用验证   当你的 版本不符合逻辑 比如 你先执行了 DML 而没有 对应的DDL 会抛出异常
validate-on-migrate: true

每个业务模块创建 目录: db/migration 用来专门存放业务模块中的SQL。

命名规范:V 20220224.01__create_report.sql

解析:大写V + 年 + 月 + 日 + 点符合( . ) + 版本号(防止同一天有多个sql修改) + 两个下划线( __ ) + 描述(中文或者英文都行)

2.2 初始化模块功能说明

初始化公共模块为:sc-initialize 。里面存放的是一些公共功能,大家要多加熟悉,防止出现一个功能两份代码。

1 公共配置

目前公共配置如下,已有的公共配置,不允许睡意修改,业务模块直接使用相关功能即可。

//Redis使用 FastJson 序列化,防止中文出现乱码
FastJson2JsonRedisSerializer
//Mybatis Plus 配置
MybatisPlusConfig
//Mybatis Plus 对数据库每条记录的创建时间和更新时间自动进行填充
MyMetaObjectHandler
//redis 配置
RedisConfig
// RestTemplate配置,用于服务之间进行通信
RestTemplateConfig
//Swagger配置类 + 整合Knife4j
SwaggerConfig
2 公共常量

//用于启动类配置的常量
ConfigConstants
//系统处理返回网络请求状态码
HttpStatus
3、公共的 bean 实体类

基本上是对应我们数据表中的实体类,这样多个业务操作同一个表,就不用每次都去创建实体类了,后续还会加上更多的实体类。

// customer_company 表实体类
CustomerBean
// customer_preferences 表实体类
CustomerPreferences
// customer_User + customer_company 表实体类
CustomerUser
//queue 表实体类
Queue
// system_param_config 表实体类
SystemParamConfig
//服务人员+客户用户所有信息实体类
SysUser
//user_preferences 表实体类
UserPreferences
//user 表实体类
Users
// 登录用户身份权限信息
LoginUser
//分页返回值封装 bean
ResList
//返回值封装 bean
Result
//接口状态码枚举
StatusCodeEnum
//用户类型枚举
UserTypeEnum
4、公共业务功能功能

//customer_preferences 表的相关操作
CustomerPreferencesMapper
//根据客户用户id查询客户用户偏好
CustomerUserMapper
//queue 表的相关操作
QueueMapper
//根据服务人员ID查询权限&根据客户用户ID查询权限
SysMenuMapper
//system_param_config 表的相关操作
SystemParamConfigMapper
// user_preferences 表的相关操作
UserPreferencesMapper
// 根据服务人员id查询服务人员偏好
UsersMapper
5、公共工具类

//数据表 big 字段转换 为 int
BigIntegerConverter
//时间戳转换器
TimestampConverter
//异常相关工具类
execption
//spring工具类 方便在非spring管理环境中获取bean
SpringUtils
//使用Base64进行对字符串加解密
Base64Util
//excel导出工具类
ExcelUtil
//获取i18n资源文件,获取国际化翻译值
MessageUtils
//redis操作工具类
RedisCache
//Spring RestTemplate的请求方法工具类
RestTemplateUtil
//安全服务工具类
SecurityUtils
//字符串操作工具类
StringUtil

2.3 新建子模块注意事项

新建一个业务模块需处做哪些事情?

1、引入新建子模块

最外层的pom.xml中引入新建子模块

2、 sc-start 中加入配置文件

如果有配置,需要在 sc-start ---> bootstrap.yaml 中加入配置文件

3、注入依赖到sc-start

把自己注入到 sc-start 模块中,如果不需要打包,直接去掉依赖即可

4、引入初始化模块依赖

在新建业务子模块的 pom.xml 中引入初始化模块 sc-initialize 的依赖

<!-- 初始化模块-->
<dependency>
<groupId>com.dt.cloud</groupId>
<artifactId>sc-initialize</artifactId>
</dependency>
5、编写代码

到这里,就能愉快的编写代码了。对了,初始化模块中的公共功能别忘记使用哦!

常见问题

swagger 规范问题

项目引入 swagger 文档就是为了方便前端&后端&测试快速交互,这样只要定义好入参,返回值,就可以出接口文档,接下来前端后端及测试就可以并行去开发。如果大家没有按标准去使用 swagger 文档注解,这势必会回到手写文档的时代。而且还会引发后续一系列的问题,比如代码后期维护交接困难,没有问题的代码,只能进到业务文档里面去看实际效果。本地排查问题也全靠猜。所以为了方便大家的工作,开发的时候务必要话时间去打磨好这个 swagger 接口文档。

1、返回值 bean 中没有写 swagger注解,如下:

正确的写法如下:

每个入参 bean 都需要配上相对应的注解描述

@ApiModel
@ApiModelProperty

2、返回值 bean 的嵌套类型没有写相关注解,导致嵌套类型解析不出来,如下:

嵌套在 List 里面的 DataSetParamDto 实体类没有写注解。

导致 swagger 看到的文档效果是这样的:

3、入参是 Map 或者是 JSONObject

除非是不可抗拒的历史原因,否则强制要求开发人员把入参封装为 bean。这不仅仅是为了方便整合 swagger 文档,这也是 java 封装的一大特性。特别是刚入职场的新人,要避免存在这个问题。对于前后端数据交互,推荐阅读这篇文档:https://www.cnblogs.com/panlei3707/p/11208811.html

2 数据库相关问题

1、建表语句

引入 flyway 之后,V1 版本允许建表语句出现,后面的所有版本都是围绕表结构的增删改。每次对表结构的修改,要记录为一个 sql 文件,而不是把旧表删除,创建新表。新表一定是相关的旧表过渡而来。

2、文件命名规范及存放

sql 文件命名规范遵循 flyway 命名规范,放在业务模块的 resources/db/migration 下,命名为:

V 20220224.01__create_report.sql

解析:大写V + 年 + 月 + 日 + 点符合( . ) + 版本号(防止同一天有多个sql修改) + 两个下划线( __ ) + 描述(中文或者英文都行)

3、漏写注释问题

对于每个类,每个方法,每个 bean 实体类 的作用,我们都应该做一个注释,让人一眼看下去,就知道是它的大概作用。特别是对应数据表的每一个 bean ,要么用 @TableName("表名") 标准对应的是哪个表,要么就在注释用写明是基于哪个表生成的 bean, 特别是连表,复杂的 bean 实体类, 要标注清楚,每个字段要写上注释。

4、返回值封装问题

不同项目,所用不同的返回值封装。返回值封装无好坏之分,但是为了统一格式,统一代码风格,后续开发一律要使用 sc-initialize 中 entity/vo/ 下面的 ResList和 Result 作为返回值封装类型。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: