refactor(model): 重构模型类包结构并优化序列化处理
重构模型类包结构,将模型类按功能模块划分到不同的子包中。优化序列化处理,为VO类添加serialVersionUID并实现Serializable接口。移除部分冗余的serialVersionUID字段,简化模型类代码。同时修复UITools中空值处理的问题,并更新pom版本至0.0.100-SNAPSHOT。 - 将模型类按功能模块划分到ds子包中 - 为VO类添加序列化支持 - 移除冗余的serialVersionUID字段 - 修复UITools空值处理问题 - 更新项目版本号
This commit is contained in:
@@ -1,301 +1,612 @@
|
||||
# Server模块Service缓存调整为Vo对象设计文档
|
||||
# 6A工作流 - 架构阶段
|
||||
# 任务名: Server模块Service缓存调整为Vo对象
|
||||
|
||||
## 1. 整体架构图
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
graph TD
|
||||
subgraph 客户端层
|
||||
Client[客户端应用]
|
||||
end
|
||||
|
||||
subgraph 控制器层
|
||||
Controller[Controller控制器]
|
||||
Controller[REST控制器]
|
||||
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转换器
|
||||
负责双向转换]
|
||||
IEntityService_Int[IEntityService<T, ID>接口]
|
||||
QueryService_Int[QueryService<Vo>接口]
|
||||
VoableService_Int[VoableService<Model, Vo>接口]
|
||||
ServiceImpl1[Service实现类1]
|
||||
ServiceImpl2[Service实现类2]
|
||||
end
|
||||
|
||||
subgraph 数据访问层
|
||||
Repository[Repository接口
|
||||
操作实体类]
|
||||
Repository1[Repository接口1]
|
||||
Repository2[Repository接口2]
|
||||
JPA[Spring Data JPA]
|
||||
end
|
||||
|
||||
subgraph 数据层
|
||||
Database[(数据库)]
|
||||
Model1[Model实体类1]
|
||||
Model2[Model实体类2]
|
||||
Vo1[Vo视图对象1]
|
||||
Vo2[Vo视图对象2]
|
||||
MySQL[MySQL数据库]
|
||||
end
|
||||
|
||||
subgraph 缓存层
|
||||
RedisCache[Redis缓存
|
||||
存储VO对象]
|
||||
subgraph 缓存机制
|
||||
Cacheable[Spring Cache注解]
|
||||
Redis[Redis缓存]
|
||||
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
|
||||
subgraph 依赖组件
|
||||
WebSocketServerCallbackManager[WebSocketServerCallbackManager]
|
||||
WebSocketServerHandler[WebSocketServerHandler]
|
||||
WebSocketServerTaskManager[WebSocketServerTaskManager]
|
||||
Voable_Int[Voable<Vo>接口]
|
||||
end
|
||||
|
||||
%% 关键修改点
|
||||
style RedisCache fill:#bbf,stroke:#333,stroke-width:2px
|
||||
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. 分层设计和核心组件
|
||||
## 2. 架构说明
|
||||
|
||||
### 2.1 控制器层
|
||||
- **职责**: 处理HTTP请求,调用Service层方法,返回处理结果
|
||||
- **影响**: 可能需要调整调用Service层方法的参数和返回值类型
|
||||
本架构设计主要针对Server模块中Service缓存从实体类调整为Vo对象的需求,核心调整点包括:
|
||||
|
||||
### 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.1 缓存层调整
|
||||
- 将Redis缓存中的数据从实体类(Model)改为视图对象(Vo)
|
||||
- 所有查询操作返回Vo对象并缓存
|
||||
- 缓存策略调整:findById方法使用@Cacheable注解,key为id值
|
||||
|
||||
### 2.2 服务层重构
|
||||
- Service实现类同时实现三个核心接口:IEntityService<T, ID>、QueryService<Vo>和VoableService<Model, Vo>
|
||||
- 分离实体操作和查询操作,使系统更符合单一职责原则
|
||||
- 添加基于Vo对象的更新和创建操作方法
|
||||
|
||||
### 2.3 数据转换层
|
||||
- **职责**: 负责实体类和VO类之间的数据转换
|
||||
- **核心组件**:
|
||||
- 现有的VoableService接口
|
||||
- 实体类自带的toVo()方法
|
||||
- **设计考虑**: 使用实体类自带的toVo()方法进行转换,简化代码结构
|
||||
- 引入Voable接口,定义实体类到Vo类的转换方法
|
||||
- 所有实体类实现Voable接口,提供具体的转换逻辑
|
||||
- Service层负责调用转换方法并管理转换过程中的异常处理
|
||||
|
||||
### 2.4 数据访问层
|
||||
- **职责**: 提供对数据库的访问操作
|
||||
- **核心组件**: Spring Data JPA Repository接口
|
||||
- **影响**: 基本不受修改影响,仍然操作实体类
|
||||
### 2.4 依赖组件兼容性
|
||||
- 特别关注WebSocketServerCallbackManager、WebSocketServerHandler等依赖组件对Service接口的调用方式
|
||||
- 增强这些组件的类型处理逻辑,确保它们能够正确处理Service类的新泛型参数
|
||||
|
||||
### 2.5 缓存层
|
||||
- **职责**: 存储VO对象,提高数据访问性能
|
||||
- **核心组件**: Redis缓存
|
||||
- **关键修改**: 确保只缓存VO对象,避免代理对象序列化问题
|
||||
## 3. 分层设计和核心组件
|
||||
|
||||
## 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
|
||||
flowchart TD
|
||||
subgraph 接口定义
|
||||
IEntityService[IEntityService<Model>
|
||||
定义CRUD操作接口] --> VoableService[VoableService<M, Vo>
|
||||
定义VO更新方法]
|
||||
QueryService[QueryService<Vo>
|
||||
定义查询操作接口]
|
||||
end
|
||||
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>接口]
|
||||
|
||||
subgraph 服务实现
|
||||
ServiceImpl[Service实现类
|
||||
实现IEntityService<Model>、QueryService<Vo>和VoableService]
|
||||
end
|
||||
IEntityService_Int -->|实现| ServiceImpl1
|
||||
QueryService_Int -->|实现| ServiceImpl1
|
||||
VoableService_Int -->|实现| ServiceImpl1
|
||||
IEntityService_Int -->|实现| ServiceImpl2
|
||||
QueryService_Int -->|实现| ServiceImpl2
|
||||
VoableService_Int -->|实现| ServiceImpl2
|
||||
|
||||
subgraph 数据访问
|
||||
Repository[Repository接口
|
||||
操作实体类]
|
||||
end
|
||||
ServiceImpl1 -->|使用| Repository1
|
||||
ServiceImpl2 -->|使用| Repository2
|
||||
Repository1 -->|继承| JPA
|
||||
Repository2 -->|继承| JPA
|
||||
|
||||
subgraph 数据模型
|
||||
Entity[实体类
|
||||
持久化对象]
|
||||
VO[VO类
|
||||
视图对象]
|
||||
end
|
||||
ServiceImpl1 -->|操作| Model1
|
||||
ServiceImpl2 -->|操作| Model2
|
||||
Model1 -->|实现| Voable_Int
|
||||
Model2 -->|实现| Voable_Int
|
||||
Model1 -->|转换为| Vo1
|
||||
Model2 -->|转换为| Vo2
|
||||
|
||||
subgraph 缓存
|
||||
RedisCache[Redis缓存
|
||||
存储VO对象]
|
||||
end
|
||||
ServiceImpl1 -->|使用| Cacheable
|
||||
ServiceImpl2 -->|使用| Cacheable
|
||||
Cacheable -->|存储| Redis
|
||||
|
||||
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
|
||||
WebSocketServerCallbackManager -->|调用| ServiceImpl1
|
||||
WebSocketServerCallbackManager -->|调用| ServiceImpl2
|
||||
WebSocketServerHandler -->|使用| WebSocketServerCallbackManager
|
||||
WebSocketServerTaskManager -->|使用| WebSocketServerCallbackManager
|
||||
```
|
||||
|
||||
## 4. 接口契约定义
|
||||
**依赖关系说明**:
|
||||
|
||||
### 4.1 IEntityService<Model>接口
|
||||
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<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);
|
||||
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);
|
||||
// 其他实体类操作方法
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 QueryService<Vo>接口
|
||||
**功能描述**:提供实体类的基本CRUD操作,泛型T表示实体类类型,ID表示实体类主键类型。
|
||||
|
||||
**实现说明**:
|
||||
- Service实现类需要实现此接口,确保实体类的基本操作功能正常。
|
||||
- 此接口主要用于后端内部的数据处理,不直接返回给前端。
|
||||
- 与QueryService<Vo>接口配合使用,实现数据访问和数据展示的分离。
|
||||
|
||||
### 5.2 QueryService<Vo>接口
|
||||
|
||||
**接口定义**:
|
||||
```java
|
||||
public interface QueryService<Vo> {
|
||||
// 根据ID查询Vo对象
|
||||
Vo findById(Integer id);
|
||||
@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方法
|
||||
|
||||
// 根据查询参数和分页条件获取Vo对象列表
|
||||
Page<Vo> findAll(JsonNode paramsNode, Pageable pageable);
|
||||
|
||||
// 计数方法
|
||||
default long count(JsonNode paramsNode) {
|
||||
return 0;
|
||||
@Override
|
||||
public CompanyFileTypeVo toVo() {
|
||||
CompanyFileTypeVo vo = new CompanyFileTypeVo();
|
||||
vo.setId(this.id);
|
||||
vo.setName(this.name);
|
||||
vo.setCode(this.code);
|
||||
// 只复制需要在前端展示的属性
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Service实现类接口契约
|
||||
## 6. 数据流向图
|
||||
|
||||
对于每个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. 数据流向图
|
||||
### 6.1 请求处理流程
|
||||
|
||||
```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
|
||||
graph TD
|
||||
Client[客户端请求]
|
||||
Controller[控制器]
|
||||
ServiceImpl[Service实现类]
|
||||
Repository[Repository]
|
||||
JPA[JPA]
|
||||
MySQL[MySQL数据库]
|
||||
Redis[Redis缓存]
|
||||
Vo[Vo对象]
|
||||
Model[Model实体类]
|
||||
|
||||
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
|
||||
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
|
||||
```
|
||||
|
||||
## 6. 异常处理策略
|
||||
**数据流向说明**:
|
||||
|
||||
1. **转换异常处理**:
|
||||
- 在实体类和VO类之间进行转换时,捕获并处理可能的转换异常
|
||||
- 提供清晰的错误信息,指明转换失败的原因
|
||||
1. **查询请求处理**:客户端发起查询请求,控制器接收请求并调用Service实现类的findById方法。
|
||||
|
||||
2. **数据验证**:
|
||||
- 在接收VO对象时,进行数据验证,确保数据的有效性
|
||||
- 对于无效数据,抛出适当的异常并提供错误信息
|
||||
2. **缓存检查**:Service实现类首先检查Redis缓存中是否存在对应的Vo对象。
|
||||
|
||||
3. **事务处理**:
|
||||
- 保持原有的事务边界,确保数据操作的原子性
|
||||
- 在事务中包含完整的数据操作和转换过程
|
||||
3. **缓存命中**:如果缓存命中,直接从缓存中获取Vo对象返回。
|
||||
|
||||
4. **缓存异常**:
|
||||
- 处理可能的缓存操作异常,确保即使缓存失败也不会影响业务逻辑
|
||||
- 考虑添加缓存回退机制
|
||||
- 特别处理Redis连接问题和序列化问题,确保系统可用性
|
||||
4. **缓存未命中**:如果缓存未命中,Service实现类通过Repository查询数据库获取实体类对象,然后将实体类对象转换为Vo对象,存入Redis缓存,并返回Vo对象。
|
||||
|
||||
5. **序列化异常**:
|
||||
- 处理VO对象序列化失败的情况
|
||||
- 确保VO类实现Serializable接口,避免在VO类中包含不可序列化的引用
|
||||
### 6.2 数据转换流程
|
||||
|
||||
6. **WebSocket服务异常处理**:
|
||||
- 处理WebSocketServerCallbackManager中反射调用IEntityService接口时可能出现的类型转换异常
|
||||
- 特别关注createNewEntity、findEntityTypeInInterfaces等依赖泛型参数的方法
|
||||
- 确保WebSocket服务在接口泛型修改后能够正常处理异常情况
|
||||
- 在invokerFindByIdMethod、invokerFindAllMethod等方法中添加类型安全检查
|
||||
```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[客户端]
|
||||
```
|
||||
|
||||
## 7. 设计原则
|
||||
**转换流程说明**:
|
||||
|
||||
1. **最小化修改原则**: 仅修改必要的代码,避免不必要的重构
|
||||
1. **数据查询**:从数据库查询实体类数据,通过Repository返回给Service实现类。
|
||||
|
||||
2. **向后兼容原则**: 尽量保持与原有系统的兼容性,特别是对依赖这些Service的组件,包括WebSocket服务
|
||||
2. **数据转换**:Service实现类调用实体类的toVo方法,将实体类数据转换为Vo对象。
|
||||
|
||||
3. **数据一致性原则**: 确保实体类和VO类之间的数据转换不会导致数据丢失或不一致
|
||||
3. **缓存存储**:转换后的Vo对象被存入Redis缓存中,以提高后续查询性能。
|
||||
|
||||
4. **可测试性原则**: 设计支持单元测试和集成测试的代码结构,包括WebSocket服务的测试
|
||||
4. **数据返回**:Vo对象通过控制器返回给客户端,用于前端展示。
|
||||
|
||||
5. **性能优化原则**: 考虑数据转换可能带来的性能影响,必要时进行优化
|
||||
## 7. 异常处理策略
|
||||
|
||||
6. **代码复用原则**: 尽量复用现有的代码和模式,特别是数据转换相关的代码
|
||||
### 7.1 转换异常处理
|
||||
|
||||
7. **序列化安全原则**: 确保所有缓存的VO对象都是可序列化的,避免在VO对象中包含循环引用和不可序列化的组件
|
||||
**场景**:实体类转换为Vo对象时发生异常
|
||||
|
||||
8. **类型安全原则**: 在WebSocketServerCallbackManager中添加类型安全检查,确保能够正确处理从实体类到VO类的泛型变化
|
||||
**处理策略**:
|
||||
- 使用try-catch块捕获转换过程中可能发生的异常
|
||||
- 记录异常日志,包括异常信息和上下文数据
|
||||
- 返回友好的错误提示,避免将系统内部错误暴露给前端
|
||||
- 针对关键业务,可以考虑使用补偿机制或降级处理
|
||||
|
||||
9. **服务兼容性原则**: 确保修改后的IEntityService接口能够与WebSocket服务和其他现有服务组件兼容
|
||||
**示例代码**:
|
||||
```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());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
通过以上设计,我们可以系统地完成IEntityService接口泛型的修改任务,确保修改后的系统能够正确、高效地运行。
|
||||
### 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. **代码复用原则**:提取通用的转换逻辑和缓存策略,提高代码的复用性。
|
||||
Reference in New Issue
Block a user