elastic-job官网地址:https://shardingsphere.apache.org/elasticjob/index_zh.html
程序在运行时,动态添加定时任务,这种场景应用非常广泛。下面我们使用elastic-job实现动态添加定时任务。
注:在使用elastic-job前,需先安装zookeeper。
实现步骤:
1、配置zookeeper地址和任务命名空间
在yaml文件中配置:
#动态定时任务
zkserver: 192.168.3.10:2181 #zookeeper地址
zknamespace: zknamesp # 任务命名空间
2、初始化zookeeper注册中心
@Configuration
public class ElasticJobConfig {
//配置文件中的zookeeper的ip和端口
@Value(value = "${zkserver}")
private String serverlists;
//指定一个命名空间
@Value("${zknamespace}")
private String namespace;
/***
* 配置Zookeeper和namespace
* @return
*/
@Bean
public ZookeeperConfiguration zkConfig() {
return new ZookeeperConfiguration(serverlists, namespace);
}
/***
* 向zookeeper注册初始化信息
* @param config
* @return
*/
@Bean(initMethod = "init")
public ZookeeperRegistryCenter regCenter(ZookeeperConfiguration config) {
return new ZookeeperRegistryCenter(config);
}
/****
* 创建ElasticJob的监听器实例
* @return
*/
@Bean
public ElasticJobListener elasticJobListener() {
//初始化要给定超时多少秒重连
return new ElasticJobListener(100L,100L);
}
}
3、创建监听器
public class ElasticJobListener extends AbstractDistributeOnceElasticJobListener {
/****
* 构造函数
* @param startedTimeoutMilliseconds
* @param completedTimeoutMilliseconds
*/
public ElasticJobListener(long startedTimeoutMilliseconds, long completedTimeoutMilliseconds) {
super(startedTimeoutMilliseconds, completedTimeoutMilliseconds);
}
/***
* 任务初始化前要做的事情,类似前置通知
* @param shardingContexts
*/
@Override
public void doBeforeJobExecutedAtLastStarted(ShardingContexts shardingContexts) {
System.out.println("========doBeforeJobExecutedAtLastStarted========"+ TimeUtil.date2FormatHHmmss(new Date()));
}
/***
* 任务执行完成后要做的事情,类似后置通知
* @param shardingContexts
*/
@Override
public void doAfterJobExecutedAtLastCompleted(ShardingContexts shardingContexts) {
System.out.println("=======doAfterJobExecutedAtLastCompleted============="+ TimeUtil.date2FormatHHmmss(new Date()));
}
}
4、动态添加定时任务
我们创建一个动态配置任务的类,任何逻辑代码需要创建定时任务,可以直接调用该类的指定方法即可。
@Component
public class ElasticJobHandler {
@Resource
private ZookeeperRegistryCenter registryCenter;
@Resource
private ElasticJobListener elasticJobListener;
/**
* @param jobName:任务的命名空间
* @param jobClass:执行的定时任务对象
* @param shardingTotalCount:分片个数
* @param cron:定时周期表达式
* @param id:自定义参数
* @return
*/
private static LiteJobConfiguration.Builder simpleJobConfigBuilder(String jobName, Class<? extends SimpleJob> jobClass, int shardingTotalCount, String cron, String id) {
//创建任务构建对象
LiteJobConfiguration.Builder builder = LiteJobConfiguration.newBuilder(new SimpleJobConfiguration(
JobCoreConfiguration.
//任务命名空间名字、任务执行周期表达式、分片个数
newBuilder(jobName, cron, shardingTotalCount).
//自定义参数
jobParameter(id).
build(),
jobClass.getCanonicalName()));
//本地配置是否可覆盖注册中心配置
builder.overwrite(true);
return builder;
}
/**
* 添加一个定时任务
* @param cron:周期执行表达式
* @param id:自定义参数
* @param jobName:命名空间
* @param instance:任务对象
*/
public void addPublishJob(String cron,String id,String jobName,SimpleJob instance) {
LiteJobConfiguration jobConfig = simpleJobConfigBuilder(
jobName,
instance.getClass(),
1,
cron,
id).overwrite(true).build();
//DynamicTask为具体的任务执行逻辑类
new SpringJobScheduler(instance, registryCenter, jobConfig, elasticJobListener).init();
}
/***
* Date转cron表达式
*/
public static final String CRON_DATE_FORMAT = "ss mm HH dd MM ? yyyy";
/**
* 获得定时
* @param date
* @return
*/
public static String getCron(final Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(CRON_DATE_FORMAT);
return simpleDateFormat.format(date);
}
}
5、实现自定义任务,需要实现SimpleJob接口
public class DynamicTask implements SimpleJob {
@Override
public void execute(ShardingContext shardingContext) {
//传递的参数
String id = shardingContext.getJobParameter();
try {
//具体任务逻辑
System.out.println("执行你的逻辑代码!param:"+id);
} catch (Exception e) {
e.printStackTrace();
}
}
}
6、测试
@RestController
@RequestMapping(value = "/test")
public class TestController {
@Autowired
ElasticJobHandler elasticJobHandler;
/***
* 动态创建任务
* @param times:延迟时间,为了测试到效果,所以在当前时间往后延迟
* @param jobname:任务名字
* @param param:自定义参数
* @return
*/
@GetMapping
public Result add(Long times,String jobname,String param){
//在当前指定时间内延迟times毫秒执行任务
Date date = new Date(System.currentTimeMillis()+times);
//需要传递给定时任务的参数
String cron = ElasticJobHandler.getCron(date);
//执行任务
elasticJobHandler.addPublishJob(cron,param,jobname,new DynamicTask());
return new Result(true, StatusCode.OK,"添加任务成功!");
}
}
完成!!!