SpringBoot添加定时任务
背景描述: 需要定期执行一批数据 ,所以就需要定义定时任务啦
一、固定的定时任务类:(修改定时任务执行时间时需要重启服务)
package com.gaunyi.batteryonline.web.scheduled; import com.gaunyi.batteryonline.service.OnePartnerContactsAbstract; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; /** * 定时任务类 */ @Configuration //1.主要用于标记配置类,兼备Component的效果。 @EnableScheduling // 2.开启定时任务 public class OnePartnerScheduled { @Autowired private OnePartnerContactsAbstract onePartnerAbstract; //定时任务 每3秒跑一次数 // @Scheduled(cron = "0/3 * * * * ?") // private void configureTasksDemo() { // System.out.println("定时任务执行"); // } //3.添加定时任务(每30分钟执行一次) @Scheduled(cron = "* 0/30 * * * ?") private void configureTasks() { dealContactOnelife(); } public Integer dealContactOnelife(){ Integer resultNums = null; try { resultNums = getContactOnelife(); } catch(Exception e){ System.out.println("数据获取失败,请注意检查,失败原因:"+ e); dealContactOnelife();//失败了就重新开始跑数 } return resultNums; } private Integer getContactOnelife() throws Exception{ long starttime = System.currentTimeMillis(); //省略数据处理逻辑... long endtime = System.currentTimeMillis(); System.out.println("整体方法耗时:"+(endtime-starttime)/1000 +"s"); return contactsOnelife; } }
二、定时任务执行时间可配置化,定义到数据库中(修改定时任务执行时间不需要重启服务)
数据库定时任务表设计( rs_cronConfig ):
DROP TABLE IF EXISTS `rs_cronConfig`; CREATE TABLE `rs_cronConfig` ( `SEQID` int(11) PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '数据库自增长唯一标识', `TASKNAME` varchar(128) NOT NULL COMMENT '定时任务名称', `TASKCRON` varchar(32) NOT NULL COMMENT '定时任务执行时间-周期表达式', `STATUS` TINYINT DEFAULT 0 COMMENT '0-正常可使用,1-已弃用', `LASTUPDATETIME` datetime DEFAULT now() COMMENT '上一次更新时间', `CREATETIME` datetime DEFAULT now() COMMENT '数据创建时间', `REMARK` varchar(255) DEFAULT NULL COMMENT '备注信息' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=1 COMMENT='定时任务配置表';
插入与更新定时任务数据示例:
insert into rs_cronConfig(TASKNAME,TASKCRON,REMARK) values('demoScheduledDynamic','* 0/30 * * * ?','示例数据定时任务-每30分钟执行一次'); update rs_cronConfig set TASKCRON='0/3 * * * * ?',LASTUPDATETIME=now(),REMARK='示例数据定时任务-每3秒钟执行一次' where TASKNAME='demoScheduledDynamic' AND STATUS=0;
定时任务执行示例(Java)
package com.gaunyi.batteryonline.web.scheduled; import com.gaunyi.batteryonline.service.OnePartnerContactsAbstract; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.support.CronTrigger; import org.springframework.util.StringUtils; import java.time.LocalDateTime; /** * 定时任务类 动态配置的定时任务类 */ @Configuration //1.主要用于标记配置类,兼备Component的效果。 @EnableScheduling // 2.开启定时任务 public class OnePartnerScheduledDynamic implements SchedulingConfigurer { @Autowired private OnePartnerContactsAbstract onePartnerAbstract; // @Scheduled(cron = "0/3 * * * * ?") // private void configureTasksDemo() { // System.out.println("定时任务执行"); // } //3.添加定时任务 /* @Scheduled(cron = "* 0/30 * * * ?") private void configureTasks() { dealContactOnelife(); }*/ @Mapper public interface CronMapper { @Select("select TASKCRON from rs_cronConfig where TASKNAME='demoScheduledDynamic' AND STATUS=0") public String getTaskCron(); } @Autowired //注入mapper @SuppressWarnings("all") CronMapper cronMapper; /** * 定时任务方法 * @param taskRegistrar */ @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { System.out.println("进入定时任务方法"); taskRegistrar.addTriggerTask( //1.添加任务内容(Runnable) () -> dealContactOnelife(), //2.设置执行周期(Trigger) triggerContext -> { //2.1 从数据库获取执行周期 String cron = cronMapper.getTaskCron(); System.out.println("Cron:"+cron); //2.2 合法性校验. if (StringUtils.isEmpty(cron)) { // Omitted Code .. //CronExpression.isValidExpression(cron) 需要引入quartz的jar包 } //2.3 返回执行周期(Date) return new CronTrigger(cron).nextExecutionTime(triggerContext); } ); } public Integer dealContactOnelife(){ System.out.println("数据定时任务开始执行,开始时间:"+ LocalDateTime.now().toLocalTime()); Integer resultNums = null; try { resultNums = getContactOnelife(); } catch(Exception e){ System.out.println("数据获取失败,请注意检查,失败原因:"+ e); dealContactOnelife();//失败了就重新开始跑数 } return resultNums; } private Integer getContactOnelife() throws Exception{ long starttime = System.currentTimeMillis(); //中间省略数据处理逻辑... long endtime = System.currentTimeMillis(); System.out.println("整体方法耗时:"+(endtime-starttime)/1000 +"s"); return contactsOnelife; } }
Lamada表达式实现Runnable接口示例:
参考博客地址:https://www.cnblogs.com/franson-2016/p/5593080.html
// 1.1使用匿名内部类 new Thread(new Runnable() { @Override public void run() { System.out.println("Hello world !"); } }).start(); // 1.2使用 lambda expression new Thread(() -> System.out.println("Hello world !")).start(); // 2.1使用匿名内部类 Runnable race1 = new Runnable() { @Override public void run() { System.out.println("Hello world !"); } }; // 2.2使用 lambda expression Runnable race2 = () -> System.out.println("Hello world !"); // 直接调用 run 方法(没开新线程哦!) race1.run(); race2.run();
总结:
第一种定时任务的配置是固定的,写法简单容易上手,但是不够灵活,想要更改定时任务执行时间的时候需要修改代码重启服务(对于有可能会变动的任务不太推荐)
第二种定时任务的配置是从数据库里面读取的,比较推荐! 需要注意检查数据库中配置的定时任务格式。(推荐使用!!!)