Appearance
java
### 定时任务架构
#### 类关系图

##### 说明
> 1. TimedTaskJobHandler 定时执行任务
> 2. EveryHourExecute 等等接口,即为延时任务接口,其他地方实现接口即可实现调用
> 3. 其他实现 EveryHourExecute 等等接口 的类,即为定时任务的实际业务类,例如店铺评分计算、定时操作订单等等
#### 二开示例说明
1. 通过Autowired 注入接口的实现集合
2. @XxlJob("everyMinuteExecute") 即为xxljob的注解,告知调度中心,当前任务名称。
3. 调用任务前,需要对任务做非空判定,如果没有实现,那么代码就不要继续执行,以免带来其他后果
4. 执行期间,每个调度都需要有try catch 以防止前半段代码执行,后半段代码因为前端代码抛出的异常导致无法走下去
5. 返回 ReturnT.SUCCESS 及代表xxljob执行成功,调度中心也会记录成功。
6. xxljob定时任务 配置,主要在意address即可,这里配置的是xxljob的地址,其他东西xxljob会给我们维护好
```yaml
xxl:
job:
admin:
addresses: http://127.0.0.1:9001/xxl-job-admin
executor:
appname: xxl-job-executor-lilishop
address:
ip:
port: 8891
logpath: ./xxl-job/executor
logretentiondays: 7
```
7. 具体示例如下:
1. 调度层
```java
@Autowired(required = false)
private List<EveryMinuteExecute> everyMinuteExecutes;
/**
* 每分钟任务
*
* @throws Exception
*/
@XxlJob("everyMinuteExecute")
public ReturnT<String> everyMinuteExecute(String param) {
log.info("每分钟任务执行");
if (everyMinuteExecutes == null || everyMinuteExecutes.size() == 0) {
return ReturnT.SUCCESS;
}
for (int i = 0; i < everyMinuteExecutes.size(); i++) {
try {
everyMinuteExecutes.get(i).execute();
} catch (Exception e) {
log.error("每分钟任务异常", e);
}
}
return ReturnT.SUCCESS;
}
```
2. 具体逻辑执行层
```java
/**
* 订单自动取消(每分钟执行)
*
* @author paulG
* @date 2021/3/11
**/
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CancelOrderTaskExecute implements EveryMinuteExecute {
//订单
private final OrderService orderService;
//设置
private final SettingService settingService;
@Override
public void execute() {
Setting setting = settingService.get(SettingEnum.ORDER_SETTING.name());
OrderSetting orderSetting = JSONUtil.toBean(setting.getSettingValue(), OrderSetting.class);
if (orderSetting != null && orderSetting.getAutoCancel() != null) {
// 订单自动取消时间 = 当前时间 - 自动取消时间分钟数
DateTime cancelTime = DateUtil.offsetMinute(DateUtil.date(), -orderSetting.getAutoCancel());
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.UNPAID.name());
// 订单创建时间 <= 订单自动取消时间
queryWrapper.le(Order::getCreateTime, cancelTime);
List<Order> list = orderService.list(queryWrapper);
List<String> cancelSnList = list.stream().map(Order::getSn).collect(Collectors.toList());
for (String sn : cancelSnList) {
orderService.systemCancel(sn, "超时未支付自动取消");
}
}
}
}
```
xxxxxxxxxx // 延时任务执行 public void onMessage(TimeTriggerMsg timeTriggerMsg) { try { String key = TimeTriggerUtil.generateKey(timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getTriggerTime(), timeTriggerMsg.getUniqueKey()); if (cache.get(key) == null) { log.info("执行器执行被取消:{} | 任务标识:{}", timeTriggerMsg.getTriggerExecutor(), timeTriggerMsg.getUniqueKey()); return; } log.info("执行器执行:" + timeTriggerMsg.getTriggerExecutor()); log.info("执行器参数:" + JSONUtil.toJsonStr(timeTriggerMsg.getParam())); cache.remove(key); TimeTriggerExecutor executor = (TimeTriggerExecutor) SpringContextUtil.getBean(timeTriggerMsg.getTriggerExecutor()); executor.execute(timeTriggerMsg.getParam()); } catch (Exception e) { log.error("mq延时任务异常", e); } }java