Spring Cloud 与 Spring Cloud Alibaba 微服务开发流程详解:解耦之道
Spring Cloud 与 Spring Cloud Alibaba 微服务开发流程详解:解耦之道
前言
在当今数字化转型加速推进的背景下,企业应用架构正经历着从单体架构向微服务架构的重大转变。微服务架构通过将应用拆分成多个小型、独立的服务,每个服务专注于特定的业务功能,实现了系统的高可扩展性、灵活性和维护性。而Spring Cloud与Spring Cloud Alibaba作为微服务架构领域的杰出框架,为开发者提供了强大的工具和便捷的开发体验,助力企业高效构建基于微服务的应用系统。
本篇文章将深入剖析利用Spring Cloud与Spring Cloud Alibaba进行微服务开发的流程,重点探讨如何通过合理的架构设计和开发实践实现系统各模块间的解耦。我们将从项目的整体架构规划入手,逐步深入到各个关键层次的开发细节,包括API层、Biz层等在微服务架构中的角色与实现方式。同时,还会结合实际开发场景,分享如何有效管理项目中的target文件夹,以确保项目的整洁性和可维护性。无论是正在探索微服务架构的技术团队,还是希望提升开发技能的个人开发者,本文都将为您提供有价值的参考和指导,助您在微服务开发的道路上更加得心应手。
开发顺序复盘
api层就是对外的交互
在微服务架构中,api
层通常作为对外的交互接口,定义了服务间通信的契约和数据模型。以下是图片中 api
层各部分在开发中的作用:
1. api
包
- 作用:定义服务的接口和数据模型,供其他模块或服务调用。
- 详细说明:
-
- 接口定义:定义了服务的 API 接口,其他模块通过这些接口与当前服务进行交互。例如,定义门票服务的接口,供订单服务调用。
- 数据模型:定义了服务间传递的数据模型,确保数据的一致性和兼容性。例如,定义门票信息的 JavaBean,供其他服务在调用时传递数据。
2. enums
包
- 作用:定义枚举类型,用于表示固定的、有限的值集合。
- 详细说明:
-
- 枚举类型:定义了各种业务相关的枚举类型,如订单状态、订单类型、支付方式、支付状态等。这些枚举类型在服务间传递和处理数据时,提供了统一的标识和语义。
- 代码示例:
public enum OrderStatusEnum {
// 订单状态枚举
WAIT_PAY("待支付"),
PAID("已支付"),
DELIVERED("已出票"),
CLOSED("已关闭");
private String description;
OrderStatusEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
3. common
包
- 作用:存放公共的工具类、常量类等,供整个项目或多个模块使用。
- 详细说明:
-
- 字典类型常量:
DictTypeConstants
定义了字典类型的常量,用于在系统中标识不同的字典类型,方便在代码中进行判断和处理。 - 错误码常量:
ErrorCodeConstants
定义了错误码的常量,用于在系统中标识不同的错误情况,方便在代码中进行异常处理和返回统一的错误信息。 - 日志记录常量:
LogRecordConstants
定义了日志记录相关的常量,用于在系统中标识不同的日志类型和操作类型,方便进行日志的分类和查询。 - 代码示例:
- 字典类型常量:
public class DictTypeConstants {
// 字典类型常量
public static final String TICKET_TYPE = "ticket_type";
public static final String ORDER_STATUS = "order_status";
}
public class ErrorCodeConstants {
// 错误码常量
public static final int SUCCESS = 200;
public static final int PARAM_ERROR = 400;
public static final int SERVER_ERROR = 500;
}
public class LogRecordConstants {
// 日志记录常量
public static final String LOGIN_LOG = "login_log";
public static final String OPERATION_LOG = "operation_log";
}
4. package-info.java
- 作用:提供包的信息,如包的描述、版本等。
- 详细说明:
-
- 包描述:在
package-info.java
文件中,可以对包进行描述,说明包的作用和包含的内容。这有助于在开发和维护过程中,快速了解包的相关信息。 - 代码示例:
- 包描述:在
/**
* 包描述:门票模块的 API 层,定义了服务的接口和数据模型。
*/
package cn.iocoder.central.module.ticket.api;
开发中的作用总结
- 统一接口定义:
api
层通过定义统一的接口和数据模型,使得不同模块之间的交互更加规范和高效。 - 枚举类型规范化:
enums
包中的枚举类型,为业务相关的固定值提供了规范化的表示,避免了使用魔法值带来的问题。 - 公共常量共享:
common
包中的常量类,供整个项目或多个模块使用,确保了常量的统一性和一致性。 - 包信息清晰化:
package-info.java
文件对包进行描述,有助于开发人员快速了解包的相关信息,提高开发和维护的效率。
通过以上结构和内容,api
层在开发中起到了规范交互、统一数据模型、共享公共常量等重要作用,为整个系统的稳定性和可维护性提供了保障。
biz层
在微服务架构中,biz
层通常是指业务逻辑层,负责处理具体的业务逻辑和数据操作。以下是图片中 biz
层各部分在开发中的作用:
1. controller
包
- 作用:处理客户端的 HTTP 请求,提供 RESTful API 接口。
- 详细说明:
-
- 控制器类:定义了处理不同业务请求的控制器类,如
TicketOrderInfoController
,用于处理门票订单信息的相关请求。 - 视图对象(VO):在
vo
包中定义了视图对象,用于在控制器层和客户端之间传递数据。例如,TicketImportRespVo
、TicketImportVo
等,这些 VO 类通常用于封装请求和响应的数据。 - Excel 相关 VO:在
excel
包中定义了与 Excel 文件操作相关的 VO 类,如TicketImportRespVo
和TicketImportVo
,用于处理 Excel 文件的导入和导出。 - 代码示例:
- 控制器类:定义了处理不同业务请求的控制器类,如
@RestController
@RequestMapping("/ticket-order-info")
public class TicketOrderInfoController {
@Autowired
private TicketOrderInfoService ticketOrderInfoService;
@PostMapping("/save")
public ResponseEntity<TicketOrderInfoRespVO> saveTicketOrderInfo(@RequestBody TicketOrderInfoSaveReqVO reqVO) {
return ResponseEntity.ok(ticketOrderInfoService.saveTicketOrderInfo(reqVO));
}
}
2. dal
包
- 作用:数据访问层,负责与数据库进行交互,执行数据的增删改查操作。
- 详细说明:
-
- 数据对象(DO):在
dataobject
包中定义了数据对象类,如TicketOrderInfoDO
,这些类通常与数据库表结构一一对应,用于封装数据库中的数据。 - Mapper 接口:在
ticketinfo
包中定义了 Mapper 接口,如TicketOrderInfoMapper
,这些接口用于定义与数据库交互的方法,通常结合 MyBatis 或 MyBatis Plus 使用。 - 代码示例:
- 数据对象(DO):在
@Mapper
public interface TicketOrderInfoMapper {
int deleteByPrimaryKey(Long id);
int insert(TicketOrderInfoDO record);
TicketOrderInfoDO selectByPrimaryKey(Long id);
int updateByPrimaryKeySelective(TicketOrderInfoDO record);
int updateByPrimaryKey(TicketOrderInfoDO record);
}
3. package-info.java
- 作用:提供包的信息,如包的描述、版本等。
- 详细说明:
-
- 包描述:在
package-info.java
文件中,可以对包进行描述,说明包的作用和包含的内容。这有助于在开发和维护过程中,快速了解包的相关信息。 - 代码示例:
- 包描述:在
/**
* 包描述:门票模块的业务逻辑层,处理具体的业务逻辑和数据操作。
*/
package cn.iocoder.central.module.ticket.biz;
开发中的作用总结
- 处理 HTTP 请求:
controller
包中的控制器类负责处理客户端的 HTTP 请求,提供 RESTful API 接口,是客户端与服务器端交互的入口。 - 封装请求和响应数据:
vo
包中的视图对象类用于封装请求和响应的数据,确保数据的完整性和一致性。 - 处理 Excel 文件操作:
excel
包中的 VO 类专门用于处理 Excel 文件的导入和导出,方便与客户端进行 Excel 格式的数据交换。 - 数据访问操作:
dal
包中的数据对象类和 Mapper 接口负责与数据库进行交互,执行数据的增删改查操作,是业务逻辑层与数据层之间的桥梁。 - 包信息清晰化:
package-info.java
文件对包进行描述,有助于开发人员快速了解包的相关信息,提高开发和维护的效率。
通过以上结构和内容,biz
层在开发中起到了处理业务逻辑、封装数据、与数据库交互等重要作用,是整个微服务架构中的核心部分。
biz层中详细每个分层的分析
1. 框架层(Framework Layer)
- 功能与技术点配置:作为整个系统的基础,需先搭建好 Spring Security、Feign、JWT 等配置,为系统提供安全和通信支持。
-
- Spring Security 配置:定义安全策略,如基于角色的访问控制,配置用户认证和授权方式。
- Feign 客户端配置:设置超时时间、重试机制等,确保服务间远程调用的稳定性和可靠性。
- JWT 配置:实现用户令牌的生成和解析,确保用户身份在无状态分布式环境中安全传递。
- 联动方式实现:通过过滤器或拦截器检查请求中的认证信息,确保请求的合法性和安全性。
2. 数据访问层(Data Access Layer - DAL)
- 功能与技术点实现:负责数据存储与访问,包含 DataObject、MySQL 和 Redis 三部分。
-
- 实体类定义:使用 MyBatis Plus 定义数据库实体类(DataObject),映射数据库表结构。
- Mapper 接口与 XML 文件编写:编写 Mapper 接口和对应的 XML 文件,定义 SQL 语句,实现数据库操作。
- RedisTemplate 配置:配置 RedisTemplate,实现与 Redis 的交互,支持多种数据结构存储查询。
- 事务管理配置:结合 Spring 的事务管理器,确保数据操作一致性。
- 联动方式实现:通过 MyBatis Plus 的 Mapper 接口与 MySQL 数据库交互,执行 SQL 语句完成数据操作。对于 Redis 缓存操作,使用 RedisTemplate 进行数据的存取和过期设置。在数据查询时,优先从 Redis 缓存中获取数据,若缓存不存在则查询 MySQL 数据库,并将查询结果缓存到 Redis 中。
3. 服务层(Service Layer)
- 功能与技术点实现:作为业务逻辑核心,处理票务信息的增删改查。
-
- 服务接口与实现类编写:定义服务接口,编写实现类,处理业务规则。
- 分布式事务处理:涉及多数据源或服务的事务操作时,使用 Seata 等框架确保事务一致性。
- 服务发现与调用配置:通过 Nacos 发现服务,用 Feign 或 Dubbo 进行远程调用。
- 联动方式实现:通过依赖注入调用 DAL 层的 DAO 方法进行数据操作。当涉及多个服务的协作时,通过 Feign 客户端调用其他服务的 API,Nacos 实现服务发现和负载均衡。对于需要缓存的数据,服务层会先调用 Redis 相关操作从缓存中获取数据,若缓存失效则再调用 MySQL 相关操作从数据库中查询数据并更新缓存。
4. 控制层(Controller Layer)
- 功能与技术点实现:处理客户端的 HTTP 请求,尤其针对管理员操作和 Excel 文件相关视图对象(VO)。
-
- 控制器类与方法编写:使用 Spring MVC 处理 HTTP 请求响应,定义请求映射和参数绑定。
- Sentinel 配置:在方法级配置流量控制和熔断降级规则,防止接口过载。
- 统一响应格式设置:使用全局异常处理和响应封装,确保接口返回格式一致。
- 联动方式实现:通过依赖注入(@Autowired)调用服务层的业务逻辑方法。例如,当处理一个门票订单信息的查询请求时,控制器方法会调用服务层的查询业务逻辑方法,获取数据后将其转换为 Excel 格式返回给客户端。
5. 映射层(Mapper Layer)
- 功能与技术点实现:存放 MyBatis 的映射文件,定义 SQL 语句与 Java 方法的映射关系,实现数据库操作结果与 Java 对象的相互转换。
-
- MyBatis Mapper:通过 XML 文件或注解定义 SQL 映射,支持动态 SQL 和结果集映射。
- 联动方式实现:映射层的 Mapper 接口与 DAL 层的 DAO 类进行交互。DAO 类通过注入 Mapper 接口来执行 SQL 语句,完成数据的持久化操作或数据查询。MyBatis 会根据映射文件或注解中的配置,将 Java 对象转换为数据库操作所需的参数,或者将数据库查询结果映射为 Java 对象返回给 DAL 层。
通过以上分层架构设计,各层之间通过依赖注入、接口调用、配置文件等方式实现松耦合的联动,共同构建了一个高可用、安全、可扩展且性能优化的门票微服务系统。
项目中的target是什么
在软件开发项目中,target
文件夹通常是用于存放构建工具(如 Maven、Gradle 等)生成的构建输出文件的目录。以下是 target
文件夹在项目中的作用和内容的详细说明:
1. 构建输出目录
- 作用:
target
文件夹是 Maven 项目的默认构建输出目录,用于存放构建过程中生成的各类文件。 - 详细说明:
-
- 编译后的类文件:存放 Java 源代码编译后的
.class
文件。 - 资源文件:存放项目中的资源文件,如配置文件、静态资源等。
- 打包文件:存放项目构建后的打包文件,如 JAR、WAR 等。
- 编译后的类文件:存放 Java 源代码编译后的
2. 目录结构
classes
目录:存放编译后的类文件和资源文件。
-
- 包结构:通常会保留源代码的包结构,例如
cn.iocoder.central.module.ticket.controller
等。 - 内容示例:包含控制器类、视图对象(VO)类等的编译后的文件。
- 包结构:通常会保留源代码的包结构,例如
test-classes
目录:存放测试编译后的类文件和资源文件。surefire-reports
目录:存放测试运行后的报告文件。generated-sources
目录:存放构建过程中生成的源代码文件,如注解处理器生成的代码。
3. 构建工具的作用
- Maven:Maven 是一个流行的构建工具,它使用
pom.xml
文件定义项目的依赖、插件和构建配置。在构建过程中,Maven 会将编译后的文件输出到target
文件夹中。 - Gradle:Gradle 是另一个常用的构建工具,它使用
build.gradle
文件进行配置,同样会将构建输出放在target
文件夹中。
4. 版本控制
- 作用:
target
文件夹通常被添加到版本控制的忽略列表中(如.gitignore
),因为其中的内容是自动生成的,不需要纳入版本控制。 - 原因:
-
- 减少冗余:编译后的文件和构建输出文件较大,纳入版本控制会增加仓库的大小。
- 环境差异:不同开发环境下的构建输出可能不同,纳入版本控制可能导致环境不一致的问题。
5. 清理构建
- 作用:在开发过程中,有时需要清理
target
文件夹中的内容,以确保构建的干净性和一致性。 - 命令:
-
- Maven:使用
mvn clean
命令清理target
文件夹。 - Gradle:使用
gradle clean
命令清理target
文件夹。
- Maven:使用
6. 实际开发中的注意事项
- 不要手动修改:
target
文件夹中的内容是自动生成的,通常不需要手动修改。 - 构建配置:确保项目的构建配置(如
pom.xml
或build.gradle
)正确,以避免构建过程中出现问题。 - 依赖管理:正确管理项目的依赖,确保所有需要的库都正确配置并下载到本地。
通过以上说明,可以清楚地了解 target
文件夹在项目中的作用和重要性,以及在开发过程中如何正确使用和管理它。