重构Service类实现,将QueryService泛型参数调整为VO类型,确保缓存VO对象而非实体。优化关联实体处理逻辑,减少重复代码。修改findById方法返回VO对象,新增getById方法获取实体。更新相关调用点以适配新接口。 调整WebSocket处理、控制器及Service实现,确保数据类型一致性。完善文档记录重构过程及发现的问题。为后续优化提供基础架构支持。
301 lines
9.8 KiB
Markdown
301 lines
9.8 KiB
Markdown
# Server模块Service缓存调整为Vo对象设计文档
|
||
|
||
## 1. 整体架构图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
subgraph 控制器层
|
||
Controller[Controller控制器]
|
||
end
|
||
|
||
subgraph 服务层
|
||
direction LR
|
||
Service1[Service类
|
||
实现IEntityService<Model>和QueryService<Vo>]
|
||
Service2[Service类
|
||
实现IEntityService<Model>和QueryService<Vo>]
|
||
Service3[Service类
|
||
实现IEntityService<Model>和QueryService<Vo>]
|
||
end
|
||
|
||
subgraph 数据转换层
|
||
Mapper[实体-VO转换器
|
||
负责双向转换]
|
||
end
|
||
|
||
subgraph 数据访问层
|
||
Repository[Repository接口
|
||
操作实体类]
|
||
end
|
||
|
||
subgraph 数据层
|
||
Database[(数据库)]
|
||
end
|
||
|
||
subgraph 缓存层
|
||
RedisCache[Redis缓存
|
||
存储VO对象]
|
||
end
|
||
|
||
Controller -->|调用服务方法| Service1
|
||
Controller -->|调用服务方法| Service2
|
||
Controller -->|调用服务方法| Service3
|
||
Service1 -->|转换VO到实体| Mapper
|
||
Service2 -->|转换VO到实体| Mapper
|
||
Service3 -->|转换VO到实体| Mapper
|
||
Mapper -->|转换实体到VO| Service1
|
||
Mapper -->|转换实体到VO| Service2
|
||
Mapper -->|转换实体到VO| Service3
|
||
Service1 -->|CRUD操作| Repository
|
||
Service2 -->|CRUD操作| Repository
|
||
Service3 -->|CRUD操作| Repository
|
||
Repository -->|存取数据| Database
|
||
Service1 <-->|缓存VO对象| RedisCache
|
||
Service2 <-->|缓存VO对象| RedisCache
|
||
Service3 <-->|缓存VO对象| RedisCache
|
||
|
||
%% 关键修改点
|
||
style RedisCache fill:#bbf,stroke:#333,stroke-width:2px
|
||
```
|
||
|
||
## 2. 分层设计和核心组件
|
||
|
||
### 2.1 控制器层
|
||
- **职责**: 处理HTTP请求,调用Service层方法,返回处理结果
|
||
- **影响**: 可能需要调整调用Service层方法的参数和返回值类型
|
||
|
||
### 2.2 服务层
|
||
- **职责**: 实现业务逻辑,处理数据转换,调用Repository层进行数据操作,管理缓存
|
||
- **核心组件**: 所有注解了@CacheConfig的Service类
|
||
- **修改内容**:
|
||
- Service类同时实现IEntityService<Model>和QueryService<Vo>接口
|
||
- IEntityService接口泛型保持为实体类(Model)
|
||
- QueryService接口泛型修改为VO类
|
||
- 继承 VoableService<M, Vo>接口,实现 updateByVo 方法
|
||
- 修改 findById 方法,返回VO对象,并且使用 @Cacheable(key = "#p0") 注解
|
||
- 保留 getById 方法,调用 repository.findById(id) 返回实体对象
|
||
|
||
### 2.3 数据转换层
|
||
- **职责**: 负责实体类和VO类之间的数据转换
|
||
- **核心组件**:
|
||
- 现有的VoableService接口
|
||
- 实体类自带的toVo()方法
|
||
- **设计考虑**: 使用实体类自带的toVo()方法进行转换,简化代码结构
|
||
|
||
### 2.4 数据访问层
|
||
- **职责**: 提供对数据库的访问操作
|
||
- **核心组件**: Spring Data JPA Repository接口
|
||
- **影响**: 基本不受修改影响,仍然操作实体类
|
||
|
||
### 2.5 缓存层
|
||
- **职责**: 存储VO对象,提高数据访问性能
|
||
- **核心组件**: Redis缓存
|
||
- **关键修改**: 确保只缓存VO对象,避免代理对象序列化问题
|
||
|
||
## 3. 模块依赖关系图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
subgraph 接口定义
|
||
IEntityService[IEntityService<Model>
|
||
定义CRUD操作接口] --> VoableService[VoableService<M, Vo>
|
||
定义VO更新方法]
|
||
QueryService[QueryService<Vo>
|
||
定义查询操作接口]
|
||
end
|
||
|
||
subgraph 服务实现
|
||
ServiceImpl[Service实现类
|
||
实现IEntityService<Model>、QueryService<Vo>和VoableService]
|
||
end
|
||
|
||
subgraph 数据访问
|
||
Repository[Repository接口
|
||
操作实体类]
|
||
end
|
||
|
||
subgraph 数据模型
|
||
Entity[实体类
|
||
持久化对象]
|
||
VO[VO类
|
||
视图对象]
|
||
end
|
||
|
||
subgraph 缓存
|
||
RedisCache[Redis缓存
|
||
存储VO对象]
|
||
end
|
||
|
||
IEntityService --> ServiceImpl
|
||
QueryService --> ServiceImpl
|
||
VoableService --> ServiceImpl
|
||
ServiceImpl --> Repository
|
||
Repository --> Entity
|
||
ServiceImpl --> Entity
|
||
ServiceImpl --> VO
|
||
ServiceImpl <-->|缓存VO对象| RedisCache
|
||
|
||
style RedisCache fill:#bbf,stroke:#333,stroke-width:2px
|
||
```
|
||
|
||
## 4. 接口契约定义
|
||
|
||
### 4.1 IEntityService<Model>接口
|
||
|
||
```java
|
||
public interface IEntityService<Model> {
|
||
// 根据ID查询Model对象
|
||
Model getById(Integer id);
|
||
|
||
// 根据查询规范和分页参数查询Model对象列表
|
||
Page<Model> findAll(Specification<Model> spec, Pageable pageable);
|
||
|
||
// 根据搜索文本构建查询规范
|
||
Specification<Model> getSpecification(String searchText);
|
||
|
||
// 搜索Model对象列表(默认方法)
|
||
default List<Model> search(String searchText) {
|
||
throw new UnsupportedOperationException();
|
||
}
|
||
|
||
// 删除Model对象
|
||
void delete(Model entity);
|
||
|
||
// 保存Model对象
|
||
Model save(Model entity);
|
||
}
|
||
|
||
### 4.2 QueryService<Vo>接口
|
||
|
||
```java
|
||
public interface QueryService<Vo> {
|
||
// 根据ID查询Vo对象
|
||
Vo findById(Integer id);
|
||
|
||
// 根据查询参数和分页条件获取Vo对象列表
|
||
Page<Vo> findAll(JsonNode paramsNode, Pageable pageable);
|
||
|
||
// 计数方法
|
||
default long count(JsonNode paramsNode) {
|
||
return 0;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.3 Service实现类接口契约
|
||
|
||
对于每个Service实现类,需要同时实现IEntityService<Model>和QueryService<Vo>接口:
|
||
|
||
#### IEntityService<Model>实现方法:
|
||
|
||
| 方法签名 | 实现逻辑 |
|
||
|---------|---------|
|
||
| `Model getById(Integer id)` | 1. 调用repository.findById(id)
|
||
2. 直接返回实体对象(不做缓存) |
|
||
| `Page<Model> findAll(Specification<Model> spec, Pageable pageable)` | 1. 构建查询条件
|
||
2. 调用repository.findAll(spec, pageable)
|
||
3. 返回包含实体对象的Page |
|
||
| `void delete(Model entity)` | 1. 直接调用repository.delete(entity) |
|
||
| `Model save(Model entity)` | 1. 直接调用repository.save(entity)
|
||
2. 清除相关缓存
|
||
3. 返回实体对象 |
|
||
|
||
#### QueryService<Vo>实现方法:
|
||
|
||
| 方法签名 | 实现逻辑 |
|
||
|---------|---------|
|
||
| `Vo findById(Integer id)` | 1. 调用repository.findById(id)
|
||
2. 将查询到的实体对象转换为VO对象
|
||
3. 使用@Cacheable注解缓存VO对象
|
||
4. 返回VO对象 |
|
||
| `Page<Vo> findAll(JsonNode paramsNode, Pageable pageable)` | 1. 构建查询条件
|
||
2. 调用repository.findAll(spec, pageable)
|
||
3. 将查询结果中的每个实体对象转换为VO对象
|
||
4. 返回包含VO对象的Page |
|
||
|
||
## 5. 数据流向图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
subgraph 服务请求处理流程
|
||
B[Controller接收请求
|
||
调用Service方法] --> C[Service方法处理
|
||
接收参数] --> D{检查Redis缓存
|
||
中是否存在VO对象}
|
||
D -->|存在| D1[直接返回缓存中的VO对象]
|
||
D -->|不存在| D2[准备数据操作
|
||
调用Repository] --> E[Repository操作数据库
|
||
返回Entity结果]
|
||
E --> F[Entity转换为VO
|
||
准备响应数据]
|
||
F --> G[将VO对象存入Redis缓存] --> H[Service返回VO
|
||
Controller组装响应]
|
||
D1 --> H
|
||
end
|
||
|
||
subgraph 数据转换流程
|
||
K[VO对象] -->|属性映射| L[Entity对象
|
||
用于数据持久化]
|
||
L -->|属性映射| K
|
||
end
|
||
|
||
C -->|查询操作| D
|
||
C -->|更新/删除操作| D2
|
||
D2 --> L
|
||
E --> L
|
||
F --> K
|
||
|
||
style G fill:#bbf,stroke:#333,stroke-width:2px
|
||
style D fill:#bbf,stroke:#333,stroke-width:2px
|
||
```
|
||
|
||
## 6. 异常处理策略
|
||
|
||
1. **转换异常处理**:
|
||
- 在实体类和VO类之间进行转换时,捕获并处理可能的转换异常
|
||
- 提供清晰的错误信息,指明转换失败的原因
|
||
|
||
2. **数据验证**:
|
||
- 在接收VO对象时,进行数据验证,确保数据的有效性
|
||
- 对于无效数据,抛出适当的异常并提供错误信息
|
||
|
||
3. **事务处理**:
|
||
- 保持原有的事务边界,确保数据操作的原子性
|
||
- 在事务中包含完整的数据操作和转换过程
|
||
|
||
4. **缓存异常**:
|
||
- 处理可能的缓存操作异常,确保即使缓存失败也不会影响业务逻辑
|
||
- 考虑添加缓存回退机制
|
||
- 特别处理Redis连接问题和序列化问题,确保系统可用性
|
||
|
||
5. **序列化异常**:
|
||
- 处理VO对象序列化失败的情况
|
||
- 确保VO类实现Serializable接口,避免在VO类中包含不可序列化的引用
|
||
|
||
6. **WebSocket服务异常处理**:
|
||
- 处理WebSocketServerCallbackManager中反射调用IEntityService接口时可能出现的类型转换异常
|
||
- 特别关注createNewEntity、findEntityTypeInInterfaces等依赖泛型参数的方法
|
||
- 确保WebSocket服务在接口泛型修改后能够正常处理异常情况
|
||
- 在invokerFindByIdMethod、invokerFindAllMethod等方法中添加类型安全检查
|
||
|
||
## 7. 设计原则
|
||
|
||
1. **最小化修改原则**: 仅修改必要的代码,避免不必要的重构
|
||
|
||
2. **向后兼容原则**: 尽量保持与原有系统的兼容性,特别是对依赖这些Service的组件,包括WebSocket服务
|
||
|
||
3. **数据一致性原则**: 确保实体类和VO类之间的数据转换不会导致数据丢失或不一致
|
||
|
||
4. **可测试性原则**: 设计支持单元测试和集成测试的代码结构,包括WebSocket服务的测试
|
||
|
||
5. **性能优化原则**: 考虑数据转换可能带来的性能影响,必要时进行优化
|
||
|
||
6. **代码复用原则**: 尽量复用现有的代码和模式,特别是数据转换相关的代码
|
||
|
||
7. **序列化安全原则**: 确保所有缓存的VO对象都是可序列化的,避免在VO对象中包含循环引用和不可序列化的组件
|
||
|
||
8. **类型安全原则**: 在WebSocketServerCallbackManager中添加类型安全检查,确保能够正确处理从实体类到VO类的泛型变化
|
||
|
||
9. **服务兼容性原则**: 确保修改后的IEntityService接口能够与WebSocket服务和其他现有服务组件兼容
|
||
|
||
通过以上设计,我们可以系统地完成IEntityService接口泛型的修改任务,确保修改后的系统能够正确、高效地运行。 |