refactor(model): 重构模型类包结构并优化序列化处理
重构模型类包结构,将模型类按功能模块划分到不同的子包中。优化序列化处理,为VO类添加serialVersionUID并实现Serializable接口。移除部分冗余的serialVersionUID字段,简化模型类代码。同时修复UITools中空值处理的问题,并更新pom版本至0.0.100-SNAPSHOT。 - 将模型类按功能模块划分到ds子包中 - 为VO类添加序列化支持 - 移除冗余的serialVersionUID字段 - 修复UITools空值处理问题 - 更新项目版本号
This commit is contained in:
146
.trae/rules/client_service_rules.md
Normal file
146
.trae/rules/client_service_rules.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# 客户端 Service 类规则
|
||||
|
||||
## 1. 目录结构
|
||||
- 所有客户端 Service 类位于 `client/src/main/java/com/ecep/contract/service/` 目录下
|
||||
- 按业务领域组织,直接放置在 service 包下,不进行子包划分
|
||||
- 服务类命名与实体类一一对应
|
||||
|
||||
## 2. 命名规范
|
||||
- 服务类命名格式为:`[实体名称]Service.java`
|
||||
- 例如:`CompanyService.java`、`ContractService.java`、`ProjectService.java`
|
||||
- 基础服务接口命名为:`IEntityService.java`、`ViewModelService.java`
|
||||
- 泛型基础服务类命名为:`QueryService.java`
|
||||
|
||||
## 3. 继承关系
|
||||
- 业务服务类通常继承自泛型基础服务类 `QueryService<T, TV>`
|
||||
- `T` 表示 VO 类型(实现了 IdentityEntity 接口)
|
||||
- `TV` 表示 ViewModel 类型(实现了 IdentityViewModel<T> 接口)
|
||||
- `QueryService` 实现了 `ViewModelService<T, TV>` 接口
|
||||
- `ViewModelService` 继承了 `IEntityService<T>` 接口
|
||||
- 特定场景下可以不继承 `QueryService`,直接实现所需接口或创建独立服务类
|
||||
|
||||
```java
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "company")
|
||||
public class CompanyService extends QueryService<CompanyVo, CompanyViewModel> {
|
||||
// 业务方法实现
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 注解使用
|
||||
- **@Service**:标记为 Spring 服务组件,使其可被自动发现和注入
|
||||
- **@CacheConfig**:配置缓存名称,通常与服务类名对应
|
||||
- **@Cacheable**:标记方法结果可缓存,需指定缓存键(key)
|
||||
- **@CacheEvict**:标记方法执行后清除缓存,可指定缓存键或清除所有
|
||||
- **@Caching**:组合多个缓存操作(如同时清除多个缓存条目)
|
||||
- **@Autowired**:用于自动注入依赖的其他服务
|
||||
|
||||
```java
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract")
|
||||
public class ContractService extends QueryService<ContractVo, ContractViewModel> {
|
||||
@Autowired
|
||||
private SysConfService confService;
|
||||
|
||||
@Cacheable(key = "#p0")
|
||||
public ContractVo findById(Integer id) {
|
||||
return super.findById(id);
|
||||
}
|
||||
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#p0.id"),
|
||||
@CacheEvict(key = "'code-'+#p0.code")
|
||||
})
|
||||
public ContractVo save(ContractVo contract) {
|
||||
return super.save(contract);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 缓存机制
|
||||
- 每个服务类应有独立的缓存名称空间
|
||||
- 缓存键(key)应具有唯一性,通常使用 ID、代码或名称等唯一标识
|
||||
- 保存和删除操作时应清除相关缓存,保持数据一致性
|
||||
- 可使用 SpEL 表达式动态生成缓存键
|
||||
- 频繁查询的数据应考虑缓存,提高性能
|
||||
|
||||
## 6. 异步调用机制
|
||||
- 使用 `async()` 方法进行异步远程调用
|
||||
- 方法参数通常包括:方法名、参数值、参数类型列表
|
||||
- 使用 `CompletableFuture` 处理异步结果
|
||||
- 使用 `handle()` 方法处理响应和异常
|
||||
- 远程调用异常应包装为 RuntimeException 并提供详细错误信息
|
||||
|
||||
```java
|
||||
@Cacheable(key = "'code-'+#p0")
|
||||
public ContractVo findByCode(String code) {
|
||||
try {
|
||||
return async("findByCode", code, String.class).handle((response, ex) -> {
|
||||
if (ex != null) {
|
||||
throw new RuntimeException("远程方法+findByCode+调用失败", ex);
|
||||
}
|
||||
if (response != null) {
|
||||
return updateValue(createNewEntity(), response);
|
||||
}
|
||||
return null;
|
||||
}).get();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("查询失败: " + code, e);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 基础方法实现
|
||||
- 应实现 `IEntityService<T>` 接口定义的核心方法:
|
||||
- `findById(Integer id)`:根据 ID 查询实体
|
||||
- `save(T entity)`:保存实体
|
||||
- `delete(T entity)`:删除实体
|
||||
- `findAll()`:查询所有实体
|
||||
- `findAll(Map<String, Object> params, Pageable pageable)`:条件分页查询
|
||||
- `getStringConverter()`:获取类型转换器
|
||||
- 通常通过继承 `QueryService` 来复用这些基础方法的实现
|
||||
- 可根据业务需求重写或扩展基础方法
|
||||
|
||||
## 8. 业务方法规范
|
||||
- 业务方法应与服务端对应,保持方法名和参数一致
|
||||
- 方法命名应清晰表达其功能,如 `findByName`, `findByCode`
|
||||
- 复杂业务逻辑应封装为独立方法
|
||||
- 参数校验应在方法开始处进行
|
||||
- 返回值类型应明确,避免使用过于泛化的类型
|
||||
|
||||
## 9. 类型转换器
|
||||
- 实现 `getStringConverter()` 方法,返回对应的 StringConverter 实例
|
||||
- 通常创建专用的 Converter 类,如 `CustomerCatalogStringConverter`
|
||||
- 转换器实例应作为服务类的成员变量,避免重复创建
|
||||
|
||||
```java
|
||||
public class CustomerCatalogService extends QueryService<CustomerCatalogVo, CustomerCatalogViewModel> {
|
||||
private final CustomerCatalogStringConverter stringConverter = new CustomerCatalogStringConverter(this);
|
||||
|
||||
@Override
|
||||
public StringConverter<CustomerCatalogVo> getStringConverter() {
|
||||
return stringConverter;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 10. 错误处理
|
||||
- 远程调用异常应捕获并包装为更具描述性的 RuntimeException
|
||||
- 提供详细的错误信息,包括调用的方法名和参数
|
||||
- 对于可预期的业务异常,可添加专门的处理逻辑
|
||||
- 不推荐使用 printStackTrace(),应使用日志记录异常
|
||||
|
||||
## 11. 工具方法和辅助功能
|
||||
- 通用功能可封装为工具方法
|
||||
- 配置相关操作可通过 `SysConfService` 实现
|
||||
- 文件路径处理应使用 `File` 类和相关工具方法
|
||||
- 日期时间处理应使用 Java 8+ 的日期时间 API
|
||||
|
||||
## 12. 最佳实践
|
||||
- 遵循单一职责原则,每个服务类专注于一个业务领域
|
||||
- 优先使用继承和接口实现来复用代码
|
||||
- 合理使用缓存提高性能,但注意缓存一致性
|
||||
- 异步调用应正确处理异常和超时情况
|
||||
- 服务类之间的依赖应通过 `@Autowired` 注入,避免硬编码
|
||||
- 方法实现应简洁明了,复杂逻辑应拆分
|
||||
- 为重要方法添加 JavaDoc 注释,说明其功能和参数含义
|
||||
Reference in New Issue
Block a user