1.maven pom引入依赖
org.quartz-scheduler
quartz
2.2.3
org.quartz-scheduler
quartz-jobs
2.2.3
org.springframework
spring-context-support
2.数据库建立quartz相关表
执行quartz建表sql即可。
3.quartz配置文件quartz.properties
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
#如果使用集群,instanceId必须唯一,设置成AUTO
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 50
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
#============================================================================
# Configure JobStore
#============================================================================
#
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
#存储方式使用JobStoreTX,也就是数据库
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties:false
#数据库中quartz表的表名前缀
org.quartz.jobStore.tablePrefix:QRTZ_
org.quartz.jobStore.dataSource:qzDS
#是否使用集群(如果项目只部署到 一台服务器,就不用了)
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 30000
#============================================================================
# Configure Datasources
#============================================================================
#配置数据源
org.quartz.dataSource.qzDS.driver:com.mysql.cj.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/micro_mall?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:`1qazx
org.quartz.dataSource.qzDS.validationQuery=select 0 from dual
此处需说明:org.quartz.jobStore.userProperties值为true时,标记指示着持久性 JobStore 所有在 JobDataMap 中的值都是字符串,因此能以 名-值 对的形式存储,而不用让更复杂的对象以序列化的形式存入 BLOB 列中。
job工厂:
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
@Component
public class SpringJobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
定时任务配置:
package com.hxkg.datafusion.schedule;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.io.IOException;
import java.util.Properties;
/**
* 定时任务配置
*
* @author yangfeng
* @date 2018-07-03
*/
@Configuration
public class QuartzConfig {
@Autowired
private SpringJobFactory springJobFactory;
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
//获取配置属性
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("quartz.properties"));
//在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.afterPropertiesSet();
//创建SchedulerFactoryBean
SchedulerFactoryBean factory = new SchedulerFactoryBean();
Properties pro = propertiesFactoryBean.getObject();
factory.setOverwriteExistingJobs(true);
factory.setAutoStartup(true);
factory.setQuartzProperties(pro);
factory.setJobFactory(springJobFactory);
return factory;
}
@Bean
public Scheduler scheduler() throws IOException{
return schedulerFactoryBean().getScheduler();
}
}
4.任务调度表结构
CREATE TABLE `schedule_job` (
`id` varchar(32) NOT NULL,
`job_name` varchar(126) NOT NULL COMMENT '任务名称',
`bean_name` varchar(126) NOT NULL COMMENT 'bean名称',
`cron_expression` varchar(126) NOT NULL COMMENT '表达式',
`method_name` varchar(32) DEFAULT NULL COMMENT '方法名',
`params` varchar(32) DEFAULT NULL COMMENT '参数',
`status` int(1) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`createBy` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务调度表';
5.任务调度实体
package com.mall.shop.entity.gen;
import java.io.Serializable;
import java.util.Date;
public class ScheduleJob implements Serializable {
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.id
*
* @mbggenerated
*/
private String id;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.job_name
*
* @mbggenerated
*/
private String jobName;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.bean_name
*
* @mbggenerated
*/
private String beanName;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.cron_expression
*
* @mbggenerated
*/
private String cronExpression;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.method_name
*
* @mbggenerated
*/
private String methodName;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.params
*
* @mbggenerated
*/
private String params;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.status
*
* @mbggenerated
*/
private Integer status;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.create_time
*
* @mbggenerated
*/
private Date createTime;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column schedule_job.createBy
*
* @mbggenerated
*/
private String createby;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database table schedule_job
*
* @mbggenerated
*/
private static final long serialVersionUID = 1L;
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.id
*
* @return the value of schedule_job.id
*
* @mbggenerated
*/
public String getId() {
return id;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.id
*
* @param id the value for schedule_job.id
*
* @mbggenerated
*/
public void setId(String id) {
this.id = id;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.job_name
*
* @return the value of schedule_job.job_name
*
* @mbggenerated
*/
public String getJobName() {
return jobName;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.job_name
*
* @param jobName the value for schedule_job.job_name
*
* @mbggenerated
*/
public void setJobName(String jobName) {
this.jobName = jobName == null ? null : jobName.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.bean_name
*
* @return the value of schedule_job.bean_name
*
* @mbggenerated
*/
public String getBeanName() {
return beanName;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.bean_name
*
* @param beanName the value for schedule_job.bean_name
*
* @mbggenerated
*/
public void setBeanName(String beanName) {
this.beanName = beanName == null ? null : beanName.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.cron_expression
*
* @return the value of schedule_job.cron_expression
*
* @mbggenerated
*/
public String getCronExpression() {
return cronExpression;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.cron_expression
*
* @param cronExpression the value for schedule_job.cron_expression
*
* @mbggenerated
*/
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression == null ? null : cronExpression.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.method_name
*
* @return the value of schedule_job.method_name
*
* @mbggenerated
*/
public String getMethodName() {
return methodName;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.method_name
*
* @param methodName the value for schedule_job.method_name
*
* @mbggenerated
*/
public void setMethodName(String methodName) {
this.methodName = methodName == null ? null : methodName.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.params
*
* @return the value of schedule_job.params
*
* @mbggenerated
*/
public String getParams() {
return params;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.params
*
* @param params the value for schedule_job.params
*
* @mbggenerated
*/
public void setParams(String params) {
this.params = params == null ? null : params.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.status
*
* @return the value of schedule_job.status
*
* @mbggenerated
*/
public Integer getStatus() {
return status;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.status
*
* @param status the value for schedule_job.status
*
* @mbggenerated
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.create_time
*
* @return the value of schedule_job.create_time
*
* @mbggenerated
*/
public Date getCreateTime() {
return createTime;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.create_time
*
* @param createTime the value for schedule_job.create_time
*
* @mbggenerated
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column schedule_job.createBy
*
* @return the value of schedule_job.createBy
*
* @mbggenerated
*/
public String getCreateby() {
return createby;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column schedule_job.createBy
*
* @param createby the value for schedule_job.createBy
*
* @mbggenerated
*/
public void setCreateby(String createby) {
this.createby = createby == null ? null : createby.trim();
}
}
实体扩展类:
package com.mall.shop.entity.customized;
import java.io.Serializable;
import com.mall.shop.entity.gen.ScheduleJob;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
/**
* 应用对象 - ScheduleJob.
*
* 该类于 2021-05-21 13:56:38 首次生成,后由开发手工维护。
*
* @author yangfeng
* @version 1.0.0, May 21, 2021
*/
@JsonSerialize(include = Inclusion.ALWAYS)
public final class ScheduleJobAO extends ScheduleJob implements Serializable {
/**
* 默认的序列化 id.
*/
private static final long serialVersionUID = 1L;
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}
6.接口服务
package com.mall.shop.service;
import com.backstage.core.result.ServiceResult;
import com.backstage.core.service.IBaseAOService;
import com.mall.shop.dto.request.ScheduleJobRequest;
import com.mall.shop.entity.customized.ScheduleJobAO;
import com.mall.shop.entity.gen.ScheduleJobCriteria;
import java.util.List;
public interface IScheduleJobService extends IBaseAOService {
ServiceResult> list(ScheduleJobRequest request);
ServiceResult> listByCondition(ScheduleJobRequest request);
ServiceResult add(ScheduleJobAO scheduleJob);
ServiceResult update(ScheduleJobAO scheduleJob);
ServiceResult deleteBatch(String[] jobIds);
ServiceResult run(String[] jobIds);
ServiceResult pause(String[] jobIds);
ServiceResult resume(String[] jobIds);
}
package com.mall.shop.service.impl;
import com.backstage.common.page.Page;
import com.backstage.core.mapper.BaseGeneratedMapper;
import com.backstage.core.result.ServiceResult;
import com.backstage.core.result.ServiceResultHelper;
import com.backstage.core.service.AbstractBaseAOService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mall.shop.dao.customized.ScheduleJobCustomizedMapper;
import com.mall.shop.dao.gen.ScheduleJobGeneratedMapper;
import com.mall.shop.dto.request.ScheduleJobRequest;
import com.mall.shop.entity.customized.ScheduleJobAO;
import com.mall.shop.entity.gen.ScheduleJob;
import com.mall.shop.entity.gen.ScheduleJobCriteria;
import com.mall.shop.enums.ScheduleStatus;
import com.mall.shop.service.IScheduleJobService;
import com.mall.shop.util.ScheduleUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 任务调度服务
*
* @author yangfeng
*/
@Service
public class ScheduleJobService extends AbstractBaseAOService implements IScheduleJobService {
@Resource
private ScheduleJobGeneratedMapper scheduleJobGeneratedMapper;
@Resource
private ScheduleJobCustomizedMapper scheduleJobCustomizedMapper;
@Override
protected BaseGeneratedMapper getGeneratedMapper() {
return scheduleJobGeneratedMapper;
}
@Autowired
private Scheduler scheduler;
/**
* 项目启动时,初始化定时器
*/
@PostConstruct
public void init() {
List scheduleJobList = this.listByCondition(null).getData();
for (ScheduleJobAO scheduleJob : scheduleJobList) {
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId());
//如果不存在,则创建
if (cronTrigger == null) {
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
} else {
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
}
}
}
/**
* 分页查询
*
* @param request
* @return
*/
@Override
public ServiceResult> list(ScheduleJobRequest request) {
ServiceResult> ret = new ServiceResult();
PageHelper.startPage(request.getPageNo(), request.getPageSize());
List scheduleJobAOList = scheduleJobCustomizedMapper.listByCondition(request);
ret.setData(scheduleJobAOList);
ret.setSucceed(true);
ret.setAdditionalProperties("page", Page.obtainPage(new PageInfo(scheduleJobAOList)));
return ret;
}
@Override
public ServiceResult> listByCondition(ScheduleJobRequest request) {
return ServiceResultHelper.genResultWithSuccess(scheduleJobCustomizedMapper.listByCondition(request));
}
@Override
@Transactional(rollbackFor = Exception.class)
public ServiceResult add(ScheduleJobAO scheduleJob) {
scheduleJob.setCreateTime(new Date());
scheduleJob.setStatus(ScheduleStatus.NORMAL.getValue());
this.insert(scheduleJob);
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
return ServiceResultHelper.genResultWithSuccess();
}
@Override
@Transactional(rollbackFor = Exception.class)
public ServiceResult update(ScheduleJobAO scheduleJob) {
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
this.saveOrUpdate(scheduleJob);
return ServiceResultHelper.genResultWithSuccess();
}
@Override
@Transactional(rollbackFor = Exception.class)
public ServiceResult deleteBatch(String[] jobIds) {
for (String jobId : jobIds) {
ScheduleUtils.deleteScheduleJob(scheduler, jobId);
deleteById(jobId);
}
return ServiceResultHelper.genResultWithSuccess();
}
@Override
@Transactional(rollbackFor = Exception.class)
public ServiceResult run(String[] jobIds) {
for (String jobId : jobIds) {
ScheduleUtils.run(scheduler, selectByPrimaryKey(jobId).getData());
}
return ServiceResultHelper.genResultWithSuccess();
}
@Override
@Transactional(rollbackFor = Exception.class)
public ServiceResult pause(String[] jobIds) {
for (String jobId : jobIds) {
ScheduleUtils.pauseJob(scheduler, jobId);
}
return updateBatch(jobIds, ScheduleStatus.PAUSE.getValue());
}
@Override
@Transactional(rollbackFor = Exception.class)
public ServiceResult resume(String[] jobIds) {
for (String jobId : jobIds) {
ScheduleUtils.resumeJob(scheduler, jobId);
}
return updateBatch(jobIds, ScheduleStatus.NORMAL.getValue());
}
public ServiceResult updateBatch(String[] jobIds, int status) {
for (String jobId : jobIds) {
ScheduleJobAO scheduleJob = new ScheduleJobAO();
scheduleJob.setId(jobId);
scheduleJob.setStatus(status);
this.saveOrUpdate(scheduleJob);
}
return ServiceResultHelper.genResultWithSuccess();
}
}
7.动态调度相关
ScheduleUtils工具类:
package com.mall.shop.util;
import com.backstage.common.exception.BaseException;
import com.mall.shop.entity.customized.ScheduleJobAO;
import com.mall.shop.entity.gen.ScheduleJob;
import com.mall.shop.enums.ScheduleStatus;
import org.quartz.*;
/**
* 定时任务工具类
*
*/
public class ScheduleUtils {
private final static String JOB_NAME = "TASK_";
/**
* 任务调度参数key
*/
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
/**
* 获取触发器key
*/
public static TriggerKey getTriggerKey(String jobId) {
return TriggerKey.triggerKey(JOB_NAME + jobId);
}
/**
* 获取jobKey
*/
public static JobKey getJobKey(String jobId) {
return JobKey.jobKey(JOB_NAME + jobId);
}
/**
* 获取表达式触发器
*/
public static CronTrigger getCronTrigger(Scheduler scheduler, String jobId) {
try {
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
} catch (SchedulerException e) {
throw new BaseException(-1, "获取定时任务CronTrigger出现异常" + e.getMessage());
}
}
/**
* 创建定时任务
*/
public static void createScheduleJob(Scheduler scheduler, ScheduleJobAO scheduleJob) {
try {
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(ScheduleJobExec.class).withIdentity(getJobKey(scheduleJob.getId())).build();
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getId())).withSchedule(scheduleBuilder).build();
//放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
scheduler.scheduleJob(jobDetail, trigger);
//暂停任务
if (scheduleJob.getStatus() == ScheduleStatus.PAUSE.getValue()) {
pauseJob(scheduler, scheduleJob.getId());
}
} catch (SchedulerException e) {
throw new BaseException(-1, "创建定时任务失败" + e.getMessage());
}
}
/**
* 更新定时任务
*/
public static void updateScheduleJob(Scheduler scheduler, ScheduleJobAO scheduleJob) {
try {
TriggerKey triggerKey = getTriggerKey(scheduleJob.getId());
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getId());
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//参数
trigger.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
scheduler.rescheduleJob(triggerKey, trigger);
//暂停任务
if (scheduleJob.getStatus() == ScheduleStatus.PAUSE.getValue()) {
pauseJob(scheduler, scheduleJob.getId());
}
} catch (SchedulerException e) {
throw new BaseException(-1, "更新定时任务失败" + e.getMessage());
}
}
/**
* 立即执行任务
*/
public static void run(Scheduler scheduler, ScheduleJobAO scheduleJob) {
try {
//参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(JOB_PARAM_KEY, scheduleJob);
scheduler.triggerJob(getJobKey(scheduleJob.getId()), dataMap);
} catch (SchedulerException e) {
throw new BaseException(-1, "立即执行定时任务失败" + e.getMessage());
}
}
/**
* 暂停任务
*/
public static void pauseJob(Scheduler scheduler, String jobId) {
try {
scheduler.pauseJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new BaseException(-1, "暂停定时任务失败" + e.getMessage());
}
}
/**
* 恢复任务
*/
public static void resumeJob(Scheduler scheduler, String jobId) {
try {
scheduler.resumeJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new BaseException(-1, "恢复定时任务失败" + e.getMessage());
}
}
/**
* 删除定时任务
*/
public static void deleteScheduleJob(Scheduler scheduler, String jobId) {
try {
scheduler.deleteJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new BaseException(-1, "删除定时任务失败" + e.getMessage());
}
}
}
定时任务调度类ScheduleJobExec:
package com.mall.shop.util;
import com.alibaba.fastjson.JSON;
import com.mall.shop.entity.customized.ScheduleJobAO;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 定时任务
*/
public class ScheduleJobExec extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(getClass());
private ExecutorService service = Executors.newSingleThreadExecutor();
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
Object o = context.getMergedJobDataMap().get(ScheduleUtils.JOB_PARAM_KEY);
ScheduleJobAO scheduleJob;
if (o instanceof ScheduleJobAO) {
scheduleJob = (ScheduleJobAO) o;
} else {
scheduleJob = JSON.parseObject(JSON.toJSON(o).toString(), ScheduleJobAO.class);
}
//任务开始时间
long startTime = System.currentTimeMillis();
try {
//执行任务
logger.info("任务准备执行,任务ID:" + scheduleJob.getId());
ScheduleRunnable task = new ScheduleRunnable(scheduleJob.getBeanName(),
scheduleJob.getMethodName(), scheduleJob.getParams());
Future> future = service.submit(task);
future.get();
//任务执行总时长
long times = System.currentTimeMillis() - startTime;
logger.info("任务执行完毕,任务ID:" + scheduleJob.getId() + " 总共耗时:" + times + "毫秒");
} catch (Exception e) {
logger.error("任务执行失败,任务ID:" + scheduleJob.getId(), e);
} finally {
}
}
}
反射执行定时任务线程类:
package com.mall.shop.util;
import com.backstage.common.exception.BaseException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
/**
* 执行定时任务
*
*/
public class ScheduleRunnable implements Runnable {
private Object target;
private Method method;
private String params;
public ScheduleRunnable(String beanName, String methodName, String params) throws NoSuchMethodException, SecurityException {
this.target = SpringContextUtils.getBean(beanName);
this.params = params;
if (StringUtils.isNotBlank(params)) {
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
} else {
this.method = target.getClass().getDeclaredMethod(methodName);
}
}
@Override
public void run() {
try {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
} catch (Exception e) {
throw new BaseException(-1, "执行定时任务失败" + e.getMessage());
}
}
}
Spring Context 工具类:
package com.mall.shop.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring Context 工具类
*
*/
@Component
public class SpringContextUtils implements ApplicationContextAware {
public static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static T getBean(String name, Class requiredType) {
return applicationContext.getBean(name, requiredType);
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) {
return applicationContext.isSingleton(name);
}
public static Class extends Object> getType(String name) {
return applicationContext.getType(name);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static T getBean(Class requiredType) {
return applicationContext.getBean(requiredType);
}
}
8.controller
package com.mall.shop.controller;
import com.backstage.system.log.LogOperation;
import com.mall.shop.dto.request.ScheduleJobRequest;
import com.mall.shop.entity.customized.ScheduleJobAO;
import com.mall.shop.service.IScheduleJobService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* Created by yangfeng on 2020/01/23.
* 任务调度 controller
*/
@RestController
public class ScheduleJobController {
private static Logger LOG = LoggerFactory.getLogger(ScheduleJobController.class);
@Resource
private IScheduleJobService scheduleJobService;
/**
* 分页查询任务调度
*
* @return
*/
@PostMapping(value = "/scheduleJob/list")
@RequiresPermissions(value = {"scheduleJob:view", "scheduleJob:manage"}, logical = Logical.OR)
@LogOperation(action = "分页查询任务调度")
public Object list(ScheduleJobRequest request) {
return scheduleJobService.list(request);
}
/**
* 新增任务调度
*
* @param scheduleJob
* @return
*/
@PostMapping(value = "/scheduleJob/add")
@RequiresPermissions("scheduleJob:manage")
@LogOperation(action = "新增任务调度")
public Object add(ScheduleJobAO scheduleJob) {
return scheduleJobService.add(scheduleJob);
}
/**
* 修改任务调度
*
* @param scheduleJob
* @return
*/
@PostMapping(value = "/scheduleJob/update")
@RequiresPermissions("scheduleJob:manage")
@LogOperation(action = "修改任务调度")
public Object update(ScheduleJobAO scheduleJob) {
return scheduleJobService.update(scheduleJob);
}
/**
* 删除任务调度
*
* @return
*/
@PostMapping(value = "/scheduleJob/delete")
@RequiresPermissions("scheduleJob:manage")
@LogOperation(action = "删除任务调度")
public Object delete(String[] jobIds) {
return scheduleJobService.deleteBatch(jobIds);
}
@LogOperation(action = "立即执行任务")
@PostMapping("/scheduleJob/run")
@RequiresPermissions("scheduleJob:manage")
public Object run(String[] jobIds) {
return scheduleJobService.run(jobIds);
}
/**
* 暂停定时任务
*
* @param jobIds jobIds
*/
@LogOperation(action = "暂停定时任务")
@PostMapping("/scheduleJob/pause")
@RequiresPermissions("scheduleJob:manage")
public Object pause(String[] jobIds) {
return scheduleJobService.pause(jobIds);
}
/**
* 恢复定时任务
*
* @param jobIds jobIds
*/
@LogOperation(action = "恢复定时任务")
@PostMapping("/scheduleJob/resume")
@RequiresPermissions("scheduleJob:manage")
public Object resume(String[] jobIds) {
return scheduleJobService.resume(jobIds);
}
}
9.前端页面
package com.mall.shop.schedule;
import com.mall.shop.entity.customized.PurchaseOrderAO;
import com.mall.shop.enums.OrderStatus;
import com.mall.shop.service.IPurchaseOrderService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
* 过期自动取消订单
*/
@Component
public class OrderTask {
@Resource
private IPurchaseOrderService purchaseOrderService;
public void expireOrder() {
List orderList = purchaseOrderService.listExpireOrder().getData();
if (!CollectionUtils.isEmpty(orderList)) {
orderList.stream().forEach(o -> {
o.setOrderStatus(OrderStatus.YQX.getCode());
purchaseOrderService.update(o);
});
}
}
}