美文网首页
QuartzTask任务调度

QuartzTask任务调度

作者: 楼兰King | 来源:发表于2021-01-19 10:11 被阅读0次

    项目简介
    基于quartz的二次集成
    支持集群
    支持其它web项目进行功能开发
    动态控制定时任务启动、暂停、重启、删除、添加、修改
    支持多数据库
    支持自实现Scheduler、Job、Trigger监听,系统自动注册
    支持自主选择Trigger类型,已支持CronTrigger、SimpleTrigger
    支持一个Job对应多个Trigger,且可设置不同的Trigger类型
    支持Job中Autowired Spring bean
    支持JobData自动赋值给Job的成员变量(名称相同)
    支持Job、Trigger同时携带JobData
    使用教程
    引入依赖
    在settings.gradle中引入模块

    includeFlat("quartz-task")
    project(":quartz-task").projectDir = new File(rootDir,"../../../framework/packs/quartz-task/backend/")
    选择使用系统数据源、自主数据源(默认不需要修改)
    默认使用系统数据源,如需要自主配置数据源,则需要重写数据源配置类,并注入到QuartzConfig中,并替换数据源即可,也可以通过quartz.propertys进行配置

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setConfigLocation(quartzProperties().getScheduler().getConfigLocation());
        schedulerFactoryBean.setDataSource(dataSource);
        schedulerFactoryBean.setJobFactory(quartzSpringBeanJobFactory());
        schedulerFactoryBean.setSchedulerName(quartzProperties().getScheduler().getSchedulerName());
        schedulerFactoryBean.setTaskExecutor(threadPoolTaskExecutor());
        schedulerFactoryBean.setTransactionManager(transactionManager);
        schedulerFactoryBean.setApplicationContextSchedulerContextKey(quartzProperties().getScheduler().getApplicationContextSchedulerContextKey());
        schedulerFactoryBean.setOverwriteExistingJobs(quartzProperties().getScheduler().isOverwriteExistingJobs());
        schedulerFactoryBean.setAutoStartup(quartzProperties().getScheduler().isAutoStartup());
        schedulerFactoryBean.setStartupDelay(quartzProperties().getScheduler().getStartupDelay());
        return schedulerFactoryBean;
    }
    

    新建QuartzJobService,且继承自DefaultQuartzJobBean
    此处执行调度任务逻辑,如有需要可以注入业务逻辑bean进行调用

    package com.softium.xsk.facade.service;
    
    import com.softium.xsk.quartz.task.AbstractQuartzJobBean;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.stereotype.Service;
    
    @Service
    public class QuartzJobService extends AbstractQuartzJobBean {
    
        @Override
        public String name() {
            return this.getClass().getName();    }
    
        @Override
        protected void executeInternalService(JobExecutionContext context) throws JobExecutionException {
            //此处执行调度任务逻辑,如有需要可以注入业务逻辑bean进行调用
            System.out.println("-------执行调度任务逻辑----------");
        }
    }
    

    Job中注入Service,实现自己的逻辑

    @Override
    protected void executeInternalService(JobExecutionContext context) throws JobExecutionException {
        //此处执行调度任务逻辑,如有需要可以注入业务逻辑bean进行调用
        System.out.println("-------执行调度任务逻辑----------");
    }
    

    配置到Scheduler中
    具体的配置调用请参考QuartzJobController的demo测试类

    /**
     * 动态添加任务
     */
    @PostMapping(value = "/addjob")
    public void addjob() throws SchedulerException {
        QuartzJob quartzJob = new QuartzJob();
        quartzJob.setKey(new JobKey("testJob", "testJobGroup"));
        quartzJob.setDescription("TEST-JOB");
        quartzJob.setJobClass(quartzJobService.getClass());
    
        Set<QuartzTrigger> triggers = new HashSet<>();
    
        triggers.add(QuartzTriggerBuilder.newTrigger()
                     .ofType(QuartzTrigger.TriggerType.CRON)
                     .withIdentity("testJobTrigger", "testJobTriggerGroup")
                     .withDescription("TEST-JOB-TRIGGER")
                     .withCronExpression("30 * * * * ?")
                     .build());
        quartzJob.setTriggers(triggers);
        defaultQuartzTaskHandler.addJob(quartzJob);
    }
    

    配置示例
    application.yml配置

    king:
      quartz:
        thread-pool:
          thread-name-prefix: KingThreadPoolTaskExecutor-
          thread-priority: 5
          daemon: false
          thread-group-name: KingThreadPoolTaskExecutorGroup
          core-pool-size: 20
          max-pool-size: 50
          keep-alive-seconds: 60
          queue-capacity: 100
          allow-core-thread-timeout: false
          waitfor-tasks-tocomplete-onshutdown: false
          await-termination-seconds: 60 * 15
        scheduler:
          config-location: classpath:quartz.properties
          scheduler-name: king-scheduler
          application-context-scheduler-contextkey: applicationContext
          overwrite-existing-jobs: true
          auto-startup: true
          startup-delay: 10
    quartz.properties配置
    
    org.quartz.scheduler.instanceName = quartzScheduler
    org.quartz.scheduler.instanceId = AUTO
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
    org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    org.quartz.jobStore.tablePrefix = QRTZ_
    org.quartz.jobStore.isClustered = true
    org.quartz.jobStore.clusterCheckinInterval = 20000
    org.quartz.scheduler.skipUpdateCheck = true
    org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
    org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
    org.quartz.plugin.shutdownhook.cleanShutdown = true
    

    使用说明
    样例参考

    package com.hello.king.facade.controller.task;
    
    import com.hello.king.commons.util.fast.U;
    import com.hello.king.facade.service.QuartzJobService;
    import com.hello.king.quartz.task.QuartzJob;
    import com.hello.king.quartz.task.QuartzJobBuilder;
    import com.hello.king.quartz.task.QuartzTrigger;
    import com.hello.king.quartz.task.QuartzTriggerBuilder;
    import com.hello.king.quartz.task.handler.DefaultQuartzTaskHandler;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import org.quartz.JobDataMap;
    import org.quartz.JobKey;
    import org.quartz.SchedulerException;
    import org.quartz.TriggerKey;
    import org.quartz.impl.calendar.AnnualCalendar;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.HashSet;
    import java.util.Set;
    
    @Api(tags = "QuartzJobController",value ="QuartzJob定时任务样例" )
    @RestController
    @RequestMapping(value = "quartzJob")
    public class QuartzJobController {
    
        @Autowired
        private DefaultQuartzTaskHandler defaultQuartzTaskHandler;
        @Autowired
        private QuartzJobService quartzJobService;
    
    
        /**
         * 动态添加Cron任务
         */
        @ApiOperation(value = "/addjob",notes = "动态添加任务")
        @PostMapping(value = "/addjob")
        public void addjob() throws SchedulerException {
            QuartzJob quartzJob = new QuartzJob();
            quartzJob.setKey(new JobKey("testJob", "testJobGroup"));
            quartzJob.setDescription("TEST-JOB");
            quartzJob.setJobClass(quartzJobService.getClass());
    
            Set<QuartzTrigger> triggers = new HashSet<>();
    
            triggers.add(QuartzTriggerBuilder.newTrigger()
                    .ofType(QuartzTrigger.TriggerType.CRON)
                    .withIdentity("testJobTrigger", "testJobTriggerGroup")
                    .withDescription("TEST-JOB-TRIGGER")
                    .withCronExpression("30 * * * * ?")
                    .build());
            quartzJob.setTriggers(triggers);
            defaultQuartzTaskHandler.addJob(quartzJob);
        }
    
        /**
         * 动态添加Simple任务
         * <p>
         *     startNow(true) 可以立即开始执行
         *     执行完毕自动删除Trigger触发器
         *     如要删除job任务,则需要使用job的delete方法
         * </p>
         */
        @ApiOperation(value = "/addSimpleJob",notes = "动态添加任务")
        @PostMapping(value = "/addSimpleJob")
        public void addSimpleJob() throws SchedulerException {
            QuartzJob quartzJob = new QuartzJob();
            quartzJob.setKey(new JobKey("testSimpleJob", "testSimpleJobGroup"));
            quartzJob.setDescription("TEST-SIMPLE-JOB");
            quartzJob.setJobClass(quartzJobService.getClass());
            Set<QuartzTrigger> triggers = new HashSet<>();
            triggers.add(QuartzTriggerBuilder.newTrigger()
                    .ofType(QuartzTrigger.TriggerType.SIMPLE)
                    .startNow(true)//是否现在开始执行
    //                .startAt(U.Date.parse("2020-05-15 16:10:00")) //开始时间
    //                .withIntervalInSeconds(10) //间隔时间
    //                .withRepeatCount(10) //重复次数
                    .withIdentity("testSimpleJobTrigger", "testSimpleJobTriggerGroup")
                    .withDescription("TEST-SIMPLE-JOB-TRIGGER")
                    .build());
            quartzJob.setTriggers(triggers);
            defaultQuartzTaskHandler.saveOrUpdateJob(quartzJob);
        }
    
        /**
         * 动态添加Calendar任务
         * <p>
         *     startNow(true) 可以立即开始执行
         *     执行完毕自动删除Trigger触发器
         *     如要删除job任务,则需要使用job的delete方法
         * </p>
         */
        @ApiOperation(value = "/addCalendarJob",notes = "动态添加任务")
        @PostMapping(value = "/addCalendarJob")
        public void addCalendarJob() throws SchedulerException {
            QuartzJob quartzJob = new QuartzJob();
            quartzJob.setKey(new JobKey("testSimpleJob", "testSimpleJobGroup"));
            quartzJob.setDescription("TEST-SIMPLE-JOB");
            quartzJob.setJobClass(quartzJobService.getClass());
    
    
            AnnualCalendar annualCalendar = new AnnualCalendar();
            annualCalendar.setDayExcluded( U.Date.parse("2020-05-15 16:10:00").toCalendar(), true);//排除的日期,如果设置为false则为包含
            defaultQuartzTaskHandler.addCalendar("annualCalendar", annualCalendar, false, false);
    
            Set<QuartzTrigger> triggers = new HashSet<>();
            triggers.add(QuartzTriggerBuilder.newTrigger()
                    .ofType(QuartzTrigger.TriggerType.SIMPLE)
                    .startAt(U.Date.parse("2020-05-15 16:10:00")) //开始时间
                    .withIntervalInSeconds(10) //间隔时间
                    .withRepeatCount(10) //重复次数
                    .withIdentity("testSimpleJobTrigger", "testSimpleJobTriggerGroup")
                    .withDescription("TEST-SIMPLE-JOB-TRIGGER")
                    .withCalendarName("annualCalendar")
                    .build());
            quartzJob.setTriggers(triggers);
            defaultQuartzTaskHandler.saveOrUpdateJob(quartzJob);
    
        }
    
    
        /**
         * 动态更新任务
         */
        @ApiOperation(value = "/updateJob",notes = "动态更新任务")
        @PostMapping(value = "/updateJob")
        public void updateJob() throws SchedulerException {
            QuartzJob quartzJob = new QuartzJob();
            quartzJob.setKey(new JobKey("testJob", "testJobGroup"));
            quartzJob.setDescription("TEST-JOB-UPDATE");
            quartzJob.setJobClass(quartzJobService.getClass());
            quartzJob.setJobData(null);
    
            defaultQuartzTaskHandler.updateJob(quartzJob);
        }
    
    
        /**
         * 暂停任务
         */
        @ApiOperation(value = "/pauseJob",notes = "暂停任务")
        @PostMapping(value = "/pauseJob")
        public void pauseJob() throws SchedulerException {
            this.defaultQuartzTaskHandler.pauseJob(QuartzJobBuilder.newJob()
                    .withIdentity("testJob", "testJobGroup")
                    .build()
                    .getKey());
        }
    
        /**
         * 继续任务
         */
        @ApiOperation(value = "/resumeJob",notes = "继续任务")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "name",value = "JobKey.name",required = true,dataType = "String",paramType="query"),
                @ApiImplicitParam(name = "group",value = "JobKey.group",required = true,dataType = "String",paramType="query")
        })
        @PostMapping(value = "/resumeJob")
        public void resumeJob(String name,String group) throws SchedulerException {
            this.defaultQuartzTaskHandler.resumeJob(new JobKey(name,group));
        }
    
        /**
         * 触发任务
         */
        @ApiOperation(value = "/triggerJob/key",notes = "继续任务")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "name",value = "JobKey.name",required = true,dataType = "String",paramType="query"),
                @ApiImplicitParam(name = "group",value = "JobKey.group",required = true,dataType = "String",paramType="query")
        })
        @PostMapping(value = "/triggerJob/key")
        public void triggerJob(@RequestParam String name,@RequestParam String group) throws SchedulerException {
            this.defaultQuartzTaskHandler.triggerJob(new JobKey(name,group));
        }
    
        /**
         * 触发任务
         *
         * <p>立即触发一次任务</p>
         */
        @ApiOperation(value = "/triggerJob",notes = "触发任务-立即触发一次任务")
        @PostMapping(value = "/triggerJob")
        public void triggerJob() throws SchedulerException {
    
            JobKey jobKey =new JobKey("testJob", "testJobGroup");
            JobDataMap jobDataMap = new JobDataMap();
            this.defaultQuartzTaskHandler.triggerJob(jobKey, jobDataMap);
        }
    
    
        /**
         * 删除任务
         */
        @ApiOperation(value = "/deleteJob",notes = "删除任务")
        @PostMapping(value = "/deleteJob")
        public void deleteJob() throws SchedulerException {
            JobKey jobKey =new JobKey("testJob", "testJobGroup");
            this.defaultQuartzTaskHandler.deleteJob(jobKey);
        }
    
        /**
         * 删除任务QuartzJob
         */
        @ApiOperation(value = "/deleteJob/key",notes = "删除任务")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "name",value = "QuartzJob.name",required = true,dataType = "String",paramType="query"),
                @ApiImplicitParam(name = "group",value = "QuartzJob.group",required = true,dataType = "String",paramType="query")
        })
        @PostMapping(value = "/deleteJob/key")
        public void deleteJob(String name,String group) throws SchedulerException {
            this.defaultQuartzTaskHandler.deleteJob(QuartzJobBuilder.newJob()
                    .withIdentity( name, group)
                    .build());
        }
    
        /**
         * 添加任务Trigger
         */
        @ApiOperation(value = "/addTrigger",notes = "添加任务Trigger")
        @PostMapping(value = "/addTrigger")
        public void addTrigger() throws SchedulerException {
            QuartzTrigger quartzTrigger = new QuartzTrigger();
            quartzTrigger.setJobKey(new JobKey("testJob", "testJobGroup"));
            quartzTrigger.setKey(new TriggerKey("testJobTrigger", "testJobTriggerGroup"));
            quartzTrigger.setType(QuartzTrigger.TriggerType.CRON);
            quartzTrigger.setCronExpression("10 * * * * ?");
            quartzTrigger.setDescription("添加的触发器,每十秒执行一次");
            this.defaultQuartzTaskHandler.addTrigger(quartzTrigger);
        }
    
        /**
         * 更新任务Trigger
         */
        @ApiOperation(value = "/updateTrigger",notes = "更新任务Trigger")
        @PostMapping(value = "/updateTrigger")
        public void updateTrigger() throws SchedulerException {
            this.defaultQuartzTaskHandler.updateTrigger(QuartzTriggerBuilder.newTrigger()
                    .forJob("testJob", "testJobGroup")
                    .withIdentity("testJobTrigger", "testJobTriggerGroup")
                    .withOriginalIdentity("testJobTrigger", "testJobTriggerGroup")
                    .ofType(QuartzTrigger.TriggerType.CRON)
                    .withCronExpression("15 * * * * ?")
                    .withDescription("修改的触发器,每十秒执行一次")
                    .build());
        }
    
        /**
         * 暂停任务Trigger
         */
        @ApiOperation(value = "/pauseTrigger",notes = "暂停任务Trigger")
        @PostMapping(value = "/pauseTrigger")
        public void pauseTrigger() throws SchedulerException {
            this.defaultQuartzTaskHandler.pauseTrigger(QuartzTriggerBuilder.newTrigger()
                    .withIdentity("testJobTrigger", "testJobTriggerGroup")
                    .build());
        }
    
        /**
         * 暂停任务Trigger
         */
        @ApiOperation(value = "/pauseTrigger/key",notes = "暂停任务Trigger")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "name",value = "TriggerKey.name",required = true,dataType = "String",paramType="query"),
                @ApiImplicitParam(name = "group",value = "TriggerKey.group",required = true,dataType = "String",paramType="query")
        })
        @PostMapping(value = "/pauseTrigger/key")
        public void pauseTrigger(String name,String group) throws SchedulerException {
            this.defaultQuartzTaskHandler.pauseTrigger(new TriggerKey(name, group));
        }
    
        /**
         * 暂停所有任务Trigger
         */
        @ApiOperation(value = "/pauseAll",notes = "暂停所有任务Trigger")
        @PostMapping(value = "/pauseAll")
        public void pauseAll() throws SchedulerException {
            this.defaultQuartzTaskHandler.pauseAll();
        }
    
        /**
         * 重启任务Trigger
         */
        @ApiOperation(value = "/resumeTrigger",notes = "重启任务Trigger")
        @PostMapping(value = "/resumeTrigger")
        public void resumeTrigger() throws SchedulerException {
            this.defaultQuartzTaskHandler.resumeTrigger(QuartzTriggerBuilder.newTrigger()
                    .withIdentity("testJobTrigger", "testJobTriggerGroup")
                    .build());
        }
    
        /**
         * 重启任务Trigger
         */
        @ApiOperation(value = "/resumeTrigger/key",notes = "重启任务Trigger")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "name",value = "TriggerKey.name",required = true,dataType = "String",paramType="query"),
                @ApiImplicitParam(name = "group",value = "TriggerKey.group",required = true,dataType = "String",paramType="query")
        })
        @PostMapping(value = "/resumeTrigger/key")
        public void resumeTrigger(String name,String group) throws SchedulerException {
            this.defaultQuartzTaskHandler.resumeTrigger(new TriggerKey(name, group));
        }
    
        /**
         * 删除任务Trigger
         */
        @ApiOperation(value = "/deleteTrigger",notes = "删除任务Trigger")
        @PostMapping(value = "/deleteTrigger")
        public void deleteTrigger() throws SchedulerException {
            this.defaultQuartzTaskHandler.deleteTrigger(QuartzTriggerBuilder.newTrigger()
                    .withIdentity("testJobTrigger", "testJobTriggerGroup")
                    .build());
        }
    
        /**
         * 删除任务Trigger
         */
        @ApiOperation(value = "/deleteTrigger/key",notes = "删除任务Trigger")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "name",value = "TriggerKey.name",required = true,dataType = "String",paramType="query"),
                @ApiImplicitParam(name = "group",value = "TriggerKey.group",required = true,dataType = "String",paramType="query")
        })
        @PostMapping(value = "/deleteTrigger/key")
        public void deleteTrigger(String name,String group) throws SchedulerException {
            this.defaultQuartzTaskHandler.deleteTrigger(new TriggerKey(name,group));
        }
    }
    

    功能扩展
    QuartzTaskHandler 任务处理接口,其中有添加、修改、删除、暂停、重启等功能接口

    AbstractSchedulerListener Scheduler监听,可自行实现自己需要的Scheduler监听

    AbstractJobListener Job监听,可自行实现自己需要的Job监听

    AbstractTriggerListener Trigger监听,可自行实现自己需要的Trigger监听

    数据库说明
    数据库表信息解析
    qrtz_blob_triggers : 以Blob 类型存储的触发器。
    qrtz_calendars:存放日历信息, quartz可配置一个日历来指定一个时间范围。
    qrtz_cron_triggers:存放cron类型的触发器。
    qrtz_fired_triggers:存放已触发的触发器。
    qrtz_job_details:存放一个jobDetail信息。
    qrtz_job_listeners:job监听器。
    qrtz_locks: 存储程序的悲观锁的信息(假如使用了悲观锁)。
    qrtz_paused_trigger_graps:存放暂停掉的触发器。
    qrtz_scheduler_state:调度器状态。
    qrtz_simple_triggers:简单触发器的信息。
    qrtz_trigger_listeners:触发器监听器。
    qrtz_triggers:触发器的基本信息。
    触发时间配置的三种方式
    cron 方式:采用cronExpression表达式配置时间。
    simple 方式:和JavaTimer差不多,可以指定一个开始时间和结束时间外加一个循环时间。[请参考样例中addSimpleJob()方法]
    calendars 方式:可以和cron配合使用,用cron表达式指定一个触发时间规律,用calendar指定一个范围。 注意:cron方式需要用到的4张数据表: qrtz_triggers,qrtz_cron_triggers,qrtz_fired_triggers,qrtz_job_details。
    Cron表达式
    Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:

    (1) Seconds Minutes Hours DayofMonth Month DayofWeek Year

    (2)Seconds Minutes Hours DayofMonth Month DayofWeek

    结构   corn从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份(可为空)

    例 "0 0 12 ? * WED" 在每星期三下午12:00 执行(年份通常 省略)

    各字段的含义

    通配符说明 星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如, 在分钟字段时,表示“每分钟”;

    问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;

    减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12;

    逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五;

    斜杠(/):x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y;

    L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示“这个月的最后X天”,例如,6L表示该月的最后星期五;

    W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围;

    LW组合:在日期字段可以组合使用LW,它的意思是当月的最后一个工作日;

    井号(#):该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发;

    C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。

    Cron表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。


    image.png

    生成工具

    cron表达式在线生成工具http://www.pppet.net/

    相关文章

      网友评论

          本文标题:QuartzTask任务调度

          本文链接:https://www.haomeiwen.com/subject/jrlqzktx.html