上一篇文章【修改定时时间,定时任务及时生效】 是定时任务与功能项目共用一个;
我目前所在公司的定时服务是专门有一个项目处理,然后定时查询库里面的定时信息配置。
话不多说,上程序
create table SCHEDULER_JOB
(
id VARCHAR2(32) not null,
job_name VARCHAR2(200),
cron VARCHAR2(100),
method_name varchar2(200),
bean_name varchar2(200),
remark varchar2(50),
type varchar2(4) default '是否有参数 01否 02是'
)
package com.example.demo.entity;
public class SchedulerJob {
private String id;
//任务名称
private String jobName;
//表达式
private String cron;
//方法名称
private String methodName;
//bean名称
private String beanName;
//备注(方法的参数)
private String remark;
//类型 是否有参数 01否 02是
private String type;
//todo get/set方法
}
import com.example.demo.entity.SchedulerJob;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SchedulerJobMapper {
List queryList();
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@Service
public class JobRegisterService {
private static final Logger logger = LoggerFactory.getLogger(JobRegisterService.class);
@Autowired
private RedisLockRegistry redisLockRegistry;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private JobService jobService;
@Scheduled(cron = "0 0/2 * * * ?")
public void startTaskJob() {
Lock lock = redisLockRegistry.obtain("lock");
try {
boolean flag = lock.tryLock(10L, TimeUnit.SECONDS);
ValueOperations map = redisTemplate.opsForValue();
if (flag) {
Object taskStatus = map.get("taskStatus");
if (taskStatus != null && taskStatus.toString().equals("Y")) {
jobService.clearAllJob();
return;
}
map.set("taskStatus", "Y");
redisTemplate.expire("taskStatus", 1L, TimeUnit.MINUTES);
jobService.timeTask();
} else {
jobService.clearAllJob();
}
} catch (Exception e) {
logger.error("获取锁异常:", e);
} finally {
lock.unlock();
}
}
}
import com.alibaba.fastjson.JSON;
import com.example.demo.entity.SchedulerJob;
import com.example.demo.mapper.SchedulerJobMapper;
import com.example.demo.util.DateUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class JobService {
private static final Logger logger = LoggerFactory.getLogger(JobService.class);
@Autowired
private Scheduler scheduler;
@Autowired
private SchedulerJobMapper schedulerJobMapper;
public void timeTask() {
//查询数据库存在需要定时的任务
logger.info("任务重置开始,查询数据...");
List schedulerJobList = schedulerJobMapper.queryList();
if (schedulerJobList != null) {
try {
scheduler.clear();
logger.info("任务重置开始,旧的任务清理");
schedulerJobList.forEach(this::addJob);
} catch (Exception e) {
logger.error("调用错误:", e);
}
}
}
public void addJob(SchedulerJob schedulerJob) {
try {
//作业名称
JobKey jobKey = JobKey.jobKey(schedulerJob.getJobName());
//设置触发时间
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(schedulerJob.getCron());
//触发建立
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(schedulerJob.getJobName()).withSchedule(cronScheduleBuilder).forJob(jobKey).build();
if (trigger != null && trigger.getStartTime() != null) {
logger.info("作业【{}】启动时间为{}", schedulerJob.getJobName(), DateUtils.formatDate(trigger.getStartTime(), DateUtils.DATETIME_FORMAT));
} else {
logger.info("作业【{}】启动时间为空", schedulerJob.getJobName());
}
//建立作业
JobDetail jobDetail = JobBuilder.newJob(QuartzFactory.class).withIdentity(schedulerJob.getJobName()).build();
jobDetail.getJobDataMap().put("schedulerJob", schedulerJob);
//调度作业
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
logger.error("添加作业失败[schedulerJob={}]", JSON.toJSONString(schedulerJob), e);
}
}
/**
* 清除任务
*/
public void clearAllJob() throws SchedulerException {
logger.info("清除任务...");
scheduler.clear();
}
}
import com.example.demo.constant.SchedulerJobTypeEnum;
import com.example.demo.entity.SchedulerJob;
import com.example.demo.util.SpringContextUtil;
import org.apache.commons.lang.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
public class QuartzFactory implements Job {
private static final Logger logger = LoggerFactory.getLogger(QuartzFactory.class);
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//获取调度数据
SchedulerJob schedulerJob = (SchedulerJob) jobExecutionContext.getMergedJobDataMap().get("schedulerJob");
//获取对应的bean
Object obj = SpringContextUtil.getObj(schedulerJob.getBeanName());
try {
if (obj == null) {
throw new Exception("找不到该类");
}
if (StringUtils.isEmpty(schedulerJob.getType()) || SchedulerJobTypeEnum.NO.getCode().equals(schedulerJob.getType())) {
Method method = obj.getClass().getMethod(schedulerJob.getMethodName());
method.invoke(obj);
} else {
Method method = obj.getClass().getMethod(schedulerJob.getMethodName(), String.class);
method.invoke(obj, schedulerJob.getRemark());
}
} catch (Exception e) {
logger.error("定时任务获取映射异常:", e);
}
}
}
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtil implements ApplicationContextAware {
//spring 上下文实例对象
private static ApplicationContext context;
// 根据class获取对象实例
public static T getObj(Class tClass) {
return context.getBean(tClass);
}
// 根据配置的 bean name 获取对象实例
public static Object getObj(String beanName) {
return context.getBean(beanName);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.integration.redis.util.RedisLockRegistry;
@Configuration
public class RedisLockConfig {
@Bean
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
//第一个参数redisConnectionFactory
//第二个参数registryKey,分布式锁前缀,设置为项目名称会好些
//该构造方法对应的分布式锁,默认有效期是60秒.可以自定义
return new RedisLockRegistry(redisConnectionFactory, "demo");
}
}
import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.io.IOException;
@Configuration
public class SchedulerConfig {
@Bean
public Scheduler scheduler() throws Exception {
Scheduler scheduler = schedulerFactoryBean().getScheduler();
return scheduler;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setSchedulerName("Test_Scheduler");
//覆盖已存在的任务
factory.setOverwriteExistingJobs(true);
// 延迟10s执行 防止发生系统未启动完成 定时任务却已经开始的情况
factory.setStartupDelay(10);
return factory;
}
}
public enum SchedulerJobTypeEnum {
NO("01", "否"),
YES("02", "是");
private String code;
private String value;
SchedulerJobTypeEnum(String code, String value) {
this.code = code;
this.value = value;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
import org.apache.commons.lang.time.DateFormatUtils;
import java.util.Date;
public class DateUtils {
public static final String DATE_FORMAT = "yyyy-MM-dd";
public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String TIME_FORMAT = "HH:mm:ss";
/**
* 常用的时间格式.
*/
private static String[] parsePatterns = {"yyyy-MM-dd",
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mm",
"HH:mm:ss"};
/**
* 得到当前日期字符串.
*/
public static String getDate() {
return getDate(DateUtils.DATE_FORMAT);
}
public static String getDate(String pattern) {
return DateFormatUtils.format(new Date(), pattern);
}
/**
* 得到当前时间字符串.
*/
public static String getTime() {
return formatDate(new Date(), DateUtils.TIME_FORMAT);
}
/**
* 得到当前日期和时间字符串.
*/
public static String getDateTime() {
return formatDate(new Date(), DateUtils.DATETIME_FORMAT);
}
/**
* 获取日期时间字符串,默认格式为(yyyy-MM-dd).
*/
public static String formatDate(Date date, Object... pattern) {
String formatDate = null;
if (pattern != null && pattern.length > 0) {
formatDate = DateFormatUtils.format(date, pattern[0].toString());
} else {
formatDate = DateFormatUtils.format(date, DateUtils.DATE_FORMAT);
}
return formatDate;
}
}
import com.example.demo.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class TestSchedulerJobService {
private static final Logger logger = LoggerFactory.getLogger(TestSchedulerJobService.class);
public void test() {
String dateTime = DateUtils.getDateTime();
logger.info("当前时间={}", dateTime);
}
public void test1(String param) {
String dateTime = DateUtils.getDateTime();
logger.info("当前时间1={},参数={}", dateTime, param);
}
}
【注意:】数据库中bean_Name存储的是bean名称(默认类名首字母小写)
job_name和method_name数据值一样即可
由此可看出,两个定时任务是按照数据库中配置的定时时间跑的。
具体定时任务时间等信息视情况而定!