java定时器结合springboot_GitHub - tj071629/scheduleDemo: springboot整合Quartz实现动态配置定时任务...

springboot整合Quartz实现动态配置定时任务

​ 原创 各自远扬_JasonYan 发布于2018-04-04 11:17:48 阅读数 5884 收藏

更新于2018-05-25 17:20:26

​ 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/yunhan0806/article/details/79814903

展开

先展示一下后台管理定时任务效果图:

1、新增任务页面:

0dd8dde473d040ca966c4438c6d5146c.png

2、列表页(实现任务的禁用启用)

513530f8b8e515c25aa1495a1405250e.png

3、后台多任务执行日志(相互之间不干扰,计划任务到点自动执行!)

1e790442259dbb4287c1ebe9c5ef7d7e.png

4、数据库脚本:

-- Table structure for schedule_job

DROP TABLE IF EXISTS schedule_job;

CREATE TABLE schedule_job (

jobid bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务ID',

jobname varchar(40) DEFAULT NULL COMMENT '任务名称',

jobgroup varchar(40) DEFAULT NULL COMMENT '任务分组',

jobstatus char(1) NOT NULL DEFAULT '1' COMMENT '任务状态 0禁用 1启用',

auditstatus char(1) NOT NULL DEFAULT '0' COMMENT '审核状态 0 已创建 1 审核通过 2 审核驳回',

cronexpression varchar(40) NOT NULL COMMENT '任务运行时间表达式',

quartzclass varchar(255) DEFAULT NULL COMMENT '定时任务处理类',

description varchar(280) DEFAULT NULL COMMENT '描述信息',

PRIMARY KEY (jobid)

) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;

(附上述任务数据:)

67ac2756a14c6cffc529fdca79c4e6ac.png

5、定时任务后台处理类(核心):

package com.eb.admin.schedule;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.quartz.CronScheduleBuilder;

import org.quartz.CronTrigger;

import org.quartz.Job;

import org.quartz.JobBuilder;

import org.quartz.JobDetail;

import org.quartz.JobKey;

import org.quartz.Scheduler;

import org.quartz.TriggerBuilder;

import org.quartz.TriggerKey;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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.quartz.SchedulerFactoryBean;

import org.springframework.stereotype.Component;

import com.eb.admin.entity.ScheduleJob;

import com.eb.admin.service.ConfigService;

/**

* 调度工厂类

*

* @author Jason.Yan

* @since 2018/03/28

*

*/

@Configuration

@EnableScheduling

@Component

public class ScheduleFactory {

private static Logger logger = LoggerFactory.getLogger(ScheduleFactory.class);

private Map jobUniqueMap = new HashMap();// 当前Trigger使用的

@Autowired

private SchedulerFactoryBean schedulerFactoryBean;

public SchedulerFactoryBean getSchedulerFactoryBean() {

return schedulerFactoryBean;

}

public void setSchedulerFactoryBean(SchedulerFactoryBean schedulerFactoryBean) {

this.schedulerFactoryBean = schedulerFactoryBean;

}

@Autowired

private ConfigService configService;

public ConfigService getConfigService() {

return configService;

}

public void setConfigService(ConfigService configService) {

this.configService = configService;

}

//TODO 此处暂且注释,后续有后台定时任务逻辑 开启

@Scheduled(fixedRate = 5000) // 每隔5s查库,并根据查询结果决定是否重新设置定时任务

public void scheduleUpdateCronTrigger() throws Exception {

try {

// schedulerFactoryBean 由spring创建注入

Scheduler scheduler = schedulerFactoryBean.getScheduler();

List jobList = configService.findLegalJobList();

// 获取最新删除(禁用)任务列表,将其从调度器中删除,并且从jobUniqueMap中删除

List jobDelList = configService.findDelJobList();

for (ScheduleJob delJob : jobDelList) {

JobKey jobKey = JobKey.jobKey(delJob.getJobName(), delJob.getJobGroup());

scheduler.deleteJob(jobKey);

jobUniqueMap.remove(TriggerKey.triggerKey(delJob.getJobName(), delJob.getJobGroup()));

}

for (ScheduleJob job : jobList) {

TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());

// 获取trigger,即在spring配置文件中定义的 bean id="myTrigger"

CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

String dbCron = job.getCronExpression();// 该job数据库中的Trigger表达式

// 不存在,创建一个

if (null == trigger) {

//JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class).withIdentity(job.getJobName(), job.getJobGroup()).build();

try{

@SuppressWarnings("unchecked")

Class extends Job> clazz = (Class extends Job>) Class.forName(job.getQuartzClass());

JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getJobName(), job.getJobGroup()).build();

jobDetail.getJobDataMap().put("scheduleJob", job);

// 表达式调度构建器

CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

// 按新的cronExpression表达式构建一个新的trigger

trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();

jobUniqueMap.put(triggerKey.toString(), trigger.getCronExpression());

//currentCron = trigger.getCronExpression();

scheduler.scheduleJob(jobDetail, trigger);

}catch(Exception e){

e.printStackTrace();

logger.error(e.getMessage());

}

} else if(!jobUniqueMap.get(triggerKey.toString()).equals(dbCron)){

// Trigger已存在,那么更新相应的定时设置

// 表达式调度构建器

CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(dbCron);

// 按新的cronExpression表达式重新构建trigger

trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

// 按新的trigger重新设置job执行

scheduler.rescheduleJob(triggerKey, trigger);

jobUniqueMap.put(triggerKey.toString(), dbCron);

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

6、后台查询sql:

ConfigService.findLegalJobList=select * from schedule_job where jobstatus = 1 and auditstatus = 1

ConfigService.findDelJobList=select * from schedule_job where jobstatus = 0

7、后台查询方法实现类:

package com.eb.admin.service.impl;

import java.util.List;

import com.eb.admin.entity.ScheduleJob;

import com.eb.admin.service.ConfigService;

import com.eb.dataservice.dao.CommonDao;

import com.eb.dataservice.dao.SqlUtils;

public class ConfigServiceImpl implements ConfigService {

@SuppressWarnings("unchecked")

@Override

public List findLegalJobList() throws Exception {

CommonDao dao = CommonDao.getDao(dbkey);

String sql = SqlUtils.getSql("ConfigService.findLegalJobList");

return dao.findBeanList(ScheduleJob.class, sql);

}

@Override

public List findDelJobList() throws Exception {

CommonDao dao = CommonDao.getDao(dbkey);

String sql = SqlUtils.getSql("ConfigService.findDelJobList");

return dao.findBeanList(ScheduleJob.class, sql);

}

}

==============================================================================

追加:

有朋友问具体的实现类是怎么写的:我也贴出源码供参考:

这是其中一个任务对应的实现类:(理论上你配置了多少个定时任务,就需要写多少个实现类与之一一匹配,否则后台会报错!)

8、ScheduleTask1.java

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.quartz.DisallowConcurrentExecution;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.eb.admin.SpringContext;

import com.eb.admin.entity.User;

import com.eb.admin.service.UserMsgService;

import com.eb.admin.service.UserService;

import com.eb.admin.utils.DateUtils;

/**

* 定时任务实现类(清明节活动专场提醒)

*

* @author Jason.Yan

* @since 2018/04/3

*

*/

@DisallowConcurrentExecution

public class ScheduleTask1 implements Job {

private static Logger logger = LoggerFactory.getLogger(ScheduleTask1.class);

public String getTemplate(String templatename, Map params) throws Exception {

UserMsgService userMsgService = SpringContext.getBean("userMsgService", UserMsgService.class);

String template = userMsgService.getTemplate(templatename);

for (String key : params.keySet()) {

String v = params.get(key);

template = template.replace("${" + key + "}", v);

}

return template;

}

@Override

public void execute(JobExecutionContext context) throws JobExecutionException {

logger.info("==== 定时任务实现类(清明节活动专场提醒)ScheduleTask1 ====> 开启!" + DateUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss"));

UserService userService= SpringContext.getBean("userService",UserService.class);

UserMsgService userMsgService= SpringContext.getBean("userMsgService",UserMsgService.class);

try {

List userList = userService.getAllUsers();

String msg = getTemplate("qingmingregard", new HashMap());

for (User user : userList) {

userMsgService.addMsg(user.getId(), 1, 1, "【系统通知】", msg);

}

} catch (Exception e) {

logger.error(e.getMessage());

}

}

}

9、上面类中SpringContext.java配置类:(注意:需要放在你的springBoot启动类的同一级)

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 SpringContext implements ApplicationContextAware {

private static ApplicationContext applicationContext;

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

this.applicationContext = applicationContext;

}

public static ApplicationContext getApplicationContext() {

return applicationContext;

}

public static Object getBean(String name) {

return getApplicationContext().getBean(name);

}

public static T getBean(Class clazz) {

return getApplicationContext().getBean(clazz);

}

public static T getBean(String name, Class clazz) {

return getApplicationContext().getBean(name, clazz);

}

}

最后:我把整体的层级结构列出来供大家参考:

212fe45ffd04258aa8127fa55a10f3ba.png

以上为本人根据两篇博文所做的整理修改,原文参见:

本着尊重原作者的态度,转载请注明出处:

看了一些网友的留言,想要我整理一下源码,我也抽出点时间整理了一套可以正常运行的框架,里面包含了以上内容,

这套框架也可以作为企业级开发用,功能已经很完善(数据库可能需要自行调整一下)

CSDN没分了,收了3个资源分,不过分吧,觉得有帮助的请加个好评,谢谢~

下载地址:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值