# 6A工作流 - 架构阶段 # 任务名: Server模块Service缓存调整为Vo对象 ## 1. 整体架构图 ```mermaid graph TD subgraph 客户端层 Client[客户端应用] end subgraph 控制器层 Controller[REST控制器] end subgraph 服务层 IEntityService_Int[IEntityService接口] QueryService_Int[QueryService接口] VoableService_Int[VoableService接口] 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接口] 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、QueryService和VoableService - 分离实体操作和查询操作,使系统更符合单一职责原则 - 添加基于Vo对象的更新和创建操作方法 ### 2.3 数据转换层 - 引入Voable接口,定义实体类到Vo类的转换方法 - 所有实体类实现Voable接口,提供具体的转换逻辑 - Service层负责调用转换方法并管理转换过程中的异常处理 ### 2.4 依赖组件兼容性 - 特别关注WebSocketServerCallbackManager、WebSocketServerHandler等依赖组件对Service接口的调用方式 - 增强这些组件的类型处理逻辑,确保它们能够正确处理Service类的新泛型参数 ## 3. 分层设计和核心组件 ### 3.1 客户端层 - **职责**:发起HTTP请求,接收和展示返回的Vo对象数据 - **组件**:前端应用程序 ### 3.2 控制器层 - **职责**:接收客户端请求,调用相应的服务方法,返回处理结果 - **组件**:REST控制器 - **关键特性**:处理请求路由和参数解析,异常统一处理 ### 3.3 服务层 - **职责**:实现业务逻辑,处理数据转换,管理缓存策略 - **核心接口**: - IEntityService:提供实体类的基本CRUD操作 - QueryService:提供Vo对象的查询操作并实现缓存 - VoableService:提供基于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接口] QueryService_Int[QueryService接口] VoableService_Int[VoableService接口] 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接口] 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、QueryService和VoableService三个接口,提供具体的业务逻辑实现。 2. **服务实现与数据访问**:Service实现类依赖Repository接口进行数据访问操作,Repository接口依赖Spring Data JPA实现数据持久化。 3. **服务实现与数据模型**:Service实现类操作实体类,并通过Voable接口将实体类转换为Vo类。 4. **服务实现与缓存机制**:Service实现类使用Spring Cache注解对查询结果进行缓存,缓存数据存储在Redis中。 5. **依赖组件与服务实现**:WebSocket相关组件依赖Service实现类提供的数据操作功能,需要特别关注这些组件对Service接口的调用方式。 ## 5. 接口契约定义 ### 5.1 IEntityService接口 **接口定义**: ```java public interface IEntityService { T findById(ID id); List findAll(); Page findAll(Pageable pageable); T save(T entity); void deleteById(ID id); // 其他实体类操作方法 } ``` **功能描述**:提供实体类的基本CRUD操作,泛型T表示实体类类型,ID表示实体类主键类型。 **实现说明**: - Service实现类需要实现此接口,确保实体类的基本操作功能正常。 - 此接口主要用于后端内部的数据处理,不直接返回给前端。 - 与QueryService接口配合使用,实现数据访问和数据展示的分离。 ### 5.2 QueryService接口 **接口定义**: ```java public interface QueryService { @Cacheable(key = "#id", unless = "#result == null") Vo findById(Object id); Page 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 findAll(Pageable pageable) { // 1. 调用IEntityService的findAll方法获取实体对象的Page Page entityPage = super.findAll(pageable); // 2. 将实体对象的Page转换为Vo对象的Page return entityPage.map(CompanyFileType::toVo); } ``` ### 5.3 VoableService接口 **接口定义**: ```java public interface VoableService { 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 toVo(); } ``` **功能描述**:定义实体类到Vo类的转换方法,泛型Vo表示目标视图对象类型。 **实现说明**: - 所有实体类都需要实现此接口,提供具体的转换逻辑。 - toVo方法负责将实体类的属性值映射到Vo类的对应属性。 **实现示例**: ```java public class CompanyFileType implements Voable { // 实体类属性 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 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. **代码复用原则**:提取通用的转换逻辑和缓存策略,提高代码的复用性。