Files
contract-manager/docs/task/server模块service缓存调整为Vo对象/DESIGN_server模块service缓存调整为Vo对象.md
songqq c4eec0a9dd refactor(model): 重构模型类包结构并优化序列化处理
重构模型类包结构,将模型类按功能模块划分到不同的子包中。优化序列化处理,为VO类添加serialVersionUID并实现Serializable接口。移除部分冗余的serialVersionUID字段,简化模型类代码。同时修复UITools中空值处理的问题,并更新pom版本至0.0.100-SNAPSHOT。

- 将模型类按功能模块划分到ds子包中
- 为VO类添加序列化支持
- 移除冗余的serialVersionUID字段
- 修复UITools空值处理问题
- 更新项目版本号
2025-10-09 18:27:48 +08:00

612 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 6A工作流 - 架构阶段
# 任务名: Server模块Service缓存调整为Vo对象
## 1. 整体架构图
```mermaid
graph TD
subgraph 客户端层
Client[客户端应用]
end
subgraph 控制器层
Controller[REST控制器]
end
subgraph 服务层
IEntityService_Int[IEntityService<T, ID>接口]
QueryService_Int[QueryService<Vo>接口]
VoableService_Int[VoableService<Model, Vo>接口]
ServiceImpl1[Service实现类1]
ServiceImpl2[Service实现类2]
end
subgraph 数据访问层
Repository1[Repository接口1]
Repository2[Repository接口2]
JPA[Spring Data JPA]
end
subgraph 数据层
Model1[Model实体类1]
Model2[Model实体类2]
Vo1[Vo视图对象1]
Vo2[Vo视图对象2]
MySQL[MySQL数据库]
end
subgraph 缓存机制
Cacheable[Spring Cache注解]
Redis[Redis缓存]
end
subgraph 依赖组件
WebSocketServerCallbackManager[WebSocketServerCallbackManager]
WebSocketServerHandler[WebSocketServerHandler]
WebSocketServerTaskManager[WebSocketServerTaskManager]
Voable_Int[Voable<Vo>接口]
end
Client -->|HTTP请求| Controller
Controller -->|调用服务方法| ServiceImpl1
Controller -->|调用服务方法| ServiceImpl2
ServiceImpl1 -->|实现| IEntityService_Int
ServiceImpl1 -->|实现| QueryService_Int
ServiceImpl1 -->|实现| VoableService_Int
ServiceImpl2 -->|实现| IEntityService_Int
ServiceImpl2 -->|实现| QueryService_Int
ServiceImpl2 -->|实现| VoableService_Int
ServiceImpl1 -->|使用| Repository1
ServiceImpl2 -->|使用| Repository2
Repository1 -->|继承| JPA
Repository2 -->|继承| JPA
ServiceImpl1 -->|操作| Model1
ServiceImpl2 -->|操作| Model2
Model1 -->|实现| Voable_Int
Model2 -->|实现| Voable_Int
Model1 -->|转换为| Vo1
Model2 -->|转换为| Vo2
ServiceImpl1 -->|使用| Cacheable
ServiceImpl2 -->|使用| Cacheable
Cacheable -->|存储| Redis
WebSocketServerCallbackManager -->|调用| ServiceImpl1
WebSocketServerCallbackManager -->|调用| ServiceImpl2
WebSocketServerHandler -->|使用| WebSocketServerCallbackManager
WebSocketServerTaskManager -->|使用| WebSocketServerCallbackManager
```
## 2. 架构说明
本架构设计主要针对Server模块中Service缓存从实体类调整为Vo对象的需求核心调整点包括
### 2.1 缓存层调整
- 将Redis缓存中的数据从实体类(Model)改为视图对象(Vo)
- 所有查询操作返回Vo对象并缓存
- 缓存策略调整findById方法使用@Cacheable注解key为id值
### 2.2 服务层重构
- Service实现类同时实现三个核心接口IEntityService<T, ID>、QueryService<Vo>和VoableService<Model, Vo>
- 分离实体操作和查询操作,使系统更符合单一职责原则
- 添加基于Vo对象的更新和创建操作方法
### 2.3 数据转换层
- 引入Voable接口定义实体类到Vo类的转换方法
- 所有实体类实现Voable接口提供具体的转换逻辑
- Service层负责调用转换方法并管理转换过程中的异常处理
### 2.4 依赖组件兼容性
- 特别关注WebSocketServerCallbackManager、WebSocketServerHandler等依赖组件对Service接口的调用方式
- 增强这些组件的类型处理逻辑确保它们能够正确处理Service类的新泛型参数
## 3. 分层设计和核心组件
### 3.1 客户端层
- **职责**发起HTTP请求接收和展示返回的Vo对象数据
- **组件**:前端应用程序
### 3.2 控制器层
- **职责**:接收客户端请求,调用相应的服务方法,返回处理结果
- **组件**REST控制器
- **关键特性**:处理请求路由和参数解析,异常统一处理
### 3.3 服务层
- **职责**:实现业务逻辑,处理数据转换,管理缓存策略
- **核心接口**
- IEntityService<T, ID>提供实体类的基本CRUD操作
- QueryService<Vo>提供Vo对象的查询操作并实现缓存
- VoableService<Model, Vo>提供基于Vo对象的更新和创建操作
- **实现类**各种具体的Service实现类
- **关键特性**:数据转换、缓存管理、事务处理、异常处理
### 3.4 数据访问层
- **职责**:提供数据访问接口,实现数据持久化
- **组件**Repository接口、Spring Data JPA
- **关键特性**ORM映射、数据库操作、查询优化
### 3.5 数据层
- **职责**:定义数据模型和视图对象
- **组件**
- Model实体类映射数据库表结构实现Voable接口
- Vo视图对象面向前端展示的数据模型
- **关键特性**:数据结构定义、属性映射、转换逻辑
### 3.6 缓存机制
- **职责**:提供数据缓存服务,提高系统性能
- **组件**Spring Cache注解、Redis缓存
- **关键特性**:缓存策略配置、缓存数据管理、缓存异常处理
### 3.7 依赖组件
- **职责**提供WebSocket通信、任务管理等辅助功能
- **组件**WebSocketServerCallbackManager、WebSocketServerHandler、WebSocketServerTaskManager
- **关键特性**与Service层交互、类型安全处理、异常降级
## 4. 模块依赖关系图
```mermaid
graph TD
IEntityService_Int[IEntityService<T, ID>接口]
QueryService_Int[QueryService<Vo>接口]
VoableService_Int[VoableService<Model, Vo>接口]
ServiceImpl1[Service实现类1]
ServiceImpl2[Service实现类2]
Repository1[Repository接口1]
Repository2[Repository接口2]
JPA[Spring Data JPA]
Model1[Model实体类1]
Model2[Model实体类2]
Vo1[Vo视图对象1]
Vo2[Vo视图对象2]
Cacheable[Spring Cache注解]
Redis[Redis缓存]
WebSocketServerCallbackManager[WebSocketServerCallbackManager]
WebSocketServerHandler[WebSocketServerHandler]
WebSocketServerTaskManager[WebSocketServerTaskManager]
Voable_Int[Voable<Vo>接口]
IEntityService_Int -->|实现| ServiceImpl1
QueryService_Int -->|实现| ServiceImpl1
VoableService_Int -->|实现| ServiceImpl1
IEntityService_Int -->|实现| ServiceImpl2
QueryService_Int -->|实现| ServiceImpl2
VoableService_Int -->|实现| ServiceImpl2
ServiceImpl1 -->|使用| Repository1
ServiceImpl2 -->|使用| Repository2
Repository1 -->|继承| JPA
Repository2 -->|继承| JPA
ServiceImpl1 -->|操作| Model1
ServiceImpl2 -->|操作| Model2
Model1 -->|实现| Voable_Int
Model2 -->|实现| Voable_Int
Model1 -->|转换为| Vo1
Model2 -->|转换为| Vo2
ServiceImpl1 -->|使用| Cacheable
ServiceImpl2 -->|使用| Cacheable
Cacheable -->|存储| Redis
WebSocketServerCallbackManager -->|调用| ServiceImpl1
WebSocketServerCallbackManager -->|调用| ServiceImpl2
WebSocketServerHandler -->|使用| WebSocketServerCallbackManager
WebSocketServerTaskManager -->|使用| WebSocketServerCallbackManager
```
**依赖关系说明**
1. **接口定义与服务实现**Service实现类依赖并实现了IEntityService<Model>、QueryService<Vo>和VoableService<Model, Vo>三个接口,提供具体的业务逻辑实现。
2. **服务实现与数据访问**Service实现类依赖Repository接口进行数据访问操作Repository接口依赖Spring Data JPA实现数据持久化。
3. **服务实现与数据模型**Service实现类操作实体类并通过Voable接口将实体类转换为Vo类。
4. **服务实现与缓存机制**Service实现类使用Spring Cache注解对查询结果进行缓存缓存数据存储在Redis中。
5. **依赖组件与服务实现**WebSocket相关组件依赖Service实现类提供的数据操作功能需要特别关注这些组件对Service接口的调用方式。
## 5. 接口契约定义
### 5.1 IEntityService<T, ID>接口
**接口定义**
```java
public interface IEntityService<T, ID> {
T findById(ID id);
List<T> findAll();
Page<T> findAll(Pageable pageable);
T save(T entity);
void deleteById(ID id);
// 其他实体类操作方法
}
```
**功能描述**提供实体类的基本CRUD操作泛型T表示实体类类型ID表示实体类主键类型。
**实现说明**
- Service实现类需要实现此接口确保实体类的基本操作功能正常。
- 此接口主要用于后端内部的数据处理,不直接返回给前端。
- 与QueryService<Vo>接口配合使用,实现数据访问和数据展示的分离。
### 5.2 QueryService<Vo>接口
**接口定义**
```java
public interface QueryService<Vo> {
@Cacheable(key = "#id", unless = "#result == null")
Vo findById(Object id);
Page<Vo> findAll(Pageable pageable);
// 其他查询方法
}
```
**功能描述**提供Vo对象的查询操作泛型Vo表示视图对象类型。
**实现说明**
- Service实现类需要实现此接口确保查询操作返回的是Vo对象。
- findById方法需要标注@Cacheable注解缓存返回的Vo对象。
- 此接口主要用于向前端提供数据展示所需的Vo对象。
**findById方法实现逻辑**
```java
@Override
public CompanyFileTypeVo findById(Object id) {
// 1. 调用IEntityService的findById方法获取实体对象
CompanyFileType entity = super.findById((Long) id);
if (entity == null) {
return null;
}
// 2. 调用实体对象的toVo方法转换为Vo对象
return entity.toVo();
}
```
**findAll方法实现逻辑**
```java
@Override
public Page<CompanyFileTypeVo> findAll(Pageable pageable) {
// 1. 调用IEntityService的findAll方法获取实体对象的Page
Page<CompanyFileType> entityPage = super.findAll(pageable);
// 2. 将实体对象的Page转换为Vo对象的Page
return entityPage.map(CompanyFileType::toVo);
}
```
### 5.3 VoableService<Model, Vo>接口
**接口定义**
```java
public interface VoableService<Model, Vo> {
Vo updateByVo(Vo vo);
Vo createByVo(Vo vo);
// 其他Vo相关操作方法
}
```
**功能描述**提供基于Vo对象的更新和创建操作泛型Model表示实体类类型Vo表示视图对象类型。
**实现说明**
- Service实现类需要实现此接口支持通过Vo对象进行数据的更新和创建。
- 实现时需要将Vo对象转换为实体类对象然后调用IEntityService的方法进行数据操作。
**updateByVo方法实现逻辑**
```java
@Override
public CompanyFileTypeVo updateByVo(CompanyFileTypeVo vo) {
// 1. 验证Vo对象
if (vo == null || vo.getId() == null) {
throw new IllegalArgumentException("Vo对象或ID不能为空");
}
// 2. 查找对应的实体对象
CompanyFileType entity = findById(vo.getId());
if (entity == null) {
throw new EntityNotFoundException("未找到实体: " + vo.getId());
}
// 3. 将Vo对象的属性值复制到实体对象
BeanUtils.copyProperties(vo, entity, "id", "createDate", "createUser", "updateDate", "updateUser");
// 4. 保存更新后的实体对象
CompanyFileType updatedEntity = save(entity);
// 5. 转换为Vo对象返回
return updatedEntity.toVo();
}
```
**createByVo方法实现逻辑**
```java
@Override
public CompanyFileTypeVo createByVo(CompanyFileTypeVo vo) {
// 1. 验证Vo对象
if (vo == null) {
throw new IllegalArgumentException("Vo对象不能为空");
}
// 2. 创建新的实体对象
CompanyFileType entity = new CompanyFileType();
// 3. 将Vo对象的属性值复制到实体对象
BeanUtils.copyProperties(vo, entity, "id", "createDate", "createUser", "updateDate", "updateUser");
// 4. 设置创建信息
entity.setCreateDate(new Date());
entity.setCreateUser(getCurrentUser());
// 5. 保存新的实体对象
CompanyFileType savedEntity = save(entity);
// 6. 转换为Vo对象返回
return savedEntity.toVo();
}
```
### 5.4 Voable接口
**接口定义**
```java
public interface Voable<Vo> {
Vo toVo();
}
```
**功能描述**定义实体类到Vo类的转换方法泛型Vo表示目标视图对象类型。
**实现说明**
- 所有实体类都需要实现此接口,提供具体的转换逻辑。
- toVo方法负责将实体类的属性值映射到Vo类的对应属性。
**实现示例**
```java
public class CompanyFileType implements Voable<CompanyFileTypeVo> {
// 实体类属性
private Long id;
private String name;
private String code;
private Date createDate;
private String createUser;
// 其他属性和getter/setter方法
@Override
public CompanyFileTypeVo toVo() {
CompanyFileTypeVo vo = new CompanyFileTypeVo();
vo.setId(this.id);
vo.setName(this.name);
vo.setCode(this.code);
// 只复制需要在前端展示的属性
return vo;
}
}
```
## 6. 数据流向图
### 6.1 请求处理流程
```mermaid
graph TD
Client[客户端请求]
Controller[控制器]
ServiceImpl[Service实现类]
Repository[Repository]
JPA[JPA]
MySQL[MySQL数据库]
Redis[Redis缓存]
Vo[Vo对象]
Model[Model实体类]
Client -->|findById请求| Controller
Controller -->|调用findById| ServiceImpl
ServiceImpl -->|检查缓存| Redis
Redis -->|缓存命中| Vo
ServiceImpl -->|缓存未命中| Repository
Repository -->|查询| JPA
JPA -->|访问| MySQL
MySQL -->|返回| Model
ServiceImpl -->|转换| Vo
ServiceImpl -->|存入缓存| Redis
Vo -->|返回| ServiceImpl
ServiceImpl -->|返回| Controller
Controller -->|返回| Client
```
**数据流向说明**
1. **查询请求处理**客户端发起查询请求控制器接收请求并调用Service实现类的findById方法。
2. **缓存检查**Service实现类首先检查Redis缓存中是否存在对应的Vo对象。
3. **缓存命中**如果缓存命中直接从缓存中获取Vo对象返回。
4. **缓存未命中**如果缓存未命中Service实现类通过Repository查询数据库获取实体类对象然后将实体类对象转换为Vo对象存入Redis缓存并返回Vo对象。
### 6.2 数据转换流程
```mermaid
graph TD
DB[数据库
Model实体类数据] -->|查询| Repository[Repository]
Repository -->|返回| ServiceImpl[Service实现类]
ServiceImpl -->|调用toVo| Model[Model实体类
实现Voable接口]
Model -->|转换为| Vo[Vo对象]
ServiceImpl -->|缓存| Redis[Redis缓存
存储Vo对象]
ServiceImpl -->|返回| Controller[控制器]
Controller -->|返回| Client[客户端]
```
**转换流程说明**
1. **数据查询**从数据库查询实体类数据通过Repository返回给Service实现类。
2. **数据转换**Service实现类调用实体类的toVo方法将实体类数据转换为Vo对象。
3. **缓存存储**转换后的Vo对象被存入Redis缓存中以提高后续查询性能。
4. **数据返回**Vo对象通过控制器返回给客户端用于前端展示。
## 7. 异常处理策略
### 7.1 转换异常处理
**场景**实体类转换为Vo对象时发生异常
**处理策略**
- 使用try-catch块捕获转换过程中可能发生的异常
- 记录异常日志,包括异常信息和上下文数据
- 返回友好的错误提示,避免将系统内部错误暴露给前端
- 针对关键业务,可以考虑使用补偿机制或降级处理
**示例代码**
```java
@Override
public CompanyFileTypeVo findById(Object id) {
try {
CompanyFileType entity = super.findById((Long) id);
if (entity == null) {
return null;
}
return entity.toVo();
} catch (Exception e) {
log.error("Failed to convert CompanyFileType to CompanyFileTypeVo for id: {}", id, e);
throw new ServiceException("数据转换异常: " + e.getMessage());
}
}
```
### 7.2 数据验证异常处理
**场景**Vo对象数据不完整或不符合业务规则
**处理策略**
- 在updateByVo和createByVo方法中对输入的Vo对象进行严格验证
- 使用@Valid注解和Bean Validation框架进行参数校验
- 对于验证失败的情况抛出ValidationException或自定义异常
- 返回详细的错误信息,指导前端用户进行正确的操作
**示例代码**
```java
@Override
public CompanyFileTypeVo updateByVo(@Valid CompanyFileTypeVo vo) {
if (vo == null || vo.getId() == null) {
throw new IllegalArgumentException("Vo对象或ID不能为空");
}
// 其他验证逻辑
// ...
}
```
### 7.3 事务处理异常
**场景**:数据操作过程中发生事务异常
**处理策略**
- 使用Spring的事务管理机制确保数据操作的原子性
- 使用@Transactional注解标记事务方法,并配置适当的事务传播特性和隔离级别
- 针对事务异常Spring会自动回滚事务确保数据一致性
- 记录异常日志,并返回适当的错误提示
**示例代码**
```java
@Transactional(rollbackFor = Exception.class)
@Override
public CompanyFileTypeVo createByVo(CompanyFileTypeVo vo) {
// 事务操作逻辑
// ...
}
```
### 7.4 缓存异常处理
**场景**Redis缓存操作失败
**处理策略**
- 使用try-catch块捕获缓存操作可能发生的异常
- 实现缓存降级策略,当缓存操作失败时,直接从数据库查询数据
- 记录异常日志,便于问题排查和监控
- 考虑使用Redis集群或哨兵模式提高缓存服务的可用性
**示例代码**
```java
@Override
@Cacheable(key = "#id", unless = "#result == null")
public CompanyFileTypeVo findById(Object id) {
try {
// 缓存操作逻辑
// ...
} catch (CacheException e) {
log.warn("Redis cache operation failed, querying from database directly", e);
// 降级到数据库查询
// ...
}
}
```
### 7.5 实体未找到异常
**场景**根据ID查询实体类时未找到对应的数据
**处理策略**
- 定义EntityNotFoundException自定义异常
- 在findById等方法中当查询结果为null时抛出EntityNotFoundException
- 全局异常处理器捕获EntityNotFoundException返回HTTP 404状态码和友好的错误信息
- 记录异常日志,便于问题排查
**示例代码**
```java
@Override
public CompanyFileTypeVo updateByVo(CompanyFileTypeVo vo) {
// 验证Vo对象
if (vo == null || vo.getId() == null) {
throw new IllegalArgumentException("Vo对象或ID不能为空");
}
// 查找对应的实体对象
CompanyFileType entity = findById(vo.getId());
if (entity == null) {
throw new EntityNotFoundException("未找到实体: " + vo.getId());
}
// 其他操作
// ...
}
```
### 7.6 WebSocket服务异常处理
**场景**WebSocket服务组件处理Service类新泛型参数时发生异常
**处理策略**
- 增强WebSocketServerCallbackManager等组件的类型处理逻辑添加类型安全检查
- 使用反射API处理泛型参数时捕获可能发生的异常如ClassCastException、NoSuchMethodException等
- 记录异常日志,包括详细的上下文信息和堆栈跟踪
- 提供优雅的降级处理确保WebSocket服务的基本功能不受影响
**示例代码**
```java
// 在WebSocketServerCallbackManager中
public <T> T createNewEntity(Class<?> serviceClass) {
try {
// 反射获取实体类型并创建实例
// ...
} catch (Exception e) {
log.error("Failed to create new entity for service: {}", serviceClass.getName(), e);
return null;
}
}
```
## 8. 设计原则
1. **最小化修改原则**:在满足需求的前提下,尽量减少对现有代码的修改,降低风险和工作量。
2. **向后兼容性原则**:确保修改后的代码能够与现有系统保持兼容,不影响系统的正常运行。
3. **数据一致性原则**:确保缓存数据与数据库数据的一致性,避免数据不一致导致的问题。
4. **接口分离原则**:将数据操作与查询操作分离到不同接口,使得系统更符合单一职责原则。
5. **可扩展性原则**:设计具有良好扩展性的架构,便于后续功能的增加和修改。
6. **安全性原则**:确保数据转换和缓存操作的安全性,防止数据泄露和恶意攻击。
7. **性能优化原则**:优化数据转换和缓存操作的性能,提高系统整体响应速度。
8. **可测试性原则**:确保设计的代码具有良好的可测试性,便于编写单元测试和集成测试。
9. **代码复用原则**:提取通用的转换逻辑和缓存策略,提高代码的复用性。