SpringBoot - 集成Quartz框架之CRON表达式

CRON是什么?

Quartz官网
CENTOS下的CRON服务及CRONTAB命令的区别

SpringBoot - 集成Quartz框架之Quartz简介(一)
SpringBoot - 集成Quartz框架之常用配置(二)
SpringBoot - 集成Quartz框架之具体步骤(三)
SpringBoot - 集成Quartz框架之独立数据源(四)
SpringBoot - 集成Quartz框架之常见问题(五)
SpringBoot - 集成Quartz框架之@DisallowConcurrentExecution注解详解(六)

CRON表达式

CRON表达式是一个字符串,字符串由5个或6个空格隔开,分为6个或7个域,每一个域代表一个含义,表达如如下:
秒 分 时 天(day-of-month) 月 周(day-of-week) 年[可选]
在这里插入图片描述在这里插入图片描述

常用示例

*/5 * * * * ?:每隔 5 秒执行一次
0 */1 * * * ?:每隔 1 分钟执行一次
0 0 2 1 * ? *:每月 1 日的凌晨 2 点执行一次
0 15 10 ? * MON-FRI:周一到周五每天上午 1015 执行一次
0 15 10 ? * 6L 2002-20062002 年至 2006 年的每个月的最后一个星期五上午 10:15 执行一次
0 0 23 * * ?:每天 23 点执行一次
0 0 1 * * ?:每天凌晨 1 点执行一次
0 0 1 1 * ?:每月 1 日凌晨 1 点执行一次
0 0 23 L * ?:每月最后一天 23 点执行一次
0 0 1 ? * L:每周星期天凌晨 1 点执行一次
0 26,29,33 * * * ?:在 26 分、29 分、33 分执行一次
0 0 0,13,18,21 * * ?:每天的 0 点、13 点、18 点、21 点都执行一次
0 0 10,14,16 * * ?:每天上午 10 点,下午 2 点,4 点执行一次
0 0/30 9-17 * * ?:朝九晚五工作时间内每半小时执行一次
0 0 12 ? * WED:每个星期三中午 12 点执行一次
0 0 12 * * ?:每天中午 12 点执行一次
0 15 10 ? * *:每天上午 10:15 执行一次
0 15 10 * * ?:每天上午 10:15 执行一次
0 15 10 * * ? *:每天上午 10:15 执行一次
0 15 10 * * ? 20052005 年的每天上午 10:15 执行一次
0 * 14 * * ?:每天下午 2 点到 2:59 期间的每 1 分钟执行一次
0 0/5 14 * * ?:每天下午 2 点到 2:55 期间的每 5 分钟执行一次
0 0/5 14,18 * * ?:每天下午 2 点到 2:55 期间和下午 6 点到 6:55 期间的每 5 分钟执行一次
0 0-5 14 * * ?:每天下午 2 点到 2:05 期间的每 1 分钟执行一次
0 10,44 14 ? 3 WED:每年三月的星期三的下午 2:102:44 执行一次
0 15 10 ? * MON-FRI:周一至周五的上午 10:15 执行一次
0 15 10 15 * ?:每月 15 日上午 10:15 执行一次
0 15 10 L * ?:每月最后一日的上午 10:15 执行一次
0 15 10 ? * 6L:每月的最后一个星期五上午 10:15 执行一次
0 15 10 ? * 6L 2002-20052002 年至 2005 年的每月的最后一个星期五上午 10:15 执行一次
0 15 10 ? * 6#3:每月的第三个星期五上午 10:15 执行一次

翻译CRON表达式

import java.text.ParseException;
import java.util.Date;
import org.quartz.CronExpression;

/**
 * CRON表达式工具类
 * @author ROCKY
 */
public class CronUtils {
    /**
     * 返回一个布尔值代表一个给定的CRON表达式是否有效
     */
    public static boolean isValid(String cronExpression) {
        return CronExpression.isValidExpression(cronExpression);
    }

    /**
     * 返回一个字符串值, 表示该消息无效CRON表达式给出有效性
     */
    public static String getInvalidMessage(String cronExpression) {
        try {
            new CronExpression(cronExpression);
            return null;
        } catch (ParseException pe) {
            return pe.getMessage();
        }
    }

    /**
     * 返回下一个执行时间根据给定的CRON表达式
     */
    public static Date getNextExecution(String cronExpression) {
        try {
            CronExpression cron = new CronExpression(cronExpression);
            return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
        } catch (ParseException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * 将一个给定的CRON表达式翻译成中文
     */
    private final static String[] CRON_EXPRESSION_DOMAIN = new String[]{"秒", "分", "时", "日", "月", "周", "年"};
    public static String translate(String expression) {

        if (StringUtils.isEmpty(expression)) {
            return expression;
        }

        String[] expressions = expression.split(" ");

        StringBuffer result = new StringBuffer();
        if (expressions.length == 6 || expressions.length == 7) {
            // 1. 年
            if (expressions.length == 7) {
                String year = expressions[6];
                if ((!year.equals("*") && !year.equals("?"))) {
                    result.append(year).append(CRON_EXPRESSION_DOMAIN[6]);
                }
            }

            // 2. 月
            String months = expressions[4];
            if (!months.equals("*") && !months.equals("?")) {
                if (months.contains("/")) {
                    result.append("从").append(months.split("/")[0]).append("日开始")
                            .append(",每").append(months.split("/")[1]).append(CRON_EXPRESSION_DOMAIN[4]);
                } else {
                    if (result.toString().contains("-")) {
                        result.append("每年");
                    }
                    result.append(months).append(CRON_EXPRESSION_DOMAIN[4]);
                }
            }

            // 3. 周
            String dayOfWeek = expressions[5];
            if (!dayOfWeek.equals("*") && !dayOfWeek.equals("?")) {
                if (dayOfWeek.contains(",")) {// 多个数字,逗号隔开
                    result.append("每周的第").append(dayOfWeek).append(CRON_EXPRESSION_DOMAIN[3]);
                } else if (dayOfWeek.contains("L") && dayOfWeek.length() > 1) {// 1L-7L
                    String index = dayOfWeek.split("L")[0];
                    String name = Weeks.name(index);
                    result.append("每月最后一周的");
                    result.append(name);
                } else if (dayOfWeek.contains("-")) {
                    String[] split = dayOfWeek.split("-");
                    String one = Weeks.name(split[0]);
                    String two = Weeks.name(split[1]);
                    result.append("每周").append(one).append("到").append(two);
                } else if (dayOfWeek.contains("#")) {
                    String[] split = dayOfWeek.split("#");
                    // 前面数字表示周几
                    String index = split[0];
                    // 后面的数字表示每月的第几周(1-4)
                    String weekOfMonth = split[1];
                    String name = Weeks.name(index);
                    result.append("每月第").append(weekOfMonth).append(CRON_EXPRESSION_DOMAIN[5]).append("的").append(name);
                } else {
                    if ("L".equals(dayOfWeek)) {
                        // L表示每周的最后一天
                        dayOfWeek = "7";
                    }
                    result.append("每周的");
                    result.append(Weeks.name(dayOfWeek));
                }
            }
            // 4. 日
            String days = expressions[3];
            if (!days.equals("*") && !days.equals("?")) {
                if (days.contains("/")) {
                    result.append("每周从第").append(days.split("/")[0]).append("天开始")
                            .append(",每").append(days.split("/")[1]).append(CRON_EXPRESSION_DOMAIN[3]);
                } else if ("L".equals(days)) {
                    // L表示每月的最后一天
                    result.append("每月最后一天");
                } else if ("W".equals(days)) {
                    // TODO 关于W的处理
                    result.append(days);
                } else {
                    result.append("每月").append(days).append("日");
                }
            } else {
                if ((result.toString().length() == 0 || expressions.length == 7) && !result.toString().contains("星期")) { // 前面没有内容的话,拼接下
                    result.append("每").append(CRON_EXPRESSION_DOMAIN[3]);
                }
            }
            // 5. 时
            String hours = expressions[2];
            if (!hours.equals("*")) {
                if (hours.contains("/")) {
                    result.append(getHourMinuteSecond(hours, 24, 2));
                } else {
                    if (!(result.toString().length() > 0)) { // 对于 , 的情况,直接拼接
                        result.append("每天").append(hours).append(CRON_EXPRESSION_DOMAIN[2]);
                    } else {
                        result.append(hours).append(CRON_EXPRESSION_DOMAIN[2]);
                    }
                }
            }

            // 6. 分
            String minutes = expressions[1];
            if (!minutes.equals("*")) {
                if (minutes.contains("/")) {
                    result.append(getHourMinuteSecond(minutes, 60, 1));
                } else if (minutes.equals("0")) {
                } else if (minutes.contains("-")) {
                    String[] splitMinute = minutes.split("-");
                    result.append(splitMinute[0]).append(CRON_EXPRESSION_DOMAIN[1]).append("到").append(splitMinute[1])
                            .append(CRON_EXPRESSION_DOMAIN[1]).append("每分钟");
                } else {
                    result.append(minutes).append(CRON_EXPRESSION_DOMAIN[1]);
                }
            }

            // 7. 秒
            String seconds = expressions[0];
            if (!seconds.equals("*")) {
                if (seconds.contains("/")) {
                    result.append(getHourMinuteSecond(seconds, 60, 0));
                } else if (!seconds.equals("0")) {
                    result.append(seconds).append(CRON_EXPRESSION_DOMAIN[0]);
                }
            }
            if (result.toString().length() > 0) {
                result.append("执行一次");
            }
        }
        return result.toString();
    }


    private static String getHourMinuteSecond(String time, int length, int index) {
        StringBuffer result = new StringBuffer();
        String[] split = time.split("/");
        String start = split[0];
        // 间隔
        String gap = split[1];
        String end = String.valueOf(length + (start.equals("*") ? 0 : Integer.parseInt(start)) - Integer.parseInt(gap));

        String unit1 = CRON_EXPRESSION_DOMAIN[index];
        String unit2 = CRON_EXPRESSION_DOMAIN[index];
        if (index == 1) {
            unit2 = "分钟";
        } else if (index == 2) {
            unit2 = "小时";
        }
        result.append("从").append(start.equals("*") ? 0 : Integer.parseInt(start)).append(unit1).append("开始").append("到").append(end)
                .append(unit1).append("范围内").append(",每隔").append(gap).append(unit2);
        return result.toString();
    }


    enum Weeks {
        SUN("1", "SUN", "星期天"),
        MON("2", "MON", "星期一"),
        TUE("3", "TUE", "星期二"),
        WED("4", "WED", "星期三"),
        THU("5", "THU", "星期四"),
        FRI("6", "FRI", "星期五"),
        SAT("7", "SAT", "星期六");

        private String index1;
        private String index2;
        private String name;

        Weeks(String index1, String index2, String name) {
            this.index1 = index1;
            this.index2 = index2;
            this.name = name;
        }

        public String getIndex1() {
            return index1;
        }

        public String getIndex2() {
            return index2;
        }

        public String getName() {
            return name;
        }

        public static String name(String index) {
            return Arrays.stream(Weeks.values()).filter(m -> m.getIndex1().equals(index) || m.getIndex2().equals(index)).map(m -> m.getName()).findFirst().get();
        }

    }


}

在线工具

1. CRON表达式在线生成工具
2. VUE-CRON在线生成工具

源码、示例及DEMO

源码、示例及DEMO

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringBoot 中实现定时任务可以使用 Quartz 框架Quartz 是一个开源的作业调度框架,可以用来创建简单或复杂的作业调度程序。 下面是使用 Quartz 实现定时任务的步骤: 1. 添加 Quartz 的依赖 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> ``` 2. 创建 Job 类 创建一个实现 org.quartz.Job 接口的 Job 类。Job 接口只有一个方法 execute(JobExecutionContext context),该方法会在作业执行时被调用。 ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 作业要执行的任务 } } ``` 3. 创建 Trigger Trigger 是定义作业调度时间的组件。可以创建多个 Trigger 对象,每个对象对应一个时间表达式。 ```java Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("triggerName", "groupName") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build(); ``` 上面的代码创建了一个 Trigger 对象,它的名称是 triggerName,所属的组是 groupName。它使用了一个 Cron 表达式,表示每隔 5 秒执行一次作业。 4. 创建 Scheduler Scheduler 是 Quartz 的核心组件,用于管理和调度作业和触发器。创建一个 Scheduler 对象,然后将 Job 和 Trigger 注册到 Scheduler 中。 ```java SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); JobDetail jobDetail = JobBuilder.newJob(MyJob.class) .withIdentity("jobName", "groupName") .build(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); ``` 上面的代码创建了一个 Scheduler 对象,并使用 JobBuilder 和 TriggerBuilder 创建了一个 JobDetail 对象和一个 Trigger 对象。然后将 JobDetail 和 Trigger 注册到 Scheduler 中,并启动 Scheduler。 完整的代码示例: ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 作业要执行的任务 } } public class QuartzConfig { @Bean public JobDetail jobDetail() { return JobBuilder.newJob(MyJob.class) .withIdentity("jobName", "groupName") .build(); } @Bean public Trigger trigger() { return TriggerBuilder.newTrigger() .withIdentity("triggerName", "groupName") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build(); } @Bean public Scheduler scheduler() throws SchedulerException { SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.scheduleJob(jobDetail(), trigger()); scheduler.start(); return scheduler; } } ``` 在上面的代码中,我们使用了 Spring 的注解 @Bean 来注册 JobDetail、Trigger 和 Scheduler。注意要捕获 SchedulerException 异常。 这样就完成了通过集成 Quartz 来实现 SpringBoot 定时任务的步骤。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cloneme01

谢谢您的支持与鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值