项目整体架构

作为微服务项目,采用多模块结构,即允许我们在一个项目中管理多个子模块,每个模块都是严格独立的项目,拥有自己的POM文件。模块之间可以相互依赖,也可以被其他项目依赖。但是,所有的模块都会被统一管理,它们共享同一套构建系统和依赖管理。
为什么需要多模块项目?
主要有以下几个原因:
-
代码组织:在大型项目中,我们经常需要把代码分成多个模块,以便更好地组织代码。每个模块可以聚焦于一个特定的功能或领域,这样可以提高代码的可读性和可维护性。
-
依赖管理:Maven 多模块项目可以帮助我们更好地管理项目的依赖。在父项目的 POM 文件中,我们可以定义所有模块共享的依赖,这样可以避免重复的依赖定义,也方便我们管理和升级依赖。
-
构建和部署:Maven 多模块项目的另一个优点是它可以统一管理项目的构建和部署。我们只需要在父项目中执行 Maven 命令,就可以对所有模块进行构建和部署。这大大简化了开发者的工作
搭建微服务多模块工程骨架
新建项目,选择Maven Archetype创建Maven项目,修改父工程的pom.xml,包括:
-
<groupId>,<artifactId>,<version>: 分别指定了项目的 groupId 、artifactId 和 version,用于唯一标识项目和版本管理。 -
<name>,<description>: 分别指定了项目的名称和描述。 -
<packaging>: 指定项目的打包方式,这里是pom,表示该项目是一个多模块项目,不会产生可执行的 Jar 包。 -
<properties>: 定义了项目的属性,包括项目版本号、JDK 版本、项目编码和依赖包版本等。 -
<dependencyManagement>: 统一管理项目的依赖版本,这里定义了 lombok 的版本。 -
<build>: 定义了项目的构建配置,包括插件管理和插件配置。这里配置了 Spring Boot Maven 插件和 Maven 编译插件,指定了 Java 版本和编码方式,并且配置了 Lombok 的注解处理器。 -
<repositories>: 配置了项目的仓库,包括华为云和阿里云的 Maven 中央仓库,用于提升依赖下载速度。
当然,Spring Cloud Alibaba是必不可少的,可以在官网https://sca.aliyun.com/查看不同版本的文档,了解不同组件的依赖关系
创建auth认证服务
在主项目的基础上新建模块,生成器选择Spring Boot,Type选择Maven后点击Next,可以添加Spring Web依赖。创建完毕后对pom.xml文件修改,主要包括:指定父项目、指定打包方式以及常规的各种依赖。注意,需要在父项目的pom.xml中<modules>节点添加子模块。完成创建后,可以在父工程的Maven生命周期clean--->package,进行正确性验证,再启动auth模块主程序进行验证
添加framework平台基础设施建设模块
为什么要抽取一个 framework 基础设施模块?
-
代码复用和减少重复开发 :将通用的功能、组件抽取到一个独立的
framework模块中,可以实现代码的复用,减少不同业务线之间的重复开发。这样,各个业务线可以专注于自身的业务逻辑实现,而不需要从头开始构建基础功能。 -
统一管理和维护 :大一点的公司中,公司内部通常会成立一个基础平台小组,小组中均是经验丰富的高级工程师,由它们来开发并维护相关基础组件,编写使用文档。开发完成后,会将这些组件提交到公司内部的
Maven私服,可以实现对该模块的统一管理和维护。一旦framework模块有更新或修复,所有业务线都可以通过更新依赖来获取最新的功能和修复,而不需要每个业务线都单独进行更新。 -
版本控制和依赖管理 :
Maven私服可以提供版本控制和依赖管理的功能。通过在Maven私服中维护framework模块的版本信息,可以确保各个业务线使用到的是正确和兼容的版本,避免版本冲突和依赖问题。 -
提高开发效率和质量 :通过提供一个稳定、可靠的
framework模块,可以提高开发效率和质量。业务线开发人员可以更加专注于业务逻辑的实现,而不需要过多关注底层技术的实现细节。
统一异常 + 统一响应
基础异常接口:BaseExceptionInterface
java
package com.quanxiaoha.framework.common.exception;
public interface BaseExceptionInterface {
// 获取异常码
String getErrorCode();
// 获取异常信息
String getErrorMessage();
}
接口 = 制定规范 / 定规矩 它规定:任何异常(业务异常、系统异常),都必须提供两个东西:
-
异常码(
errorCode):比如USER_NOT_EXIST、PARAM_ERROR -
异常信息(
errorMessage):比如 "用户不存在"、"参数不能为空"
业务异常类:BizException
java
package com.quanxiaoha.framework.common.exception;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class BizException extends RuntimeException {
// 异常码
private String errorCode;
// 错误信息
private String errorMessage;
public BizException(BaseExceptionInterface baseExceptionInterface) {
this.errorCode = baseExceptionInterface.getErrorCode();
this.errorMessage = baseExceptionInterface.getErrorMessage();
}
}
继承 RuntimeException
-
RuntimeException:运行时异常 -
好处:不用强制 try/catch,业务代码更简洁
-
专门用来抛业务逻辑错误(用户不存在、密码错误、库存不足)
java
// 抛一个"用户不存在"的业务异常 throw new BizException(USER_NOT_EXIST);
统一响应工具类:Response<T>
java
package com.quanxiaoha.framework.common.response;
import com.quanxiaoha.framework.common.exception.BaseExceptionInterface;
import com.quanxiaoha.framework.common.exception.BizException;
import lombok.Data;
import java.io.Serializable;
@Data
public class Response<T> implements Serializable {
// 是否成功,默认为 true
private boolean success = true;
// 响应消息
private String message;
// 异常码
private String errorCode;
// 响应数据
private T data;
// =================================== 成功响应 ===================================
public static <T> Response<T> success() {
Response<T> response = new Response<>();
return response;
}
public static <T> Response<T> success(T data) {
Response<T> response = new Response<>();
response.setData(data);
return response;
}
// =================================== 失败响应 ===================================
public static <T> Response<T> fail() {
Response<T> response = new Response<>();
response.setSuccess(false);
return response;
}
public static <T> Response<T> fail(String errorMessage) {
Response<T> response = new Response<>();
response.setSuccess(false);
response.setMessage(errorMessage);
return response;
}
public static <T> Response<T> fail(String errorCode, String errorMessage) {
Response<T> response = new Response<>();
response.setSuccess(false);
response.setErrorCode(errorCode);
response.setMessage(errorMessage);
return response;
}
public static <T> Response<T> fail(BizException bizException) {
Response<T> response = new Response<>();
response.setSuccess(false);
response.setErrorCode(bizException.getErrorCode());
response.setMessage(bizException.getErrorMessage());
return response;
}
public static <T> Response<T> fail(BaseExceptionInterface baseExceptionInterface) {
Response<T> response = new Response<>();
response.setSuccess(false);
response.setErrorCode(baseExceptionInterface.getErrorCode());
response.setMessage(baseExceptionInterface.getErrorMessage());
return response;
}
}
实现 Serializable → 序列化:接口返回的数据要通过网络传输,必须实现这个接口
四个核心字段(前端接收的 JSON 格式)
java
{
"success": true/false, // 接口是否成功
"message": "提示信息", // 成功/失败提示
"errorCode": "异常码", // 失败时才有
"data": {} // 成功时返回的数据
}
使用方式:
java
@GetMapping("/user/{id}")
public Response<User> getUser(@PathVariable Long id) {
User user = userService.getUser(id);
return Response.success(user);
}
封装 API 请求日志切面业务组件
自定义一个 Spring Boot Starter 组件,将 API 请求日志切面功能封装进去,后续新建新的服务时,只需添加这个 starter , 即可拿来即用。
什么是Spring Boot Starter?
Spring Boot Starter 就像是一个"工具包",里面已经包含了你所需要的东西。它们把一些常用的功能和技术打包好了,比如处理数据库、处理 Web 请求等等。你只需要在你的项目中引入这些 Starter,它们就会自动帮你配置好所需的依赖项和参数。这样,你就可以省去很多繁琐的配置工作。
举个栗子,当你想要使用 Spring Boot 开发一个 Web 应用时,只需要引入 spring-boot-starter-web Starter。这个 Starter 包含了一系列依赖项和配置,使得开发 Web 应用变得更加简单。
具体来说,引入 spring-boot-starter-web Starter 后,你可以享受到以下好处:
-
内嵌的 Web 服务器支持 :Spring Boot 内置了多种 Web 服务器支持,比如 Tomcat、Jetty、Undertow。
spring-boot-starter-web会自动配置一个默认的 Web 服务器,你无需手动配置即可启动你的应用。 -
Spring MVC 框架支持 :Spring Boot 基于 Spring MVC 构建了强大的 Web 开发框架,包括了控制器、视图解析器等。引入
spring-boot-starter-web后,你可以直接使用 Spring MVC 来处理 Web 请求。 -
静态资源支持 :
spring-boot-starter-webStarter 自动配置了对静态资源(如 HTML、CSS、JavaScript 文件)的处理,你可以直接在项目中放置这些文件,Spring Boot 就能够正确地访问它们。 -
自动配置 :Spring Boot 会根据你的 classpath 自动配置应用程序。比如,如果你引入了
spring-boot-starter-web,Spring Boot 就会自动配置 DispatcherServlet、ViewResolver 等关键组件,从而让你的 Web 应用能够顺利地工作起来。
简而言之,Spring Boot Starter 是一种方便的方式,让你能够更快、更轻松地开始使用 Spring Boot 框架,并集成各种常用功能和技术。
添加日志切面
流程:
java
请求进来
↓
进入 AOP 环绕通知
↓
【前置】获取注解信息、方法信息、参数
↓
joinPoint.proceed() → 执行你的业务方法
↓
【后置】获取返回值、耗时
↓
【异常】如果报错,捕获异常
↓
保存操作日志
↓
返回结果给前端