首页 > 其他分享 >cron表达式实现每年、每周、每月、每小时、每分、每秒周期执行

cron表达式实现每年、每周、每月、每小时、每分、每秒周期执行

时间:2022-08-18 16:35:27浏览次数:81  
标签:String 每分 cron planExecuteDefBO import com public 表达式

首先我们先来认识一下什么是cron表达式,cron表达式的格式。  

cron表达式的介绍

什么是cron表达式?

cron表达式是一个具有时间含义的字符串,一般用于定义定时任务的执行时间。

cron表达式的格式

{秒数}{分钟}{小时}{日期}{月份}{星期}{年份(可为空)}

cron表达式每个字段的允许值

  • 秒 0-59 , - * / 
  • 分 0-59 , - * / 
  • 小时 0-23 , - * / 
  • 日期 1-31 , - * ? / L W C 
  • 月份 1-12 或者 JAN-DEC , - * / 
  • 星期 1-7 或者 SUN-SAT , - * ? / L C # 
  • 年(可选) 留空, 1970-2099 , - * / 

每个符号的意义

* 表示所有值; 
? 表示未说明的值,即不关心它为何值; 
- 表示一个指定的范围; 
, 表示附加一个可能值; 
/ 符号前表示开始时间,符号后表示每次递增的值; 
L("last") ("last") "L" 用在day-of-month字段意思是 "这个月最后一天";用在 day-of-week字段, 它简单意思是 "7" or "SAT"。 如果在day-of-week字段里和数字联合使用,它的意思就是 "这个月的最后一个星期几" – 例如: "6L" means "这个月的最后一个星期五". 当我们用“L”时,不指明一个列表值或者范围是很重要的,不然的话,我们会得到一些意想不到的结果。 
W("weekday") 只能用在day-of-month字段。用来描叙最接近指定天的工作日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个 月第15天的工作日”,即如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第 16天即周一触发;如果这个月第15天是周二,那么就在触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在 day-of-month指明一天,不能是一个范围或列表。也可以用“LW”来指定这个月的最后一个工作日。 
# 只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用"6#3"指这个月第3个周五(6指周五,3指第3个)。如果指定的日期不存在,触发器就不会触发。 
C 指和calendar联系后计算过的值。例:在day-of-month 字段用“5C”指在这个月第5天或之后包括calendar的第一天;在day-of-week字段用“1C”指在这周日或之后包括calendar的第一天。

cron表达式的案列

  (1)0/2 * * * * ?   表示每2秒 执行任务

  (1)0 0/2 * * * ?    表示每2分钟 执行任务

  (1)0 0 2 1 * ?   表示在每月的1日的凌晨2点调整任务

  (2)0 15 10 ? * MON-FRI   表示周一到周五每天上午10:15执行作业

  (3)0 15 10 ? 6L 2002-2006   表示2002-2006年的每个月的最后一个星期五上午10:15执行作

  (4)0 0 10,14,16 * * ?   每天上午10点,下午2点,4点 

  (5)0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时 

  (6)0 0 12 ? * WED    表示每个星期三中午12点 

  (7)0 0 12 * * ?   每天中午12点触发 

  (8)0 15 10 ? * *    每天上午10:15触发 

  (9)0 15 10 * * ?     每天上午10:15触发 

  (10)0 15 10 * * ?    每天上午10:15触发 

  (11)0 15 10 * * ? 2005    2005年的每天上午10:15触发 

  (12)0 * 14 * * ?     在每天下午2点到下午2:59期间的每1分钟触发 

  (13)0 0/5 14 * * ?    在每天下午2点到下午2:55期间的每5分钟触发 

  (14)0 0/5 14,18 * * ?     在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 

  (15)0 0-5 14 * * ?    在每天下午2点到下午2:05期间的每1分钟触发 

  (16)0 10,44 14 ? 3 WED    每年三月的星期三的下午2:10和2:44触发 

  (17)0 15 10 ? * MON-FRI    周一至周五的上午10:15触发 

  (18)0 15 10 15 * ?    每月15日上午10:15触发 

  (19)0 15 10 L * ?    每月最后一日的上午10:15触发 

  (20)0 15 10 ? * 6L    每月的最后一个星期五上午10:15触发 

  (21)0 15 10 ? * 6L 2002-2005   2002年至2005年的每月的最后一个星期五上午10:15触发 

  (22)0 15 10 ? * 6#3   每月的第三个星期五上午10:15触发

cron表达式的在线生成工具:/https://cron.qqe2.com/

如何动态的生成cron表达式

在我我们实际的项目中,可能会出现这样的需求,由用户选择定时的执行一个任务,这个时候就需要后端开发人员根据用户设定的时间动态的生成cron表达式了。

在此,我来演示如何通过cron-utils生成cron表达式。

引入依赖

此处附有cron-utils的链接https://github.com/jmrozanec/cron-utils,内有使用示例

    <dependency>
      <groupId>com.cronutils</groupId>
      <artifactId>cron-utils</artifactId>
      <version>9.2.0</version>
    </dependency>

相关类

计划执行定义类

package com.spring4.cron;


import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;

/**
 * @Author: chenxuebing
 * @Description: 计划执行定义
 * @Date: 2022/8/10 16:33
 */
public class PlanExecuteDefBO {

    private static final long serialVersionUID = 4334316357655011464L;

    /**
     * 周期类型 minute:分钟 hour: 小时; day: 天; week: 周; month: 月; quarter: 季; year: 年
     */
    private String cycleType;

    /**
     * cron表达式
     */
    private String cron;

    /**
     * 定时任务id
     */
    private String jobId;

    /**
     * 开始时间
     */
    private LocalDate startTime;

    /**
     * 结束时间
     */
    private LocalDate endTime;

    /**
     * 周期内次数
     */
    private Integer numberOfCycles;

    /**
     * 指定一周哪几天
     */
    private List<Integer> weekDays;

    /**
     * 指定一个月哪几天
     */
    private List<Integer> monthDays;

    /**
     * 一周的星期几
     */
    private Integer dayOfWeek;

    /**
     * 第几周
     */
    private Integer week;

    /**
     * 重复规则
     */
    private String repeatRule;

    /**
     * 执行时间
     */
    private LocalTime executionTime;

    public String getCycleType() {
        return cycleType;
    }

    public void setCycleType(String cycleType) {
        this.cycleType = cycleType;
    }

    public void setStartTime(LocalDate startTime) {
        this.startTime = startTime;
    }

    public void setEndTime(LocalDate endTime) {
        this.endTime = endTime;
    }

    public String getCron() {
        return cron;
    }

    public void setCron(String cron) {
        this.cron = cron;
    }

    public String getJobId() {
        return jobId;
    }

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

    public Integer getNumberOfCycles() {
        return numberOfCycles;
    }

    public void setNumberOfCycles(Integer numberOfCycles) {
        this.numberOfCycles = numberOfCycles;
    }

    public LocalDate getStartTime() {
        return startTime;
    }

    public LocalDate getEndTime() {
        return endTime;
    }

    public List<Integer> getWeekDays() {
        return weekDays;
    }

    public void setWeekDays(List<Integer> weekDays) {
        this.weekDays = weekDays;
    }

    public List<Integer> getMonthDays() {
        return monthDays;
    }

    public void setMonthDays(List<Integer> monthDays) {
        this.monthDays = monthDays;
    }

    public Integer getDayOfWeek() {
        return dayOfWeek;
    }

    public void setDayOfWeek(Integer dayOfWeek) {
        this.dayOfWeek = dayOfWeek;
    }

    public Integer getWeek() {
        return week;
    }

    public void setWeek(Integer week) {
        this.week = week;
    }

    public String getRepeatRule() {
        return repeatRule;
    }

    public void setRepeatRule(String repeatRule) {
        this.repeatRule = repeatRule;
    }

    public LocalTime getExecutionTime() {
        return executionTime;
    }

    public void setExecutionTime(LocalTime executionTime) {
        this.executionTime = executionTime;
    }
}

枚举类

计划周期类型映射

package com.spring4.cron;

/**
 * @Author: chenxuebing
 * @Description: 质控计划周期类型映射
 * @Date: 2022/8/4 14:11
 */
public enum PlanCycleTypeEnum {
    MINUTE("minute", "分钟"),

    HOUR("hour", "小时"),

    DAY("day", "日"),

    WEEK("week", "周"),

    MONTH("month", "月"),

    QUARTER("quarter", "季度"),

    YEAR("year", "年");


    /**
     * 周期类型
     */
    private String cycleType;

    /**
     * 描述
     */
    private String description;

    PlanCycleTypeEnum(String cycleType, String description) {
        this.cycleType = cycleType;
        this.description = description;
    }

    public String getCycleType() {
        return cycleType;
    }

    public String getDescription() {
        return description;
    }
}

重复规则映射

选择每月周期执行可选择每月某几天执行或每月的第几周的星期几执行

package com.spring4.cron;

/**
 * @Author: chenxuebing
 * @Description: 重复规则
 * @Date: 2022/8/18 14:11
 */
public enum RepeatRuleEnum {
    WEEK("week", "周"),

    DATE("date", "日期");

    private String value;

    private String description;

    RepeatRuleEnum(String type, String description) {
        this.value = type;
        this.description = description;
    }

    public String getType() {
        return value;
    }

    public void setType(String type) {
        this.value = type;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

星期映射

package com.spring4.cron;

/**
 * @Author: chenxuebing
 * @Description: 星期映射
 * @Date: 2022/8/12 10:31
 */
public enum WeekEnum {
    SUNDAY(1, "星期天"),

    MONDAY(2, "星期一"),

    TUESDAY(3, "星期二"),

    WEDNESDAY(4, "星期三"),

    THURSDAY(5, "星期四"),

    FRIDAY(6, "星期五"),

    SATURDAY(7, "星期六");

    private Integer value;

    private String description;

    WeekEnum(Integer value, String description) {
        this.value = value;
        this.description = description;
    }

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

CronUtils

package com.spring4.cron;

import com.cronutils.builder.CronBuilder;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.field.expression.FieldExpression;
import com.cronutils.model.field.expression.FieldExpressionFactory;
import com.cronutils.model.field.expression.On;
import com.cronutils.model.field.value.SpecialChar;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;

import static com.cronutils.model.field.expression.FieldExpression.always;
import static com.cronutils.model.field.expression.FieldExpression.questionMark;
import static com.cronutils.model.field.expression.FieldExpressionFactory.*;

public class CronUntils {
    /**
     * 星期
     */
    private static final List<Integer> WEEKS =  Arrays.asList(WeekEnum.SUNDAY.getValue(),
            WeekEnum.MONDAY.getValue(),
            WeekEnum.THURSDAY.getValue(),
            WeekEnum.WEDNESDAY.getValue(),
            WeekEnum.THURSDAY.getValue(),
            WeekEnum.FRIDAY.getValue(),
            WeekEnum.SATURDAY.getValue());

    private static CronBuilder cronBuilder;

    static {
        cronBuilder = CronBuilder.cron(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ));
    }

    public static String createCron(PlanExecuteDefBO planExecuteDefBO) {
        LocalTime executionTime = planExecuteDefBO.getExecutionTime();
        LocalDate startTime = planExecuteDefBO.getStartTime();
        String cycleType = planExecuteDefBO.getCycleType();
        int minute = planExecuteDefBO.getExecutionTime().getMinute();
        int hour = executionTime.getHour();
        int day = startTime.getDayOfMonth();
        int month = startTime.getMonth().getValue();
        cronBuilder = cronBuilder.withSecond(on(executionTime.getSecond()));
        // 每分钟一次
        if (Objects.equals(PlanCycleTypeEnum.MINUTE.getCycleType(), cycleType)) {
            return cronBuilder.withDoW(questionMark())
                    .withMonth(always())
                    .withDoM(always())
                    .withHour(always())
                    .withMinute(always()).instance().asString();
        }

        // 每小时一次
        if (Objects.equals(PlanCycleTypeEnum.HOUR.getCycleType(), cycleType)) {
            return cronBuilder.withDoW(questionMark())
                    .withMonth(always())
                    .withDoM(always())
                    .withHour(always())
                    .withMinute(on(executionTime.getMinute())).instance().asString();
        }

        // 每天一次
        if (Objects.equals(PlanCycleTypeEnum.DAY.getCycleType(), cycleType)) {
            return cronBuilder.withDoW(questionMark())
                    .withMonth(always())
                    .withDoM(always())
                    .withHour(on(hour))
                    .withMinute(on(minute))
                    .instance().asString();
        }

        // 每周一次
        if (Objects.equals(PlanCycleTypeEnum.WEEK.getCycleType(), cycleType)) {
            List<FieldExpression> weekDays = new ArrayList<>();
            planExecuteDefBO.getWeekDays().forEach(e -> weekDays.add(FieldExpressionFactory.on(e)));
            return cronBuilder.withDoW(and(weekDays))
                    .withMonth(always())
                    .withDoM(questionMark())
                    .withHour(on(hour))
                    .withMinute(on(minute))
                    .instance().asString();
        }

        // 每月一次
        if (Objects.equals(PlanCycleTypeEnum.MONTH.getCycleType(), cycleType)) {
            List<FieldExpression> monthDays = new ArrayList<>();
            planExecuteDefBO.getMonthDays().forEach(e -> monthDays.add(FieldExpressionFactory.on(e)));
            if (Objects.equals(RepeatRuleEnum.DATE.getType(), planExecuteDefBO.getRepeatRule())) {
                return cronBuilder.withDoW(questionMark())
                        .withMonth(always())
                        .withDoM(and(monthDays))
                        .withHour(on(hour))
                        .withMinute(on(minute))
                        .instance().asString();
            }
            if (Objects.equals(RepeatRuleEnum.WEEK.getType(), planExecuteDefBO.getRepeatRule())) {
                return cronBuilder.withDoW(on(WEEKS.get(planExecuteDefBO.getDayOfWeek()), SpecialChar.HASH, planExecuteDefBO.getWeek()))
                        .withMonth(always())
                        .withDoM(questionMark())
                        .withHour(on(hour))
                        .withMinute(on(minute))
                        .instance().asString();
            }
        }

        // 每季度一次
        if (Objects.equals(PlanCycleTypeEnum.QUARTER.getCycleType(), cycleType)) {
            List<FieldExpression> flist = new ArrayList<>();
            On quarter1 = FieldExpressionFactory.on(1);
            On quarter2 = FieldExpressionFactory.on(4);
            On quarter3 = FieldExpressionFactory.on(7);
            On quarter4 = FieldExpressionFactory.on(10);
            flist.add(quarter1);
            flist.add(quarter2);
            flist.add(quarter3);
            flist.add(quarter4);
            return cronBuilder.withDoW(questionMark())
                    .withMonth(and(flist))
                    .withDoM(on(day))
                    .withHour(on(hour))
                    .withMinute(on(minute))
                    .instance().asString();
        }

        // 每年一次
        if (Objects.equals(PlanCycleTypeEnum.YEAR.getCycleType(), cycleType)) {
            List<FieldExpression> flist = new ArrayList<>();
            On on = FieldExpressionFactory.on(day);
            flist.add(on);
            return cronBuilder.withYear(always())
                    .withDoW(questionMark())
                    .withMonth(on(month))
                    .withDoM(on(day))
                    .withHour(on(hour))
                    .withMinute(on(minute))
                    .instance().asString();
        }

        // 按秒执行
        return cronBuilder.withYear(always())
                .withDoW(questionMark())
                .withMonth(always())
                .withDoM(always())
                .withHour(always())
                .withMinute(always()).instance().asString();
    }
}

测试类

package com.spring4.cron;

import com.cronutils.builder.CronBuilder;
import com.cronutils.descriptor.CronDescriptor;
import com.cronutils.mapper.CronMapper;
import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinition;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.field.expression.FieldExpression;
import com.cronutils.model.field.expression.FieldExpressionFactory;
import com.cronutils.model.field.expression.On;
import com.cronutils.model.field.value.SpecialChar;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;


import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.cronutils.model.field.expression.FieldExpression.always;
import static com.cronutils.model.field.expression.FieldExpression.questionMark;
import static com.cronutils.model.field.expression.FieldExpressionFactory.*;

public class CronDemo {
    public static void main(String[] args) {
        CronDefinition = cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
        CronParser parser = new CronParser(cronDefinition);
        CronDescriptor descriptor = CronDescriptor.instance(Locale.UK);
        LocalDate startTime = LocalDate.of(2022, 9, 1);
        LocalTime executeTime = LocalTime.of(9, 0, 0);
        PlanExecuteDefBO planExecuteDefBO = new PlanExecuteDefBO();
        planExecuteDefBO.setStartTime(startTime);
        planExecuteDefBO.setExecutionTime(executeTime);
        planExecuteDefBO.setCycleType("minute");
        // 每分钟执行一次
        String minute = CronUntils.createCron(planExecuteDefBO);
        System.out.println("每分钟:" + minute +  ":" + descriptor.describe(parser.parse(minute)));

        // 每小时执行一次
        planExecuteDefBO.setCycleType("hour");
        String hour = CronUntils.createCron(planExecuteDefBO);
        System.out.println("每小时:" + hour +  ":" +  descriptor.describe(parser.parse(hour)));

        // 每天执行一次
        planExecuteDefBO.setCycleType("day");
        String day = CronUntils.createCron(planExecuteDefBO);
        System.out.println("每天:" + day +  ":" +  descriptor.describe(parser.parse(day)));

        // 每周执行一次
        planExecuteDefBO.setCycleType("week");
        planExecuteDefBO.setWeekDays(Arrays.asList(1,3));
        String week = CronUntils.createCron(planExecuteDefBO);
        System.out.println("每周:" + week +  ":" +  descriptor.describe(parser.parse(week)));

        // 每月执行一次
        planExecuteDefBO.setCycleType("month");
        planExecuteDefBO.setMonthDays(Arrays.asList(1,11,25));
        //planExecuteDefBO.setRepeatRule("date"); // 指定月内某几天执行
        planExecuteDefBO.setRepeatRule("week"); // 可选每月第几周的星期几执行
        planExecuteDefBO.setDayOfWeek(1);
        planExecuteDefBO.setWeek(1);
        String month = CronUntils.createCron(planExecuteDefBO);
        System.out.println("每月:" + month +  ":" + descriptor.describe(parser.parse(month)));

        // 每季度执行一次
        planExecuteDefBO.setCycleType("quarter");
        String quarter = CronUntils.createCron(planExecuteDefBO);
        System.out.println("每季度:" + quarter +  ":" + descriptor.describe(parser.parse(quarter)));

        // 每年执行一次
        planExecuteDefBO.setCycleType("year");
        String year = CronUntils.createCron(planExecuteDefBO);
        System.out.println("每年:" + year +  ":" + descriptor.describe(parser.parse(year)));


    }
}

运行结果

 

标签:String,每分,cron,planExecuteDefBO,import,com,public,表达式
From: https://www.cnblogs.com/Auge/p/16599000.html

相关文章

  • leetcode10-正则表达式匹配
    正则表达式匹配dpdp[i][j]表示s[0:i]和p[0:j]是否匹配。如果i==0&&j==0,那么说明两个字符串都没有选择字符,是true如果j==0,那么说明匹配串没有字符而原字符串......
  • 正则表达式断言和分组捕获以及贪婪
    正则的写法比较多,而且方法也很多,做到提取,替换,都需要不同的正则来一,零宽断言(正向先行断言,负向先行断言,负向后行断言,正向后行断言) 断言:断定正则里面有什么字符 零宽:......
  • linux-crontab每分钟定时执行
    [root@tingnan-DB3tandelindata]#servicecrondrestart#重启定时任务,有restart和reload两个命令[root@tingnan-DB3tandelindata]#servicecrondstatus#查看执......
  • 构造表达式树
    一个表达式的典型形式(中缀表达式)为12+4*5-(4/3+123) 先将其转换为后缀表达式(可用双栈法)[12,4,5,*,+,4,3,/,123,+,-]以下构造操作均需将原始数......
  • 使用正则表达式替换手机号中间四位数为 * 号
    在有的接口或者界面上,为了保护手机号隐私,因此需要把手机号中间4位数变为*号,这种可以用正则表达式来实现替换构建匹配手机号的正则表达式要求手机号是11位,且第一位是1......
  • springboot~用正则表达式提取bearer token
    前后一体的应用,是这样进行认证的用户向服务端发送验证信息(用户名、密码);服务端验证成功就向用户返回一个sessionid;服务端保存了这个session_id对应的信息,并写入用户......
  • Python逆向爬虫之正则表达式
    Python逆向爬虫之正则表达式字符串是我们在编程的时候很常用的一种数据类型,检查会在字符串里面查找一些内容,对于比较简单的查找,字符串里面就有一些内置的方法可以处理,对于......
  • re相关正则表达式(re.sub、re.I 、re.S、re.M)
    re.I表示忽略大小写re.S表示全文匹配re.M表示全文拼配行尾段位的字符或者数字,影响^和$re.sub表示替换使用方法:re.sub(pattern,repl,string,count=0,flags=0)......
  • 正则表达式
     定义:/[0-9]+/、 /[0-9]+/i、/[0-9]+/g、/[0-9]+/gi规则:^和$匹配一个位置,开始和结束;*、+、?表示重复次数,分别为任意次、至少一次、零次或1次;中括号表示范围[a..z]......
  • 正则表达式查找邮箱等数据
    相当于一个小工具,记录一下。importjava.util.regex.Matcher;importjava.util.regex.Pattern;//正则表达式实例,查找数据中的邮箱手机号和座机号publicclassRegex......