新增task自动任务

This commit is contained in:
启航 2024-03-07 09:50:44 +08:00
parent c3811b1890
commit 6d62c7eae1
12 changed files with 438 additions and 4 deletions

View File

@ -1,6 +1,6 @@
package com.qihang.sys.api.controller;
import com.qihang.sys.api.service.EchoService;
import com.qihang.sys.api.feign.EchoService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

View File

@ -0,0 +1,176 @@
package com.qihang.sys.api.domain;
import java.io.Serializable;
import java.util.Date;
/**
*
* @TableName sys_task
*/
public class SysTask implements Serializable {
/**
*
*/
private Integer id;
/**
*
*/
private String taskName;
/**
*
*/
private String cron;
/**
*
*/
private String method;
/**
*
*/
private String remark;
/**
*
*/
private Date createTime;
private static final long serialVersionUID = 1L;
/**
*
*/
public Integer getId() {
return id;
}
/**
*
*/
public void setId(Integer id) {
this.id = id;
}
/**
*
*/
public String getTaskName() {
return taskName;
}
/**
*
*/
public void setTaskName(String taskName) {
this.taskName = taskName;
}
/**
*
*/
public String getCron() {
return cron;
}
/**
*
*/
public void setCron(String cron) {
this.cron = cron;
}
/**
*
*/
public String getMethod() {
return method;
}
/**
*
*/
public void setMethod(String method) {
this.method = method;
}
/**
*
*/
public String getRemark() {
return remark;
}
/**
*
*/
public void setRemark(String remark) {
this.remark = remark;
}
/**
*
*/
public Date getCreateTime() {
return createTime;
}
/**
*
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
SysTask other = (SysTask) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getTaskName() == null ? other.getTaskName() == null : this.getTaskName().equals(other.getTaskName()))
&& (this.getCron() == null ? other.getCron() == null : this.getCron().equals(other.getCron()))
&& (this.getMethod() == null ? other.getMethod() == null : this.getMethod().equals(other.getMethod()))
&& (this.getRemark() == null ? other.getRemark() == null : this.getRemark().equals(other.getRemark()))
&& (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getTaskName() == null) ? 0 : getTaskName().hashCode());
result = prime * result + ((getCron() == null) ? 0 : getCron().hashCode());
result = prime * result + ((getMethod() == null) ? 0 : getMethod().hashCode());
result = prime * result + ((getRemark() == null) ? 0 : getRemark().hashCode());
result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", taskName=").append(taskName);
sb.append(", cron=").append(cron);
sb.append(", method=").append(method);
sb.append(", remark=").append(remark);
sb.append(", createTime=").append(createTime);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}

View File

@ -1,10 +1,10 @@
package com.qihang.sys.api.service;
package com.qihang.sys.api.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "tao-oms")
@FeignClient(name = "tao-api")
public interface EchoService {
@GetMapping(value = "/test/na")
String echo();

View File

@ -0,0 +1,18 @@
package com.qihang.sys.api.mapper;
import com.qihang.sys.api.domain.SysTask;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author TW
* @description 针对表sys_task的数据库操作Mapper
* @createDate 2024-03-07 09:27:01
* @Entity com.qihang.sys.api.domain.SysTask
*/
public interface SysTaskMapper extends BaseMapper<SysTask> {
}

View File

@ -0,0 +1,13 @@
package com.qihang.sys.api.service;
import com.qihang.sys.api.domain.SysTask;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author TW
* @description 针对表sys_task的数据库操作Service
* @createDate 2024-03-07 09:27:01
*/
public interface SysTaskService extends IService<SysTask> {
}

View File

@ -0,0 +1,22 @@
package com.qihang.sys.api.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qihang.sys.api.domain.SysTask;
import com.qihang.sys.api.service.SysTaskService;
import com.qihang.sys.api.mapper.SysTaskMapper;
import org.springframework.stereotype.Service;
/**
* @author TW
* @description 针对表sys_task的数据库操作Service实现
* @createDate 2024-03-07 09:27:01
*/
@Service
public class SysTaskServiceImpl extends ServiceImpl<SysTaskMapper, SysTask>
implements SysTaskService{
}

View File

@ -0,0 +1,30 @@
package com.qihang.sys.api.task;
import com.qihang.sys.api.domain.SysTask;
import com.qihang.sys.api.feign.EchoService;
import com.qihang.sys.api.service.SysTaskService;
import com.qihang.sys.api.task.service.IPollableService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderTaskJD implements IPollableService {
@Autowired
private SysTaskService taskService;
@Resource
private EchoService echoService;
@Override
public void poll() {
String echo = echoService.echo();
System.out.printf("更新京东订单%s",echo);
}
@Override
public String getCronExpression() {
SysTask task = taskService.getById(2);
// return "0/1 * * * * ?";
return task.getCron();
}
}

View File

@ -0,0 +1,45 @@
package com.qihang.sys.api.task.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicBoolean;
@Component
public class CronTaskLoader implements ApplicationRunner {
// private static final Logger log = LoggerFactory.getLogger(CronTaskLoader.class);
private final SchedulingConfiguration schedulingConfiguration;
private final AtomicBoolean appStarted = new AtomicBoolean(false);
private final AtomicBoolean initializing = new AtomicBoolean(false);
public CronTaskLoader(SchedulingConfiguration schedulingConfiguration) {
this.schedulingConfiguration = schedulingConfiguration;
}
/**
* 定时任务配置刷新(1分钟刷新一次)
*/
@Scheduled(fixedDelay = 600000)
public void cronTaskConfigRefresh() {
if (appStarted.get() && initializing.compareAndSet(false, true)) {
// log.info("定时调度任务动态加载开始>>>>>>");
try {
schedulingConfiguration.refresh();
} finally {
initializing.set(false);
}
// log.info("定时调度任务动态加载结束<<<<<<");
}
}
@Override
public void run(ApplicationArguments args) {
if (appStarted.compareAndSet(false, true)) {
cronTaskConfigRefresh();
}
}
}

View File

@ -0,0 +1,84 @@
package com.qihang.sys.api.task.core;
import com.qihang.sys.api.task.service.IPollableService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.ScheduledTask;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@Configuration
@EnableAsync
@EnableScheduling
public class SchedulingConfiguration implements SchedulingConfigurer, ApplicationContextAware {
private static final Logger log = LoggerFactory.getLogger(SchedulingConfiguration.class);
private static ApplicationContext appCtx;
private final ConcurrentMap<String, ScheduledTask> scheduledTaskHolder = new ConcurrentHashMap<>(16);
private final ConcurrentMap<String, String> cronExpressionHolder = new ConcurrentHashMap<>(16);
private ScheduledTaskRegistrar taskRegistrar;
public static synchronized void setAppCtx(ApplicationContext appCtx) {
SchedulingConfiguration.appCtx = appCtx;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
setAppCtx(applicationContext);
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
this.taskRegistrar = taskRegistrar;
}
/**
* 刷新定时任务表达式
*/
public void refresh() {
Map<String, IPollableService> beanMap = appCtx.getBeansOfType(IPollableService.class);
if (beanMap.isEmpty() || taskRegistrar == null) {
return;
}
beanMap.forEach((beanName, task) -> {
String expression = task.getCronExpression();
String taskName = task.getTaskName();
if (null == expression) {
log.warn("定时任务[{}]的任务表达式未配置或配置错误,请检查配置", taskName);
return;
}
// 如果策略执行时间发生了变化则取消当前策略的任务并重新注册任务
boolean unmodified = scheduledTaskHolder.containsKey(beanName) && cronExpressionHolder.get(beanName).equals(expression);
if (unmodified) {
log.info("定时任务[{}]的任务表达式未发生变化,无需刷新", taskName);
return;
}
Optional.ofNullable(scheduledTaskHolder.remove(beanName)).ifPresent(existTask -> {
existTask.cancel();
cronExpressionHolder.remove(beanName);
});
if (ScheduledTaskRegistrar.CRON_DISABLED.equals(expression)) {
log.warn("定时任务[{}]的任务表达式配置为禁用,将被不会被调度执行", taskName);
return;
}
CronTask cronTask = new CronTask(task::poll, expression);
ScheduledTask scheduledTask = taskRegistrar.scheduleCronTask(cronTask);
if (scheduledTask != null) {
log.info("定时任务[{}]已加载,当前任务表达式为[{}]", taskName, expression);
scheduledTaskHolder.put(beanName, scheduledTask);
cronExpressionHolder.put(beanName, expression);
}
});
}
}

View File

@ -0,0 +1,26 @@
package com.qihang.sys.api.task.service;
public interface IPollableService {
/**
* 执行方法
*/
void poll();
/**
* 获取周期表达式
*
* @return CronExpression
*/
default String getCronExpression() {
return null;
}
/**
* 获取任务名称
*
* @return 任务名称
*/
default String getTaskName() {
return this.getClass().getSimpleName();
}
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qihang.sys.api.mapper.SysTaskMapper">
<resultMap id="BaseResultMap" type="com.qihang.sys.api.domain.SysTask">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="taskName" column="task_name" jdbcType="VARCHAR"/>
<result property="cron" column="cron" jdbcType="VARCHAR"/>
<result property="method" column="method" jdbcType="VARCHAR"/>
<result property="remark" column="remark" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,task_name,cron,
method,remark,create_time
</sql>
</mapper>

View File

@ -28,7 +28,7 @@ HomeController {
//https://open.taobao.com/v2/doc?spm=a219a.15212433.0.0.6aca669aUe3Kme#/abilityToOpen?treeId=780&docType=1&docId=102635
TaoGoods taoGoods = goodsMapper.selectById(1L);
return serverName;
return "serverName";
}
}