首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring Quartz 動態排程實戰(二):UI 參數轉換為 Cron Expression 核心邏輯

     編輯:Java 相關知識

接續第一篇(頁面配置),本文深入解析如何將前端收集的多維排程參數(頻率、具體時間、星期、日期等)轉換為標準 Unix Cron Expression。這是動態排程系統中最核心、邏輯最複雜的環節。

前端參數映射模型

ActionForm 收集的關鍵字段:

  • everyWhat:頻率類型 — monthly(每月)、weekly(每週)、userDefined(自定義日期)
  • commonNeeds:[秒, 分, 時] — 所有模式共用
  • monthlyNeeds:[第幾週(1-4), 星期幾(1-7)] — 每月模式專用
  • weeklyNeeds:星期幾(1-7) — 每週模式專用
  • userDefinedNeeds:yyyy-MM-dd — 自定義日期模式專用

核心轉換算法:CronExpConversion

public class CronExpConversion {
    // 特殊字符常量
    static class CronExRelated {
        static final String _ANY = "*";
        static final String _EVERY = "?";
        static final String _THENTH = "#"; // 第幾個星期幾
        static Map<String, String> specialCharacters = Map.of(
            "_ANY", "*", "_EVERY", "?", "_THENTH", "#"
        );
    }

    public static String convertDateToCronExp(String everyWhat,
            String[] commonNeeds, String[] monthlyNeeds,
            String weeklyNeeds, String userDefinedNeeds) {

        String commons = String.join(" ", commonNeeds) + " "; // 秒 分 時

        if ("monthly".equals(everyWhat)) {
            // 格式:秒 分 時 ? 月 第幾週#星期幾
            // 例:0 30 10 ? 1/1 6#3 (每月第三個週五 10:30)
            String dayOfWeek = monthlyNeeds[1] + "#" + monthlyNeeds[0];
            return (commons + "* " + dayOfWeek).trim();

        } else if ("weekly".equals(everyWhat)) {
            // 格式:秒 分 時 ? * 星期幾
            return (commons + "* " + weeklyNeeds).trim();

        } else if ("userDefined".equals(everyWhat)) {
            // 格式:秒 分 時 日 月 ?
            String[] parts = userDefinedNeeds.split("-");
            String year = parts[0]; // Quartz Cron 不支持年份,忽略
            String month = parts[1].replaceFirst("^0", "");
            String day = parts[2].replaceFirst("^0", "");
            return (commons + day + " " + month + " ?").trim();
        }
        return "";
    }
}

關鍵 Cron 語法解析

模式Cron 結構關鍵字段含義
每月秒 分 時 ? 月 星期#第幾週用 # 指定「第 N 個星期幾」,? 佔位「日」
每週秒 分 時 ? * 星期* 表示每月,? 佔位「日」
自定義秒 分 時 日 月 ?具體日期,年份被 Quartz 忽略

常見坑點與修正

  1. 前導零:month/day 需去除前導零(replaceFirst("^0", "")),否則 Quartz 解析報錯。
  2. 年份字段:標準 Quartz Cron 為 6 位(秒 分 時 日 月 星期),不包含年份,代碼中已註釋掉年份拼接。
  3. 星期表示:1=星期日 ... 7=星期六,與 Java Calendar 一致。
  4. ? **與** *:? 用於「日」與「星期」互斥字段,表示「無具體值」。

單元測試驗證

@Test
public void testMonthly() {
    String[] common = {"0", "30", "10"}; // 10:30:00
    String[] monthly = {"3", "6"};       // 第3週 的 週五(6)
    String cron = CronExpConversion.convertDateToCronExp("monthly", common, monthly, null, null);
    assertEquals("0 30 10 ? * 6#3", cron);
}

掌握此轉換邏輯,即可構建強大的可視化排程配置介面,讓非技術人員也能輕鬆維護定時任務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved