# 客户端转换器类规则 ## 1. 目录结构 - 所有类型转换器类必须位于 `com.ecep.contract.converter` 包下 - 按照实体类型组织,无需进一步分包 ## 2. 命名规范 - 类名格式:`[EntityName]StringConverter` - 例如:`ContractStringConverter`、`CompanyStringConverter`、`VendorStringConverter` ## 3. 继承关系 ### 3.1 基础转换器类型 - 直接继承 `javafx.util.StringConverter` 接口 - 适用于简单的转换场景 - 例如: ```java public class ContractStringConverter extends StringConverter { // 实现代码 } ``` ### 3.2 增强转换器类型 - 继承自定义的 `EntityStringConverter` 抽象类 - 适用于需要更多功能(如延迟初始化、搜索建议等)的场景 - 大多数业务实体转换器应使用此类型 - 例如: ```java public class CompanyStringConverter extends EntityStringConverter { // 实现代码 } ``` ### 3.3 枚举转换器类型 - 继承 `EnumEntityStringConverter, T extends BaseEnumEntity>` - 专门用于处理枚举类型实体 - 例如: ```java public class EnumEntityStringConverter, T extends BaseEnumEntity> extends StringConverter { // 实现代码 } ``` ## 4. 核心接口实现 ### 4.1 StringConverter 接口 - 所有转换器必须实现 `toString(T object)` 方法 - 所有转换器必须实现 `fromString(String string)` 方法 ## 5. Spring框架集成 ### 5.1 组件注解 - 增强转换器类型通常使用 `@Component` 注解标记为Spring组件 - 结合 `@Lazy` 注解实现延迟加载 - 例如: ```java @Lazy @Component public class CompanyStringConverter extends EntityStringConverter { // 实现代码 } ``` ### 5.2 依赖注入 - 使用 `@Autowired` 注解注入对应的Service实例 - 通常也需要为注入的Service添加 `@Lazy` 注解 - 例如: ```java @Lazy @Autowired private CompanyService service; ``` ## 6. 初始化机制 ### 6.1 构造函数 - 基础转换器通常使用构造函数接收Service实例 - 例如: ```java public ContractStringConverter(ContractService service) { this.service = service; } ``` ### 6.2 初始化方法 - 增强转换器使用 `@PostConstruct` 注解标记初始化方法 - 在初始化方法中配置转换器的各种功能 - 例如: ```java @PostConstruct private void init() { setInitialized(project -> service.findById(project.getId())); setSuggestion(service::search); setFromString(service::findByName); } ``` ## 7. EntityStringConverter 特性配置 继承自 EntityStringConverter 的增强转换器可以配置以下特性: ### 7.1 对象初始化 - 使用 `setInitialized(Function initialized)` 配置对象延迟初始化逻辑 - 通常调用Service的findById方法 - 例如:`setInitialized(project -> service.findById(project.getId()))` ### 7.2 搜索建议 - 使用 `setSuggestion(Function> suggestion)` 配置自动补全数据提供方法 - 通常调用Service的search方法 - 例如:`setSuggestion(service::search)` ### 7.3 字符串转换 - 使用 `setFromString(Function fromString)` 配置从字符串到对象的转换逻辑 - 通常调用Service的findByName方法 - 例如:`setFromString(service::findByName)` ### 7.4 格式化器 - 使用 `setFormater(Function formater)` 配置自定义格式化逻辑 - 用于自定义对象的字符串表示 - 例如:`setFormater(contract -> contract.getCode() + " " + contract.getName())` ## 8. 核心方法实现规范 ### 8.1 toString(T object) 方法 - 将对象转换为可读的字符串表示 - 必须处理null情况 - 通常返回对象的名称、编码或其他关键标识 - 对于基础转换器: ```java @Override public String toString(ContractVo cc) { return cc.getCode() + " " + cc.getName(); } ``` - 对于枚举转换器: ```java @Override public String toString(T object) { return object == null ? "" : object.getValue(); } ``` ### 8.2 fromString(String string) 方法 - 从字符串还原对象实例 - 通常调用Service的findByName或findByCode方法 - 例如: ```java @Override public ContractVo fromString(String string) { return service.findByCode(string); } ``` - 对于某些场景(如枚举转换器),可能返回null ## 9. 与Service类的关联 ### 9.1 Service中的转换器创建 - 在Service类中通常会创建并持有对应的StringConverter实例 - 实现 `getStringConverter()` 方法返回转换器实例 - 例如: ```java @Service @CacheConfig(cacheNames = "contract-cache") public class ContractService extends QueryService { private final ContractStringConverter stringConverter = new ContractStringConverter(this); @Override public StringConverter getStringConverter() { return stringConverter; } } ``` ### 9.2 Service方法支持 - Service需提供 `findByName`、`findById`、`search` 等方法供转换器使用 - 这些方法通常需要添加缓存注解以提高性能 ## 10. 使用场景 StringConverter主要用于以下场景: - ComboBox、ChoiceBox等选择组件的数据绑定和显示 - 表单数据的绑定和转换 - 支持用户输入的自动补全功能 - 在表格、列表等UI组件中显示对象的可读表示 ## 11. 最佳实践 - 对于大多数业务实体,优先使用继承 `EntityStringConverter` 的增强转换器 - 使用Spring的依赖注入和组件管理功能 - 正确处理null值和空字符串 - 为频繁调用的Service方法添加缓存支持 - 实现合理的toString逻辑,提供有意义的对象表示 ## 12. 示例代码结构 ### 12.1 基础转换器示例 ```java package com.ecep.contract.converter; import com.ecep.contract.service.ContractService; import com.ecep.contract.vo.ContractVo; import javafx.util.StringConverter; public class ContractStringConverter extends StringConverter { private final ContractService service; public ContractStringConverter(ContractService service) { this.service = service; } @Override public String toString(ContractVo cc) { return cc == null ? "" : cc.getCode() + " " + cc.getName(); } @Override public ContractVo fromString(String string) { return string == null || string.isEmpty() ? null : service.findByCode(string); } } ``` ### 12.2 增强转换器示例 ```java package com.ecep.contract.converter; import com.ecep.contract.service.CompanyService; import com.ecep.contract.vo.CompanyVo; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @Lazy @Component public class CompanyStringConverter extends EntityStringConverter { @Lazy @Autowired private CompanyService service; @PostConstruct private void init() { setInitialized(company -> service.findById(company.getId())); setSuggestion(service::search); setFromString(service::findByName); } } ```