java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaEE, JavaME, JavaSE)的总称。本站提供基于Java框架struts,spring,hibernate等的桌面应用、web交互及移动终端的开发技巧与资料

保持永久学习的心态,将成就一个优秀的你,来 继续搞起java知识。

Quartz学习笔记(七) quartz与spring实现任务动态管理面板

任务面板CRUD操作接口:

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.quartz.*;
import org.quartz.impl.StdScheduler;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * [简短描述该类的功能]
 *
 */
@Service
public class JobManager {
    private static final Logger log = LoggerFactory.getLogger(JobManager.class);
    @Resource
    private StdScheduler scheduler;
    
    /**
     * 获取计划中的任务列表
     * @return
     */
    public List<ScheduleJob> getPlanJobList(){
        List<ScheduleJob> jobList = new ArrayList<>();
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeySet = scheduler.getJobKeys(matcher);
            for (JobKey jobKey : jobKeySet){
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers){
                    ScheduleJob scheduleJob = new ScheduleJob();
                    this.wrapScheduleJob(scheduleJob,scheduler,jobKey,trigger);
                    jobList.add(scheduleJob);
                }
            }
        } catch (SchedulerException e) {
            log.error("获取计划任务列表失败: {}", ExceptionUtils.getStackTrace(e));
            throw new RuntimeException("获取计划任务列表失败",e);
        }
        return jobList;
    }

    /**
     * 获取正在运行的任务列表
     * @return
     */
    public List<ScheduleJob> getRunningJobList(){
        List<JobExecutionContext> executingJobList = scheduler.getCurrentlyExecutingJobs();
        List<ScheduleJob> jobList = new ArrayList<>(executingJobList.size());
        for(JobExecutionContext executingJob : executingJobList){
            ScheduleJob scheduleJob = new ScheduleJob();
            JobDetail jobDetail = executingJob.getJobDetail();
            JobKey jobKey = jobDetail.getKey();
            Trigger trigger = executingJob.getTrigger();
            this.wrapScheduleJob(scheduleJob,scheduler,jobKey,trigger);
            jobList.add(scheduleJob);
        }
        return jobList;
    }

    /**
     * 封装ScheduleJob对象
     * @param scheduleJob
     * @param scheduler
     * @param jobKey
     * @param trigger
     */
    private void wrapScheduleJob(ScheduleJob scheduleJob,Scheduler scheduler,JobKey jobKey,Trigger trigger){
        try {
            scheduleJob.setJobName(jobKey.getName());
            scheduleJob.setJobGroup(jobKey.getGroup());

            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            ScheduleJob job = (ScheduleJob)jobDetail.getJobDataMap().get("scheduleJob");
            scheduleJob.setDesc(job.getDesc());

            Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
            scheduleJob.setJobStatus(triggerState.name());
            if(trigger instanceof CronTrigger){
                CronTrigger cronTrigger = (CronTrigger)trigger;
                String cronExpression = cronTrigger.getCronExpression();
                scheduleJob.setCronExpression(cronExpression);
            }
        } catch (SchedulerException e) {
            log.error("获取触发器状态失败: {}", ExceptionUtils.getStackTrace(e));
            throw new RuntimeException(e);
        }
    }

    /**
     * 新增任务
     * @param scheduleJob
     */
    public void addJob(ScheduleJob scheduleJob){
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if(trigger != null){
                throw new BusinessException("添加任务失败,任务名称已重复");
            }
            JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class).withIdentity(scheduleJob.getJobName(),scheduleJob.getJobGroup()).build();
            jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);

            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
            trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).withSchedule(cronScheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            log.error("添加任务失败: {}", ExceptionUtils.getStackTrace(e));
            throw new RuntimeException("添加任务失败",e);
        }

    }

    /**
     * 暂停任务
     * @param scheduleJob
     */
    public void pauseJob(ScheduleJob scheduleJob){
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
           log.error("暂停任务失败: {}", ExceptionUtils.getStackTrace(e));
           throw new RuntimeException("暂停任务失败",e);
        }
    }

    /**
     * 恢复任务执行
     * @param scheduleJob
     */
    public void resumeJob(ScheduleJob scheduleJob){
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            log.error("恢复任务失败: {}", ExceptionUtils.getStackTrace(e));
            throw new RuntimeException("恢复任务失败",e);
        }
    }

    /**
     * 删除任务
     * @param scheduleJob
     */
    public void deleteJob(ScheduleJob scheduleJob){
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        try {
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            log.error("删除任务失败: {}", ExceptionUtils.getStackTrace(e));
            throw new RuntimeException("删除任务失败",e);
        }
    }

    /**
     * 立即执行任务
     * @param scheduleJob
     */
    public void runJobOnce(ScheduleJob scheduleJob){
        JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        try {
            scheduler.triggerJob(jobKey);
        } catch (Exception e) {
            log.error("只运行一次任务失败: {}", ExceptionUtils.getStackTrace(e));
            throw new RuntimeException("只运行一次任务失败",e);
        }
    }

    /**
     * 修改任务执行表达式
     * @param scheduleJob
     */
    public void updateJobCronExpression(ScheduleJob scheduleJob){
        TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
        try {
            CronTrigger cronTrigger = (CronTrigger)scheduler.getTrigger(triggerKey);

            //表达式调度构建器
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());

            //按新的cronExpression表达式重新构建trigger
            cronTrigger = cronTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();

            //按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, cronTrigger);
        } catch (SchedulerException e) {
            log.error("修改任务执行表达式失败: {}", ExceptionUtils.getStackTrace(e));
            throw new RuntimeException("修改任务执行表达式失败",e);
        }
    }

}

定时任务运行入口:

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.UUID;

/**
 * [定时任务运行工厂类]
 */
public class QuartzJobFactory implements Job {

    private static final Logger log = LoggerFactory.getLogger(QuartzJobFactory.class);

    public void execute(JobExecutionContext context) throws JobExecutionException {
        ScheduleJob scheduleJob = (ScheduleJob) context.getMergedJobDataMap().get("scheduleJob");
        String jobFullName = StringUtils.join(new String[]{scheduleJob.getJobGroup(),scheduleJob.getJobName()},".");
        String lockKey = jobFullName + ".lock";
        if(RedisUtil.acquireLock(lockKey, 1000)) {
            log.info("任务{}成功获取锁",jobFullName);
            String uid = UUID.randomUUID().toString();
            PushMsg msg = new PushMsg();
            msg.setInterfaceName("cn.gooday.scheduler.service.ISchedulerPullService");
            msg.setReqUniId(uid);
            msg.setMsgbody("msgbody");
            msg.setSystemid("systemA");
            PushInfo pushInfo = new PushInfo();
            pushInfo.setTopic("jsh-mq-service-test-zj4");
            pushInfo.setGoupName("jsh-mq-service-group-test-zj4");
            pushInfo.setSystemid("systemA");
            pushInfo.setReqUniId(uid);
            ArrayList<PushMsg> list = new ArrayList<PushMsg>();
            list.add(msg);
            pushInfo.setMsg(list);
            pushInfo.setIsOrderly("1");
            String jsonStr = JSON.toJSONString(pushInfo);
            LssMQPushService lssMQPushService = (LssMQPushService) SpringContextUtil.getBean("lssMQPushService");
            String rtn = lssMQPushService.pushInfo(jsonStr);
            log.info(rtn);
        }
    }
}

spring配置文件

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="configLocation" value="classpath:quartz.properties" />
 </bean>

quartz配置文件

org.quartz.scheduler.instanceName: MyScheduler
org.quartz.scheduler.instanceId: AUTO
#============================================================================
# ThreadPool
#============================================================================
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 20
org.quartz.threadPool.threadPriority: 5
#============================================================================
# JobStore
#============================================================================
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
#============================================================================
# Cluster
#============================================================================
org.quartz.jobStore.isClustered: true
org.quartz.jobStore.clusterCheckinInterval: 15000
org.quartz.jobStore.maxMisfiresToHandleAtATime: 1

org.quartz.jobStore.misfireThreshold: 120000
org.quartz.jobStore.tablePrefix: qrtz_
schedulerName:MyScheduler
startupDelay: 30
applicationContextSchedulerContextKey: applicationContextKey
overwriteExistingJobs : true
autoStartup: true
#============================================================================
# JDBC
#============================================================================
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties:false
org.quartz.jobStore.dataSource:qzDS
#org.quartz.dataSource.qzDS.connectionProvider.class:org.quartz.utils.PoolingConnectionProvider
org.quartz.dataSource.qzDS.connectionProvider.class:cn.gooday.scheduler.common.druid.DruidConnectionProvider
org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:root
org.quartz.dataSource.qzDS.maxConnection:30
org.quartz.dataSource.qzDS.validationQuery: select 0

实体类(序列化)

import java.io.Serializable;

public class ScheduleJob implements Serializable{
    private static final long serialVersionUID = 1L;
    private String jobId;
    private String jobName;
    private String jobGroup;
    private String jobStatus;
    private String cronExpression;
    private String interfaceName; //接口名称,用于MQ进行接口回调
    private String desc;

    public String getJobId() {
        return jobId;
    }

    public void setJobId(String jobId) {
        this.jobId = jobId;
    }

    public String getJobName() {
        return jobName;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }

    public String getJobGroup() {
        return jobGroup;
    }

    public void setJobGroup(String jobGroup) {
        this.jobGroup = jobGroup;
    }

    public String getJobStatus() {
        return jobStatus;
    }

    public void setJobStatus(String jobStatus) {
        this.jobStatus = jobStatus;
    }

    public String getCronExpression() {
        return cronExpression;
    }

    public void setCronExpression(String cronExpression) {
        this.cronExpression = cronExpression;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getInterfaceName() {
        return interfaceName;
    }

    public void setInterfaceName(String interfaceName) {
        this.interfaceName = interfaceName;
    }
}

因为水平有限,难免有疏忽或者不准确的地方,希望大家能够直接指出来,我会及时改正。一切为了知识的分享。

后续会有更多的精彩的内容分享给大家。