182 lines
5.4 KiB
Markdown
182 lines
5.4 KiB
Markdown
# Tasker实现规范指南
|
||
|
||
## 1. Tasker架构概述
|
||
|
||
Tasker是系统中用于执行异步任务的核心框架,主要用于处理耗时操作并提供实时进度反馈。Tasker架构包括:
|
||
|
||
- **Tasker基类**:提供任务执行的基础框架和通信功能
|
||
- **WebSocketServerTasker接口**:定义WebSocket通信任务的规范
|
||
- **MessageHolder**:用于在任务执行过程中传递消息和更新进度
|
||
|
||
## 2. 服务器端Tasker实现规范
|
||
|
||
### 2.1 基本结构
|
||
|
||
服务器端Tasker实现应遵循以下结构:
|
||
|
||
```java
|
||
@Data
|
||
@EqualsAndHashCode(callSuper = true)
|
||
public class YourTaskNameTask extends Tasker<Object> implements WebSocketServerTasker {
|
||
// 服务依赖
|
||
@Setter
|
||
private YourService service;
|
||
|
||
@Override
|
||
public void init(JsonNode argsNode) {
|
||
// 初始化任务标题
|
||
updateTitle("任务标题");
|
||
// 初始化参数
|
||
}
|
||
|
||
@Override
|
||
protected Object execute(MessageHolder holder) throws Exception {
|
||
// 实现业务逻辑
|
||
// 使用holder.info()、holder.error()等方法反馈消息
|
||
return null;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.2 关键注意事项
|
||
|
||
1. **继承与实现**:
|
||
- 必须继承`Tasker<Object>`基类
|
||
- 必须实现`WebSocketServerTasker`接口
|
||
|
||
2. **方法实现**:
|
||
- **不要重复实现**Tasker基类已提供的handler设置方法:`setMessageHandler`、`setTitleHandler`、`setPropertyHandler`、`setProgressHandler`
|
||
- 必须实现`init`方法,设置任务标题和初始化参数
|
||
- 必须实现`execute`方法,实现具体业务逻辑
|
||
|
||
3. **进度和消息反馈**:
|
||
- 使用`updateProgress`方法提供进度更新
|
||
- 使用`MessageHolder`的`info`、`error`、`debug`等方法提供消息反馈
|
||
|
||
4. **任务取消**:
|
||
- 在适当的地方检查`isCancelled()`状态,支持任务取消
|
||
|
||
5. **注册要求**:
|
||
- 任务类必须在`tasker_mapper.json`中注册
|
||
|
||
## 3. 客户端Tasker实现规范
|
||
|
||
客户端Tasker实现应遵循:
|
||
|
||
```java
|
||
public class YourTaskNameTask extends Tasker<Object> {
|
||
@Override
|
||
protected Object execute(MessageHolder holder) throws Exception {
|
||
// 客户端任务逻辑
|
||
return null;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 4. 通信规范
|
||
|
||
### 4.1 命名规范
|
||
|
||
- 客户端和服务器端对应的Tasker类应使用**相同的类名**
|
||
- 示例:客户端的`ContractSyncAllTask`对应服务器端的`ContractSyncAllTask`
|
||
|
||
### 4.2 消息传递
|
||
|
||
- 使用`MessageHolder`进行消息传递
|
||
- 支持不同级别的消息:INFO、ERROR、DEBUG
|
||
|
||
## 5. 最佳实践
|
||
|
||
1. **任务拆分**:
|
||
- 将大型任务拆分为多个小任务,提高可维护性
|
||
|
||
2. **异常处理**:
|
||
- 捕获并正确处理异常,使用`holder.error()`提供详细错误信息
|
||
|
||
3. **资源管理**:
|
||
- 确保及时释放资源,特别是在任务取消的情况下
|
||
|
||
4. **日志记录**:
|
||
- 使用`holder.debug()`记录调试信息
|
||
- 使用`holder.info()`记录进度信息
|
||
|
||
5. **状态检查**:
|
||
- 定期检查`isCancelled()`状态,确保任务可以被及时取消
|
||
|
||
## 6. 代码示例
|
||
|
||
### 6.1 服务器端Tasker示例
|
||
|
||
```java
|
||
@Data
|
||
@EqualsAndHashCode(callSuper = true)
|
||
public class ExampleSyncTask extends Tasker<Object> implements WebSocketServerTasker {
|
||
@Setter
|
||
private ExampleService exampleService;
|
||
|
||
@Override
|
||
public void init(JsonNode argsNode) {
|
||
updateTitle("示例同步任务");
|
||
// 从argsNode初始化参数
|
||
}
|
||
|
||
@Override
|
||
protected Object execute(MessageHolder holder) throws Exception {
|
||
try {
|
||
// 获取总记录数
|
||
long total = exampleService.getTotalCount();
|
||
holder.info("开始同步数据,共" + total + "条记录");
|
||
|
||
// 分批处理
|
||
long processed = 0;
|
||
List<ExampleEntity> entities = exampleService.getAllEntities();
|
||
|
||
for (ExampleEntity entity : entities) {
|
||
// 检查是否取消
|
||
if (isCancelled()) {
|
||
holder.info("任务已取消");
|
||
return null;
|
||
}
|
||
|
||
// 处理单个实体
|
||
exampleService.processEntity(entity);
|
||
processed++;
|
||
|
||
// 更新进度
|
||
updateProgress(processed, total);
|
||
if (processed % 100 == 0) {
|
||
holder.info("已处理" + processed + "/" + total + "条记录");
|
||
}
|
||
}
|
||
|
||
holder.info("同步完成,共处理" + processed + "条记录");
|
||
return processed;
|
||
} catch (Exception e) {
|
||
holder.error("同步失败: " + e.getMessage());
|
||
throw e;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 7. 常见错误和避免方法
|
||
|
||
1. **重复实现handler方法**:
|
||
- 错误:在子类中重复实现setMessageHandler等方法
|
||
- 解决:删除子类中的这些方法,直接使用Tasker基类提供的实现
|
||
|
||
2. **缺少任务注册**:
|
||
- 错误:任务类没有在tasker_mapper.json中注册
|
||
- 解决:确保所有服务器端Tasker类都在配置文件中正确注册
|
||
|
||
3. **类名不匹配**:
|
||
- 错误:客户端和服务器端Tasker类名不一致
|
||
- 解决:确保两端使用相同的类名
|
||
|
||
4. **进度更新不正确**:
|
||
- 错误:进度计算错误或没有更新
|
||
- 解决:正确计算和更新进度,提高用户体验
|
||
|
||
5. **资源泄漏**:
|
||
- 错误:未及时关闭数据库连接等资源
|
||
- 解决:使用try-with-resources或在finally块中关闭资源 |