Files
contract-manager/docs/task/client_service_compliance_analysis.md
songqq 045a1e9eed docs: 添加Service层合规性分析报告文档
添加Contract-Manager项目Service层合规性分析报告,评估各Service实现是否符合规范要求,并列出不符合项和改进建议
2025-09-26 12:16:17 +08:00

8.4 KiB
Raw Blame History

Contract-Manager 项目 Service 层合规性分析报告

概述

本报告对 Contract-Manager 项目中 client\src\main\java\com\ecep\contract\service 目录下的 Service 实现进行分析,评估它们是否符合 docs\task\service_layer_rules.md 文档中定义的规则和最佳实践。

合规性评估

1. 基础架构

1.1 继承体系

  • 符合: 大多数业务 Service 都继承自泛型抽象类 QueryService<T extends IdentityEntity, TV extends IdentityViewModel<T>>
    • 例如: CompanyFileTypeService, ContractService, CompanyService, ProjectService, VendorService
  • 不符合: SysConfService 没有继承 QueryService,而是直接实现了自己的异步调用方法

1.2 核心接口实现

  • 符合: 继承 QueryService 的 Service 间接实现了 IEntityService<T>ViewModelService<T, TV> 接口

2. 缓存管理

2.1 缓存注解使用

  • 符合: 许多 Service 使用了 @CacheConfig 和相关缓存注解
    • @CacheConfig(cacheNames = "缓存名称"): ContractFileTypeService, ProjectFileTypeService, ContractService, CompanyService, SysConfService
    • @Cacheable: 用于 findById, findAll, findByCode 等查询方法
    • @CachePut/@CacheEvict: 用于 save, delete 等修改方法
    • @Caching: 用于组合多个缓存操作
  • 不符合: 部分 Service 未使用缓存注解
    • VendorService, ProjectService 没有配置缓存

2.2 缓存键规则

  • 符合: 缓存键的使用基本符合规则
    • #p0: 用于方法参数,如 @Cacheable(key = "#p0")
    • 'all': 用于所有数据,如 @Cacheable(key = "'all'")
    • 组合键: 如 @Cacheable(key = "'code-'+#p0")

3. 数据操作模式

3.1 基础 CRUD 操作

  • 符合: 所有继承 QueryService 的 Service 都获得了基础 CRUD 操作
    • findById(Integer id): 根据 ID 查询单条数据
    • save(T entity): 保存实体
    • delete(T entity): 删除实体
    • findAll(): 查询所有数据
    • findAll(Map<String, Object> params, Pageable pageable): 带参数和分页的查询

3.2 异步操作

  • 符合: 大多数 Service 使用 QueryService 提供的异步机制
    • 通过 async(String method, Object... params) 方法实现异步调用
    • 返回 CompletableFuture<JsonNode> 对象
  • 不符合: SysConfService 实现了自己的异步方法,如 asyncFindById, asyncFindAll

3.3 业务查询方法

  • 符合: 业务 Service 通常添加特定的查询方法
    • findByCode(String code): ContractService, CompanyService, ProjectService
    • findByName(String name): ContractService, CompanyService, ProjectService
    • findAllByName(String name): CompanyService

3.4 参数构建

  • 符合: 普遍使用 ParamUtils 工具类构建查询参数
    • ParamUtils.builder().equals("字段名", 值).build()
    • ParamUtils.equal("字段名", 值)

4. 国际化支持

4.1 多语言查询

  • 符合: 文件类型相关 Service 提供了基于 Locale 的查询方法
    • findAll(Locale locale): ContractFileTypeService, ProjectFileTypeService, CompanyFileTypeService, CompanyCustomerFileTypeService
    • 通过 locale.toLanguageTag() 转换为语言标签进行查询
    • 返回结果通常转换为 Map方便按类型查找
  • 不适用: 对于不需要国际化的业务 Service没有提供这些方法

4.2 辅助方法

  • 符合: 文件类型相关 Service 实现了辅助方法
    • findOneByLang(Locale locale, String key, Object value): 私有辅助方法
    • findByLocaleAndValue(Locale locale, String string): 按语言和值查询
    • findByLocaleAndType(Locale locale, EnumType type): 按语言和枚举类型查询
  • 不适用: 对于不需要国际化的业务 Service没有提供这些方法

5. 类型转换

5.1 StringConverter 实现

  • 符合: 实体类型 Service 实现了 getStringConverter() 方法
    • 返回 StringConverter<T> 实例
    • 创建专门的 Converter 类,如 ContractFileTypeStringConverter, ProjectFileTypeStringConverter
  • 不符合: 业务对象 Service 如 ContractService, CompanyService, VendorService, ProjectService 没有实现 getStringConverter() 方法

6. 业务特性

6.1 文件路径管理

  • 符合: 部分 Service 管理文件路径
    • getBasePath() 方法: ContractService, CompanyService, VendorService, ProjectService
    • 通过 SysConfService 获取配置的基础路径
    • 路径存储为 File 对象

6.2 业务验证

  • 符合: 包含业务特定的验证逻辑
    • verifyEnterpriseStatus(CompanyVo company, LocalDate verifyDate, MessageHolder holder): CompanyService
    • verify(ContractVo contract, MessageHolder holder): VendorService
    • 使用 MessageHolder 存储验证结果和错误信息

6.3 Spring Bean 获取

  • 符合: 使用 SpringApp.getBean(ServiceClass.class) 获取其他 Service 实例
    • 例如 VendorService 中获取 SysConfServiceProjectService 中获取 ProjectSaleTypeService

7. 代码规范

7.1 类命名

  • 符合: 服务类名以 Service 结尾
    • ContractService, CompanyService, ProjectService
    • 实现类直接使用业务名称+Service无 I 前缀

7.2 注释规范

  • 部分符合: 大部分类和方法有 Javadoc 注释
    • 例如 ContractService.getBasePath() 方法有清晰的注释
  • 不符合: 部分方法缺少注释
    • 例如 VendorService.findByCompany() 方法没有注释
    • 许多未实现的方法只有 TODO 注释

7.3 异常处理

  • 符合: 使用 RuntimeException 包装异常
    • 异常消息清晰描述错误情况
  • 不符合: SysConfService 中有些异常处理直接打印堆栈,没有抛出自定义异常

8. 特定业务 Service 模式

8.1 实体类型 Service

  • 符合: 如 ContractFileTypeService, ProjectFileTypeService
    • 管理枚举类型的本地化数据
    • 提供缓存管理
    • 实现 StringConverter
    • 提供基于 Locale 的查询方法

8.2 业务对象 Service

  • 符合: 如 ContractService, CompanyService, ProjectService
    • 管理核心业务实体
    • 实现特定的业务逻辑
    • 处理文件和路径
    • 提供业务验证

8.3 关联关系管理

  • 符合: Service 之间通过依赖注入或 SpringApp.getBean() 进行协作
    • 处理实体之间的关联关系

9. 特殊实现模式

9.1 自定义 BeanName

  • 符合: 部分 Service 重写 getBeanName() 方法
    • 例如 CompanyService 指定 WebSocket 通信的 Bean 名称

9.2 未实现方法

  • 符合: 使用 throw new UnsupportedOperationException("Unimplemented method 'methodName'") 标记未实现的方法
    • 例如 CompanyService.merge(), VendorService.getVendorApprovedListTemplate()

9.3 分页查询

  • 符合: 大量使用 Pageable.ofSize(1) 进行单条记录的精确查询
    • 使用 stream().findFirst().orElse(null) 提取结果
    • 例如 ProjectService.findByName(), ProjectService.findByCode()

不符合规范的 Service 列表

Service 类名 不符合项 建议改进
SysConfService 未继承 QueryService,实现了自己的异步方法 重构为继承 QueryService,使用标准的异步方法
VendorService 未使用缓存注解 添加 @CacheConfig 和相关缓存注解
ProjectService 未使用缓存注解 添加 @CacheConfig 和相关缓存注解
业务对象 Service 没有实现 getStringConverter() 方法 如果需要类型转换,实现该方法
多个 Service 部分方法缺少注释 完善 Javadoc 注释
SysConfService 异常处理不统一 统一使用 RuntimeException 包装异常

总结

Contract-Manager 项目的 Service 层实现整体上符合 service_layer_rules.md 文档中定义的规则和最佳实践。大多数 Service 遵循了基础架构、缓存管理、数据操作模式等规范,特别是实体类型 Service 的实现非常一致。

主要的改进点包括:

  1. 统一 Service 的继承体系,确保所有 Service 都继承自 QueryService
  2. 为所有 Service 添加适当的缓存管理
  3. 完善方法注释,提高代码可读性
  4. 统一异常处理机制
  5. 根据业务需求,为需要类型转换的 Service 实现 getStringConverter() 方法

通过这些改进,可以进一步提高项目的代码一致性、可维护性和性能。