重构模型类包结构,将模型类按功能模块划分到不同的子包中。优化序列化处理,为VO类添加serialVersionUID并实现Serializable接口。移除部分冗余的serialVersionUID字段,简化模型类代码。同时修复UITools中空值处理的问题,并更新pom版本至0.0.100-SNAPSHOT。 - 将模型类按功能模块划分到ds子包中 - 为VO类添加序列化支持 - 移除冗余的serialVersionUID字段 - 修复UITools空值处理问题 - 更新项目版本号
6.5 KiB
6.5 KiB
客户端 Controller 类规则
1. 目录结构
客户端控制器位于client/src/main/java/com/ecep/contract/controller/目录下,按业务模块组织:
- 根目录:包含基础控制器、抽象控制器和主窗口控制器
- 业务子包:按业务领域组织,如
company/、project/、contract/、vendor/等 - tab/子包:包含所有Tab皮肤控制器和相关接口、抽象类
- table/子包:包含表格相关控制器和单元格实现
2. 命名规范
- 基础控制器:
BaseController.java - 抽象控制器:以
Abst开头,如AbstEntityController.java、AbstManagerWindowController.java - 窗口控制器:以
WindowController结尾,如HomeWindowController.java - 管理窗口控制器:以
ManagerWindowController结尾,如CompanyManagerWindowController.java - Tab皮肤控制器:以
TabSkin结尾,如CompanyTabSkinBase.java - 管理器皮肤:以
ManagerSkin结尾,如CompanyManagerSkin.java - 组件控制器:如
OkHttpLoginController.java
3. 继承关系
控制器类遵循以下继承层次结构:
BaseController:所有控制器的基础类,提供窗口显示、异常处理等通用功能AbstEntityBasedController:基于实体的控制器抽象类AbstManagerWindowController:管理窗口控制器的抽象类,包含搜索、分页等功能
AbstEntityController<T extends IdentityEntity, TV extends IdentityViewModel<T>>:实体详情窗口控制器的抽象类- 具体业务窗口控制器,如
CompanyWindowController、ProjectWindowController等
- 具体业务窗口控制器,如
Tab相关控制器继承关系:
Skin:皮肤接口基础TabSkin:Tab皮肤接口AbstGenericTabSkin<C extends BaseController>:通用Tab皮肤抽象类AbstEntityBasedTabSkin<C extends AbstEntityController<T, V>, T extends IdentityEntity, V extends IdentityViewModel<T>>:基于实体的Tab皮肤抽象类- 具体业务Tab皮肤控制器,如
CompanyTabSkinBase.java、ContractTabSkinFiles.java等
- 具体业务Tab皮肤控制器,如
4. 注解使用
客户端控制器类应使用以下注解:
@Component:声明为Spring组件,使其可被Spring容器管理@Scope("prototype"):设置为原型作用域,确保每次请求创建新实例@Lazy:延迟加载,提高应用启动性能@FxmlPath("/ui/[业务模块]/[文件名].fxml"):指定对应的FXML文件路径@Autowired:自动注入依赖的服务层组件
5. FXML文件规范
- 文件位置:FXML文件通常位于
/client/src/main/resources/ui/目录下,按业务模块组织子目录 - 命名规范:使用小写字母和下划线,如
home.fxml、company/company.fxml - 关联方式:通过
@FxmlPath注解指定控制器对应的FXML文件路径 - 组件ID:FXML文件中组件的id应与控制器中对应的字段名保持一致(驼峰命名法)
6. 控制器方法规范
6.1 初始化方法
initialize():控制器初始化方法,用于设置UI组件初始状态、绑定事件监听器等- 此方法会在FXML加载完成后自动调用
6.2 窗口生命周期方法
onShown(WindowEvent windowEvent):窗口显示时触发的方法- 用于执行窗口显示后的初始化操作,如数据加载、组件状态更新等
- 通常需要调用
super.onShown(windowEvent)确保父类逻辑执行
6.3 窗口显示方法
public static void show():静态方法,用于便捷地显示控制器对应的窗口- 通常有多个重载版本,支持不同参数(如viewModel、owner窗口等)
- 内部调用
BaseController.show()方法实现窗口显示逻辑
6.4 Tab相关方法
Tab皮肤控制器包含以下核心方法:
install():安装Tab皮肤,加载FXML并初始化UI组件initializeUIComponents():初始化UI组件,设置数据绑定和事件监听getTab():获取对应的Tab对象save():保存Tab中的数据变更dispose():释放资源,清理监听器等
7. 字段规范
- UI组件字段:与FXML文件中的组件id对应,使用
public访问修饰符 - 服务依赖字段:使用
@Autowired注解注入,通常使用private访问修饰符 - ViewModel字段:通常作为控制器的核心数据模型,提供
getter/setter方法 - 命名规范:使用驼峰命名法,如
nameField、tabPane、saveBtn等
8. 数据绑定与更新
- ViewModel绑定:控制器通常通过ViewModel与实体数据进行绑定
- 异步数据加载:使用
CompletableFuture进行异步数据加载,避免阻塞UI线程 - UI更新:在JavaFX应用线程中更新UI组件,可使用
Platform.runLater()确保线程安全
9. 事件处理
- 按钮点击事件:通过
setOnAction()方法绑定事件处理器 - 表单字段变更:可通过JavaFX的属性绑定机制监听字段变更
- Tab切换事件:实现
onTabShown()方法处理Tab显示事件
10. 异常处理
- 使用
handleException()方法统一处理异常 - 异常信息通常会显示在状态栏并记录日志
- 异步操作中的异常应通过
exceptionally()或handle()方法捕获处理
11. 最佳实践
- 职责分离:控制器应专注于UI交互和数据展示,业务逻辑应委托给服务层
- 避免重复代码:利用抽象类和接口提取通用逻辑
- 资源管理:及时释放资源,避免内存泄漏
- 线程安全:确保在JavaFX应用线程中更新UI
- 代码可读性:添加适当的注释,遵循命名规范
12. 示例代码结构
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/[模块名]/[文件名].fxml")
public class [业务]WindowController extends AbstEntityController<[Vo类型], [ViewModel类型]> {
private static final Logger logger = LoggerFactory.getLogger([业务]WindowController.class);
@Autowired
private [业务]Service [业务]Service;
// UI组件字段
public BorderPane root;
public TabPane tabPane;
public TextField nameField;
// ...其他UI组件
public static void show([Vo类型] entity, Window window) {
show([ViewModel类型].from(entity), window);
}
public static void show([ViewModel类型] viewModel, Window window) {
BaseController.show([业务]WindowController.class, viewModel, window);
}
@Override
public void initialize() {
// 初始化UI组件和事件监听
}
@Override
public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent);
// 窗口显示后的逻辑
}
}