feat(service): 实现国际化支持并优化Service层

重构文件类型相关Service以支持国际化查询
添加findOneByLang辅助方法统一查询逻辑
实现StringConverter支持UI控件显示
优化缓存配置和查询性能
新增UnitStringConverter和CustomerCatalogStringConverter
完善文档和测试用例
This commit is contained in:
2025-09-24 16:20:49 +08:00
parent 45eed8281f
commit 09b0da498b
32 changed files with 1968 additions and 78 deletions

View File

@@ -0,0 +1,150 @@
# Contract-Manager 项目 Service 层规则与逻辑总结
## 1. 基础架构
### 1.1 继承体系
- 所有业务Service都继承自泛型抽象类 `QueryService<T extends IdentityEntity, TV extends IdentityViewModel<T>>`
- `QueryService` 实现了 `IEntityService<T>``ViewModelService<T, TV>` 接口
- 泛型参数说明:
- `T`: 实体类型通常为Vo类
- `TV`: 视图模型类型
### 1.2 核心接口
`IEntityService<T>` 定义了基础的实体操作方法:
```java
public interface IEntityService<T> {
T findById(Integer id);
T save(T entity);
void delete(T entity);
List<T> findAll();
Page<T> findAll(Map<String, Object> params, Pageable pageable);
StringConverter<T> getStringConverter();
}
```
## 2. 缓存管理
### 2.1 缓存注解使用
- 使用 `@CacheConfig(cacheNames = "缓存名称")` 设置缓存名称
- 使用 `@Cacheable` 注解标记查询方法,如 `findById``findAll`
- 使用 `@CachePut` 注解标记更新方法,如 `save``delete`
- 使用 `@CacheEvict` 注解标记清除缓存的方法
- 使用 `@Caching` 组合多个缓存操作
### 2.2 缓存键规则
- `#p0`: 表示方法的第一个参数
- `'all'`: 表示所有数据的缓存键
- `'code-'+#p0`: 组合键,如 `'code-'+#p0.code` 用于按编码缓存
## 3. 数据操作模式
### 3.1 基础CRUD操作
所有Service通过继承`QueryService`获得以下基础操作:
- `findById(Integer id)`: 根据ID查询单条数据
- `save(T entity)`: 保存实体
- `delete(T entity)`: 删除实体
- `findAll()`: 查询所有数据
- `findAll(Map<String, Object> params, Pageable pageable)`: 带参数和分页的查询
### 3.2 异步操作
- 通过 `async(String method, Object... params)` 方法实现异步调用
- 返回 `CompletableFuture<JsonNode>` 对象
- 有专门的异步查询方法,如 `asyncFindById``asyncFindAll``asyncCount`
### 3.3 业务查询方法
业务Service通常会添加特定的查询方法
- `findByCode(String code)`: 按编码查询
- `findByName(String name)`: 按名称查询
- `findAllByName(String name)`: 按名称查询所有匹配项
### 3.4 参数构建
- 使用 `ParamUtils` 工具类构建查询参数
- 常用方法:`ParamUtils.builder().equals("字段名", 值).build()`
## 4. 国际化支持
### 4.1 多语言查询
- 所有继承自`BaseEnumEntity`的Vo类对应的Service都必须实现国际化支持
- 提供基于Locale的查询方法`findAll(Locale locale)`
- 实现方式:通过 `locale.toLanguageTag()` 转换为语言标签进行查询
- 返回结果通常转换为Map<EnumType, EntityType>,以枚举类型为键,方便按类型查找
- 方法上应添加`@Cacheable`注解进行缓存
### 4.2 辅助方法
- 必须实现`findOneByLang(Locale locale, String key, Object value)`私有辅助方法,根据语言和参数查找单个对象
- 实现方式:使用`ParamUtils.builder().equals("lang", locale.toLanguageTag()).equals(key, value).build()`构建参数
- 使用`Pageable.ofSize(1)`进行单条记录的精确查询
- 使用`stream().findFirst().orElse(null)`提取结果
- 必须实现`findByLocaleAndValue(Locale locale, String string)`方法,按语言和值查询
- 调用`findOneByLang(locale, "value", string)`实现
- 必须实现`findByLocaleAndType(Locale locale, EnumType type)`方法,按语言和枚举类型查询
- 调用`findOneByLang(locale, "type", type)`实现
## 5. 类型转换
### 5.1 StringConverter实现
- 所有Service都实现 `getStringConverter()` 方法,返回 `StringConverter<T>` 实例
- 通常会创建专门的Converter类`CompanyFileTypeStringConverter``CustomerFileTypeStringConverter`
- Converter类通常接收对应的Service作为构造参数
## 6. 业务特性
### 6.1 文件路径管理
- 部分Service管理文件路径`getBasePath()` 方法
- 通常通过 `SysConfService` 获取配置的基础路径
- 路径存储为 `File` 对象
### 6.2 业务验证
- 包含业务特定的验证逻辑,如 `verifyEnterpriseStatus``verify` 方法
- 使用 `MessageHolder` 存储验证结果和错误信息
### 6.3 Spring Bean获取
- 使用 `SpringApp.getBean(ServiceClass.class)` 获取其他Service实例
- 用于Service之间的协作调用
## 7. 代码规范
### 7.1 类命名
- 服务类名以 `Service` 结尾,如 `ContractService``CompanyService`
- 实现类直接使用业务名称+Service无I前缀
### 7.2 注释规范
- 方法和类应有清晰的Javadoc注释
- 私有辅助方法也应有注释说明其用途
### 7.3 异常处理
- 使用 `RuntimeException` 包装所有异常
- 异常消息应清晰描述错误情况
- 部分Service使用日志记录错误信息
## 8. 特定业务Service模式
### 8.1 实体类型Service
`CompanyFileTypeService``CompanyCustomerFileTypeService` 等:
- 管理枚举类型的本地化数据
- 提供缓存管理
- 实现StringConverter
- 提供基于Locale的查询方法
### 8.2 业务对象Service
`ContractService``CompanyService``ProjectService` 等:
- 管理核心业务实体
- 实现特定的业务逻辑
- 处理文件和路径
- 提供业务验证
### 8.3 关联关系管理
- Service之间通过依赖注入或 `SpringApp.getBean()` 进行协作
- 处理实体之间的关联关系,如 `Contract``Company``Vendor`
## 9. 特殊实现模式
### 9.1 自定义BeanName
部分Service重写 `getBeanName()` 方法指定WebSocket通信的Bean名称
### 9.2 未实现方法
使用 `throw new UnsupportedOperationException("Unimplemented method 'methodName'")` 标记未实现的方法
### 9.3 分页查询
- 大量使用 `Pageable.ofSize(1)` 进行单条记录的精确查询
- 使用 `stream().findFirst().orElse(null)` 提取结果