# 客户端Tasker实现WebSocketClientTasker接口规范 ## 概述 本文档基于 `ContractRepairAllTasker` 实现 `WebSocketClientTasker` 接口的经验,总结了客户端Tasker类升级为支持WebSocket通信的最佳实践和规范。 ## WebSocketClientTasker接口介绍 `WebSocketClientTasker` 接口定义了通过WebSocket与服务器通信的任务的通用方法,包括任务名称、消息更新、进度更新等核心功能。 ### 核心方法 1. **getTaskName()** - 获取任务名称,用于在WebSocket通信中标识任务 2. **updateMessage(Level, String)** - 更新任务执行过程中的消息 3. **updateTitle(String)** - 更新任务标题 4. **updateProgress(long, long)** - 更新任务进度 5. **cancelTask()** - 取消任务执行(默认实现为空) 6. **callRemoteTask(MessageHolder, Locale, Object...)** - 调用远程WebSocket任务 7. **callRemoteTaskAsync(MessageHolder, Locale, Object...)** - 异步调用远程WebSocket任务 8. **generateTaskId()** - 生成唯一的任务ID ### 典型实现模式概览 通过分析项目中的17个实现类,我们发现了以下典型实现模式: 1. **标准实现**:继承Tasker并实现WebSocketClientTasker 2. **属性注入**:使用@Setter注解或手动设置属性传递任务参数 3. **Spring Bean获取**:通过SpringApp.getBean()获取服务实例 4. **消息更新**:简洁的消息更新方式 5. **参数传递**:通过callRemoteTask的可变参数传递任务所需数据 ## Tasker实现WebSocketClientTasker最佳实践 ### 1. 类定义和继承 ```java /** * 任务类描述 * 用于通过WebSocket与服务器通信执行具体操作 */ public class 任务类名 extends Tasker implements WebSocketClientTasker { private static final Logger logger = LoggerFactory.getLogger(任务类名.class); // 实现方法 } ``` ### 2. 参数传递模式 #### 2.1 使用@Setter注解注入参数 ```java /** * 更新供应商评价表任务 */ public class CompanyVendorEvaluationFormUpdateTask extends Tasker implements WebSocketClientTasker { private static final Logger logger = LoggerFactory.getLogger(CompanyVendorEvaluationFormUpdateTask.class); @Setter private VendorVo vendor; @Override protected Object execute(MessageHolder holder) throws Exception { updateTitle("更新供应商评价表"); return callRemoteTask(holder, getLocale(), vendor.getId()); } } ``` #### 2.2 使用@Getter和@Setter注解 ```java /** * 客户文件重建任务类 */ public class CustomerRebuildFilesTasker extends Tasker implements WebSocketClientTasker { @Getter @Setter private CustomerVo companyCustomer; @Override protected Object execute(MessageHolder holder) throws Exception { updateTitle("重建客户文件"); return callRemoteTask(holder, getLocale(), companyCustomer.getId()); } } ``` ### 2. 必要方法实现 #### 2.1 getTaskName() ```java @Override public String getTaskName() { return "Task名称"; // 必须与服务器端对应Tasker类名匹配 } ``` **注意事项**: - 任务名称必须与服务器端对应的Tasker注册名(tasker_mapper.json中的key)保持一致 - 名称应简洁明了,反映任务的核心功能 #### 2.2 updateProgress() updateProgress 方法重载为public,用于外部调用更新进度 ```java @Override public void updateProgress(long current, long total) { super.updateProgress(current, total); // 调用父类方法更新进度 } ``` #### 2.3 updateTitle() ```java @Override public void updateTitle(String title) { super.updateTitle(title); // 使用Tasker的updateTitle方法更新标题 } ``` #### 2.4 execute() 方法重写 **标准实现**: ```java @Override protected Object execute(MessageHolder holder) throws Exception { logger.info("开始执行任务描述"); updateTitle("任务标题"); // 调用远程任务,可选传入参数 Object result = callRemoteTask(holder, getLocale(), 可选参数...); logger.info("任务执行完成"); return result; } ``` **简洁实现**(适用于简单任务): ```java @Override protected Object execute(MessageHolder holder) throws Exception { updateTitle("更新供应商评价表"); return callRemoteTask(holder, getLocale(), vendor.getId()); } ``` **带消息更新的实现**: ```java @Override protected Object execute(MessageHolder holder) throws Exception { // 设置任务标题 updateTitle("全量库存同步任务"); // 更新任务消息 updateMessage("开始执行全量库存同步..."); // 调用远程WebSocket任务 return callRemoteTask(holder, getLocale()); } ``` **关键步骤**: 1. 记录任务开始日志(可选) 2. 设置任务标题 3. 可选:添加任务开始消息 4. 调用远程任务执行核心逻辑,传入必要参数 5. 记录任务完成日志(可选) 6. 返回执行结果 ### 3. 日志记录 ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; // 在类中定义 private static final Logger logger = LoggerFactory.getLogger(任务类名.class); // 在关键位置使用日志 logger.info("任务开始"); logger.warn("警告信息"); logger.error("错误信息", exception); ``` **日志使用建议**: - 复杂任务建议记录详细日志 - 简单任务可以简化或省略日志记录 - 确保异常情况下有适当的错误日志记录 ### 4. 异常处理 在`execute`方法中应妥善处理可能的异常,并通过MessageHolder通知用户: ```java @Override protected Object execute(MessageHolder holder) throws Exception { try { // 任务执行逻辑 } catch (Exception e) { logger.error("任务执行失败", e); holder.addMessage(Level.SEVERE, "任务执行失败: " + e.getMessage()); throw e; // 向上抛出异常,让框架处理 } } ``` **异常处理策略**: - 对于简单任务,可以依赖框架的异常处理机制 - 对于复杂任务,建议添加自定义的异常处理逻辑 - 确保异常信息对用户友好且具有足够的调试信息 ## 完整实现示例 ### 示例1:简单任务实现 ```java package com.ecep.contract.task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ecep.contract.MessageHolder; import com.ecep.contract.WebSocketClientTasker; /** * 合同修复任务类 * 用于通过WebSocket与服务器通信执行合同数据修复操作 */ public class ContractRepairAllTasker extends Tasker implements WebSocketClientTasker { private static final Logger logger = LoggerFactory.getLogger(ContractRepairAllTasker.class); @Override public void updateProgress(long current, long total) { super.updateProgress(current, total); } @Override public void updateTitle(String title) { // 使用Tasker的updateTitle方法更新标题 super.updateTitle(title); } @Override public String getTaskName() { return "ContractRepairAllTask"; // 与服务器端对应Tasker类名匹配 } @Override protected Object execute(MessageHolder holder) throws Exception { logger.info("开始执行合同修复任务"); updateTitle("合同数据修复"); Object result = callRemoteTask(holder, getLocale()); logger.info("合同修复任务执行完成"); return result; } } ``` ### 示例2:带参数的任务实现 ```java package com.ecep.contract.task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ecep.contract.MessageHolder; import com.ecep.contract.WebSocketClientTasker; import com.ecep.contract.vo.VendorVo; import lombok.Setter; /** * 更新供应商评价表 */ public class CompanyVendorEvaluationFormUpdateTask extends Tasker implements WebSocketClientTasker { private static final Logger logger = LoggerFactory.getLogger(CompanyVendorEvaluationFormUpdateTask.class); @Setter private VendorVo vendor; @Override public void updateProgress(long current, long total) { super.updateProgress(current, total); } @Override public String getTaskName() { return "CompanyVendorEvaluationFormUpdateTask"; // 与服务器端对应Tasker类名匹配 } @Override protected Object execute(MessageHolder holder) throws Exception { updateTitle("更新供应商评价表"); return callRemoteTask(holder, getLocale(), vendor.getId()); } } ``` ### 示例3:使用Spring Bean的任务实现 ```java package com.ecep.contract.task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ecep.contract.MessageHolder; import com.ecep.contract.SpringApp; import com.ecep.contract.WebSocketClientTasker; import com.ecep.contract.service.YongYouU8Service; /** * 合同同步任务 */ public class ContractSyncTask extends Tasker implements WebSocketClientTasker { private static final Logger logger = LoggerFactory.getLogger(ContractSyncTask.class); private YongYouU8Service yongYouU8Service; private YongYouU8Service getYongYouU8Service() { if (yongYouU8Service == null) { yongYouU8Service = SpringApp.getBean(YongYouU8Service.class); } return yongYouU8Service; } public String getTaskName() { return "ContractSyncTask"; // 与服务器端对应Tasker类名匹配 } @Override public void updateProgress(long current, long total) { super.updateProgress(current, total); } @Override protected Object execute(MessageHolder holder) throws Exception { updateTitle("用友U8系统-同步合同"); return callRemoteTask(holder, getLocale()); } } ``` ## 注意事项和最佳实践 ### 1. 命名规范 - 任务类名应采用驼峰命名法,以`Tasker`结尾或描述性名称如`Task` - getTaskName()返回的名称应与服务器端对应Tasker类名完全匹配 - 类注释应清晰描述任务的功能和用途 ### 2. 继承关系 - 必须同时继承Tasker类并实现WebSocketClientTasker接口 - Tasker泛型参数通常为Object - 确保正确导入所有必要的包 ### 3. 参数处理 - 对于需要参数的任务,使用@Setter注解简化属性设置 - 对于需要在多处使用的参数,考虑添加@Getter注解 - 确保参数验证(如果必要) ### 4. Spring Bean获取 - 使用SpringApp.getBean()获取所需的服务实例 - 考虑使用懒加载模式,避免不必要的Bean初始化 ### 5. 消息和进度更新 - 使用updateTitle()设置有意义的任务标题 - 通过MessageHolder或updateMessage()记录详细的执行消息 - 确保进度更新反映真实的执行进度 ### 6. 异常处理 - 在关键操作处添加try-catch块 - 记录异常日志并通知用户 - 适当向上抛出异常以确保框架能正确处理 ### 7. 日志级别使用 - INFO: 记录正常的操作流程 - WARNING: 记录可能的问题,但不影响继续执行 - ERROR: 记录严重错误,通常会终止执行 ### 8. 远程调用参数 - 确保传入的参数类型与服务器端Tasker期望的一致 - 对于不需要参数的任务,可以不传入额外参数 - 对于需要多个参数的任务,确保参数顺序正确 ### 9. 代码风格 - 保持代码简洁明了 - 遵循项目的代码格式化规范 - 添加必要的注释说明核心逻辑 ### 10. 实现策略选择 - 简单任务:使用简洁的实现方式,省略不必要的日志 - 复杂任务:添加详细的日志记录和异常处理 - 有特定需求的任务:根据需要重写接口中的其他方法 ## 与服务器端交互流程 1. 客户端Tasker通过callRemoteTask()方法提交任务 2. WebSocketClientService负责建立与服务器的连接并发送任务信息 3. 服务器接收到任务后,创建对应的Tasker实例并执行 4. 执行过程中的消息、进度等通过WebSocket实时返回给客户端 5. 客户端Tasker通过updateMessage()、updateProgress()等方法更新UI ## 扩展和自定义 如需为特定任务提供自定义功能,可以: 1. 重写cancelTask()方法实现任务取消逻辑 2. 根据需要添加额外的字段和方法 3. 扩展execute()方法实现更复杂的任务流程 ## 总结 通过分析项目中的17个WebSocketClientTasker实现类,我们总结了客户端Tasker实现的多种模式和最佳实践。这些实现从简单到复杂,涵盖了各种使用场景,为后续Tasker的编写提供了全面的参考。 客户端Tasker类实现WebSocketClientTasker接口是实现与服务器实时通信的关键步骤。通过遵循本文档中的规范和最佳实践,可以确保任务执行的可靠性、进度的实时更新和良好的用户体验。 在实际开发中,应根据任务的复杂度和具体需求,选择合适的实现模式和策略,同时保持代码的一致性和可维护性。