spring boot + quartz实现多任务动态新增/删除调度

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-quartz</artifactId>
     <version>2.1.0.RELEASE</version>
 </dependency>
package com.XXX.task;

import com.alibaba.fastjson.JSONObject;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.XXX.model.VarMonitor;
import com.XXX.service.varMonitor.impl.VarMonitorServiceImpl;
import com.XXX.utils.DateUtil;
import com.XXX.utils.RedisUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
@DisallowConcurrentExecution
public class JobService implements InitializingBean {
    
    

    private static final Logger LOGGER = LoggerFactory.getLogger(JobService.class);

    private static final String PREFIX = "varMonitor_";

    private static final String JOB_MAP_KEY = "varMonitor";

    @Resource
    public JedisCluster jedisCluster;

    @Resource
    private SchedulerFactoryBean schedulerFactoryBean;

    @Resource
    private TaskMapper taskMapper;

    @Resource
    private VarMonitorServiceImpl varMonitorService;

    @Resource
    private RedisUtil redisUtil;

    @ApolloConfig
    private transient Config config;

    private void configScheduler() {
    
    
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        try {
    
    
            scheduler.clear();
        } catch (SchedulerException e) {
    
    
            LOGGER.error("configScheduler clear error:" + e.toString());
        }

        if (config == null) {
    
    
            config = ConfigService.getAppConfig();
        }
        boolean sendWitch = config.getBooleanProperty("switch", true);
        if (!sendWitch) {
    
    
            LOGGER.info(String.format("configScheduler sendWitch=%s", false));
            return;
        }

        // 应用启动时读取DB已有的定时任务,并执行
        List<VarMonitor> monitorList = taskMapper.queryAllActive();
        if (CollectionUtils.isEmpty(monitorList)) {
    
    
            LOGGER.info("configScheduler: empty monitorList");
            return;
        }
        for (VarMonitor job : monitorList) {
    
    
            try {
    
    
                if (StringUtils.isNotEmpty(job.getCronExp())) {
    
    
                    JobDetail jobDetail = JobBuilder.newJob(VarAlertJob.class)
                            .withIdentity(PREFIX + job.getId().toString()).build();
                    CronTrigger trigger = TriggerBuilder.newTrigger()
                            .withIdentity(PREFIX + job.getId().toString())
                            .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExp())).build();
                    jobDetail.getJobDataMap().put(JOB_MAP_KEY, job);
                    scheduler.scheduleJob(jobDetail, trigger);
                }
            } catch (Exception e) {
    
    
                LOGGER.error("configScheduler error:" + e.toString());
            }
        }
    }

    private Class<? extends Job> getJobExecutor(VarMonitor job) {
    
    
        return VarAlertJob.class;
    }

    /**
     * 新增任务
     */
    public void addJob(VarMonitor job) {
    
    
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        try {
    
    
            JobDetail jobDetail = JobBuilder.newJob(getJobExecutor(job))
                    .withIdentity(job.getId().toString(), Scheduler.DEFAULT_GROUP).build();
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getId().toString())
                    .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExp())).build();
            jobDetail.getJobDataMap().put(JOB_MAP_KEY, job);
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
    
    
            LOGGER.error("addJob with error:" + e);
        }
    }

    /**
     * 删除任务
     */
    public void removeJob(Integer id) {
    
    
        try {
    
    
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(id.toString(), Scheduler.DEFAULT_GROUP);
            // 停止、移除触发器
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            scheduler.deleteJob(new JobKey(PREFIX + id.toString(), Scheduler.DEFAULT_GROUP));
        } catch (Exception e) {
    
    
            LOGGER.error("removeJob with error:" + e);
        }
    }

    @Override
    public void afterPropertiesSet() {
    
    
        configScheduler();
    }

    /**
     * process VarMonitor one by one
     */
    private void processItem(VarMonitor item) {
    
    
        String key = String.format("%s_%s_%s", "processItem", DateUtil.getDateString(new Date(), DateUtil.DATE_COMPACT_FORMAT), item.getId());
        try {
    
    
            boolean result = redisUtil.tryGetDistributedLock(key, 10);
            if (result) {
    
    
                LOGGER.info(String.format("id=%d and varName=%s and monitorName=%s running at %s", item.getId(), item.getVarName(),
                        item.getMonitorName(), DateUtil.getDateString(new Date(), DateUtil.DATE_TIME_FORMAT)));
                if (item.getMonitorId() <= 2) {
    
    
                    varMonitorService.dealWithTimes(item);
                }
                if (item.getMonitorId() == 3) {
    
    
                    varMonitorService.dealWithCalcValue(item);
                }
            }
        } catch (Exception e) {
    
    
            LOGGER.error("processItem:" + e);
        } finally {
    
    
            redisUtil.releaseDistributedLock(key);
        }
    }

    private class VarAlertJob implements Job {
    
    

        private VarMonitor monitor;

        @Override
        public void execute(JobExecutionContext context) {
    
    
        	// 关键:利用context从JobDataMap取出所有需要定时调度的task
            JobDataMap dataMap = context.getJobDetail().getJobDataMap();
            if (monitor == null) {
    
    
                monitor = JSONObject.parseObject(JSONObject.toJSONString(dataMap.get(JOB_MAP_KEY)), VarMonitor.class);
            }
            processItem(monitor);
        }
    }

}

猜你喜欢

转载自blog.csdn.net/lonelymanontheway/article/details/108696308