定时任务在平时的工作中是很常见的,怎么有效的管理这些个定时任务呢?有的用配置文件,而我却喜欢用可视化列表管理,其实原理也就是把所有的定时任务都放到表里去管理,在项目启动的时候把这些个定时任务扫描到定时任务里即可!废话不多说了,先看看怎么去实现吧。其实SchedulingConfigurer实现方法很简单,只需要实现SchedulingConfigurer并重写configureTasks方法,在启动类必须加上@EnableScheduling注解即可。这里我就是做个封装和优化,让定时任务更好管理,原理还是这个原理。整个项目的实现是在springboot+jpa的环境下。跟着下面的向导来学习吧:
目录
1.创建定时任务的管理表(sys_scheduled)
CREATE TABLE `sys_scheduled` (
`id` varchar(32) NOT NULL COMMENT '主键',
`job_name` varchar(200) DEFAULT NULL COMMENT '定时任务名称',
`class_name` varchar(200) DEFAULT NULL COMMENT '类名',
`method` varchar(250) DEFAULT NULL COMMENT '方法名',
`cron` varchar(200) DEFAULT NULL COMMENT '定时任务表达式',
`start_flag` varchar(2) DEFAULT NULL COMMENT '启用标记',
`create_date` varchar(32) DEFAULT NULL COMMENT '创建日期',
`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
`update_date` varchar(32) DEFAULT NULL COMMENT '更新日期',
`del_flag` varchar(32) DEFAULT NULL COMMENT '删除标记',
`temp1` varchar(2500) DEFAULT NULL COMMENT '备注',
`temp2` varchar(64) DEFAULT NULL COMMENT '备用字段2',
`temp3` varchar(250) DEFAULT NULL COMMENT '备用字段3',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='定时任务配置表';
2.构造定时任务表的相关类
2.1 实体类
package com.lengmo.entity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Data//让实体类的get和set方法得以简化,引入lombok包即可
@Table(name="sys_scheduled")
public class SysScheduled implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id; // 主键
@Column(name="job_name")//表里的字段名称映射到实体类
private String jobName; // 定时任务名称
@Column(name="class_name")
private String className; // 类名
@Column(name="method")
private String method; // 方法名
@Column(name="cron")
private String cron; // 定时任务表达式
@Column(name="start_flag")
private String startFlag; // 启用标记
@Column(name="temp1")
private String temp1;//备注
}
2.2 Repository数据库交互类
package com.lengmo.repository;
import com.lengmo.entity.SysScheduled;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.io.Serializable;
import java.util.List;
public interface SysScheduledRepository extends JpaRepository<SysScheduled, Serializable> {
@Query(" from SysScheduled s where s.startFlag='1'")
public List<SysScheduled> getScheduleList();
}
2.3 Service服务类
package com.lengmo.service;
import java.util.List;
import com.lengmo.entity.SysScheduled;
import com.lengmo.repository.SysScheduledRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SysScheduledService{
@Autowired
private SysScheduledRepository sysScheduledRepository;
public List<SysScheduled> getScheduleList(){
return sysScheduledRepository.getScheduleList();
}
}
3.定时任务配置类(这个是重点哦!!!!)
3.1主要是为了获取bean
package com.lengmo.common;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
@Lazy(false)
public class ApplicationContextHelper implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public ApplicationContextHelper() {
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextHelper.applicationContext = applicationContext;
}
public static Object getBean(String beanName) {
return applicationContext != null?applicationContext.getBean(beanName):null;
}
}
3.2配置类和定时任务管理表的交互(建立关系)
package com.lengmo.common;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import com.lengmo.entity.SysScheduled;
import com.lengmo.service.SysScheduledService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
@Component
public class ScheduleSetting implements SchedulingConfigurer {
@Autowired
private SysScheduledService sysScheduledService;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
// 获取所有任务
List<SysScheduled> scheduleList = sysScheduledService.getScheduleList();
System.out.println(scheduleList.size());
for (SysScheduled s : scheduleList){
scheduledTaskRegistrar.addTriggerTask(getRunnable(s), getTrigger(s));
}
}
/**
* 转换首字母小写
*
* @param str
* @return
*/
public static String lowerFirstCapse(String str) {
char[] chars = str.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
}
/**
* runnable
* @param scheduleConfig
* @return
*/
private Runnable getRunnable(final SysScheduled scheduleConfig){
return new Runnable() {
@Override
public void run() {
Class<?> clazz;
try {
clazz = Class.forName(scheduleConfig.getClassName());
String className = lowerFirstCapse(clazz.getSimpleName());
Object bean = (Object) ApplicationContextHelper.getBean(className);
Method method = ReflectionUtils.findMethod(bean.getClass(), scheduleConfig.getMethod());
ReflectionUtils.invokeMethod(method, bean);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
};
}
/**
* Trigger
* @param scheduleConfig
* @return
*/
private Trigger getTrigger(final SysScheduled scheduleConfig){
return new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
CronTrigger trigger = new CronTrigger(scheduleConfig.getCron());
Date nextExec = trigger.nextExecutionTime(triggerContext);
return nextExec;
}
};
}
}
4.测试类编写并进行验证
package com.lengmo.common.scheduled;
import org.springframework.stereotype.Component;
@Component
public class TaskTest1 {
public void runTaskTest(){
System.out.println("=====================测试定时任务====================");
}
}
5.奉上一些常用的cron表达式
Cron表达式: *秒 *分钟 *小时 *天 *月 *星期 *年份
0~59 0~59 0~23 0~31 0~11 1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT 1970-2099
“30 * * * * ?”不是每30秒执行一次的意思,这个是每分钟的第30秒执行的意思
#经典案例:
“30 * * * * ?” 每分钟第30秒触发任务
“30 10 * * * ?” 每小时的10分30秒触发任务
“30 10 1 * * ?” 每天1点10分30秒触发任务
“30 10 1 20 * ?” 每月20号1点10分30秒触发任务
“30 10 1 20 10 ? *” 每年10月20号1点10分30秒触发任务
“30 10 1 20 10 ? 2011” 2011年10月20号1点10分30秒触发任务
“30 10 1 ? 10 * 2011” 2011年10月每天1点10分30秒触发任务
“30 10 1 ? 10 SUN 2011” 2011年10月每周日1点10分30秒触发任务
“15,30,45 * * * * ?” 每分钟的第15秒,30秒,45秒时触发任务
“15-45 * * * * ?” 15到45秒内,每秒都触发任务
“15/5 * * * * ?” 每分钟的每15秒开始触发,每隔5秒触发一次
“15-30/5 * * * * ?” 每分钟的15秒到30秒之间开始触发,每隔5秒触发一次
“0 0/3 * * * ?” 每小时的第0分0秒开始,每三分钟触发一次
“0 15 10 ? * MON-FRI” 星期一到星期五的10点15分0秒触发任务
“0 15 10 L * ?” 每个月最后一天的10点15分0秒触发任务
“0 15 10 LW * ?” 每个月最后一个工作日的10点15分0秒触发任务
“0 15 10 ? * 5L” 每个月最后一个星期四的10点15分0秒触发任务
“0 15 10 ? * 5#3”每个月第三周的星期四的10点15分0秒触发任务
好了,到这里整个定时任务的功能就完成了,以后只需要再定时任务表里添加相应的类和方法,就能把自动的开启这个定时任务!让定时任务更简单!!!大家可以去试试,上面的代码都是亲自测试过的,没有任何问题的!