Files
contract-manager/docs/task/service_compliance_analysis.md
songqq 09b0da498b feat(service): 实现国际化支持并优化Service层
重构文件类型相关Service以支持国际化查询
添加findOneByLang辅助方法统一查询逻辑
实现StringConverter支持UI控件显示
优化缓存配置和查询性能
新增UnitStringConverter和CustomerCatalogStringConverter
完善文档和测试用例
2025-09-24 16:20:49 +08:00

180 lines
8.4 KiB
Markdown
Raw 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.

# 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` 中获取 `SysConfService``ProjectService` 中获取 `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()` 方法
通过这些改进,可以进一步提高项目的代码一致性、可维护性和性能。