弹簧克隆与普通克隆?

2022-08-31 09:17:01

我试图在遗留的Java / Spring / Hibernate项目中工作cron工作,所以我决定使用spring调度程序。

我希望myTask.doStuff在每个月的第一个星期日的12:00运行。

在我的应用程序上下文中.xml我已经配置了我的任务计划程序,例如:

<task:scheduled-tasks scheduler="MyTaskScheduler">
    <task:scheduled ref="myTask" method="doStuff" cron="0 0 12 ? 1/1 SUN#1 *"/> <!-- Every first Sundy of the month -->
</task:scheduled-tasks>

<task:scheduler id="MyTaskScheduler" pool-size="10"/>

问题 cron 表达式本身是: 0 0 12 ? 1/1 SUN#1 *

并且是一个bean,它有一个名为的方法,当从单元测试运行时可以完美地工作。myTaskdoStuff

当我构建和部署时,我得到了一个来自spring的bootime异常:

Caused by: java.lang.IllegalArgumentException: cron expression must consist of 6 fields (found 7 in 0 0 12 ? 1/1 SUN#1 *)
at org.springframework.scheduling.support.CronSequenceGenerator.parse(CronSequenceGenerator.java:233)
at org.springframework.scheduling.support.CronSequenceGenerator.<init>(CronSequenceGenerator.java:81)
at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.java:54)
at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.java:44)
at org.springframework.scheduling.config.ScheduledTaskRegistrar.afterPropertiesSet(ScheduledTaskRegistrar.java:129)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)

鉴于我是第一次使用cron表达式,我的第一个假设是我做错了什么,但我使用cronmaker进行了双重检查,它给了我同样的结果。

所有文档都说:cron表达式是由六个或七个子表达式(字段)组成的字符串。1 个

尽管如此,我还是尝试了敲掉第7个元素(年份),因为它不在任何示例中,并得到了一个不同的错误消息:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.scheduling.config.ScheduledTaskRegistrar#0': Invocation of init method failed; nested exception is java.lang.NumberFormatException: For input string: "0#1"

...org.springframework.scheduling 是否支持与其他所有内容不同的 cron 风格?特定于弹簧的文档只说“cron表达式”。

在这种情况下,如何使此 cron 表达式按预期工作?任何帮助将不胜感激。

目前,我的解决方案是简化这个表达式,让它在每个星期天运行,并预先附加一些Java逻辑来计算它是什么月份的哪个星期日,看看它是否有效 - 但这种方式违背了配置方法的目的,似乎是一个反模式。


答案 1

Spring 计划任务的格式与 cron 表达式的格式不同。

它们不遵循与 UNIX cron 表达式相同的格式。

只有 6 个字段:

  • 第二
  • 分钟
  • 小时
  • 月中的某一天,
  • 星期几。

星号 (*) 表示匹配任何匹配项。*/X 表示“每个 X”(请参阅示例)。

一周中的数字天数对我不起作用。此外,“MON-FRI”更容易阅读。下面是一些示例表达式:

"0 0 18 * * MON-FRI" means every weekday at 6:00 PM. 

"0 0 */1 * * *" means every hour on the hour.

"0 0 */8 * * *" means every 8 hours on the hour.

"0 0 12 1 * *" means 12:00 PM on the first day of every month. 

在这里,您可以找到一些其他信息

此外,您可能会发现弹簧文档很有用


答案 2

从以下方面注意到:https://www.baeldung.com/cron-expressions

春季计划任务是这样的:

1 2 3 4 5 6 Index
- - - - - -
* * * * * * command to be executed
- - - - - -
| | | | | | 
| | | | | ------- Day of week (MON - SUN)
| | | | --------- Month (1 - 12)
| | | ----------- Day of month (1 - 31)
| |-------------- Hour (0 - 23)
| --------------- Minute (0 - 59)
----------------- Seconds (0 - 59)

寄件人: https://www.cyberciti.biz/faq/how-do-i-add-jobs-to-cron-under-linux-or-unix-oses/

Linux Cron 作业是这样的:

1 2 3 4 5 Index
- - - - -
* * * * * command to be executed
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

附注:

  • 有些文章说,有可能有一个7可选的参数,这是年份,我尝试使用最新的弹簧,它显示错误,所以我认为它不起作用。
  • 如果你的Linux cron job表达式足够简单,似乎可以在前面放一个0,它将转换为spring调度任务表达式。
    • 例如,每 5 分钟一次
      • */5 * * * *Linux cron job
      • 0 */5 * * * *春季计划任务

奖励:春季计划克伦发电机

  1. 点击Show code snippet
  2. 点击Run Code snippet
  3. 玩得愉快!

$('.select2').select2({
  width: '100%'
});

//// Init ////////////
$dropdown = $("#secondsSelect");
for (let i = 1; i < 60; i++) {
  $dropdown.append($("<option />").val(i).text(i));
}
$dropdown = $("#minSelect");
for (let i = 1; i < 60; i++) {
  $dropdown.append($("<option />").val(i).text(i));
}
$dropdown = $("#hoursSelect");
for (let i = 1; i < 24; i++) {
  $dropdown.append($("<option />").val(i).text(i));
}
$dropdown = $("#dayOfMonthSelect");
for (let i = 1; i < 32; i++) {
  $dropdown.append($("<option />").val(i).text(i));
}
//// Init End ////////////


$('.select2').on('select2:select', function(e) {
  let value = e.params.data.id;
  let prevValue = $(this).val().length > 0 ? $(this).val()[0] : null;

  if (value != parseInt(value)) {
    $(this).val(value).change();
  } else if (prevValue != parseInt(prevValue)) {
    $(this).val(value).change();
  }
  calculateSpringCron();
});

let r = function(dropdown) {
  return dropdown.val().join(",");

}

let calculateSpringCron = function() {

  let result = [
    r($("#secondsSelect")),
    r($("#minSelect")),
    r($("#hoursSelect")),
    r($("#dayOfMonthSelect")),
    r($("#monthsSelect")),
    r($("#weekdaySelect")),
  ];

  $("#result").val(result.join(" "));

  $("#result-expand").html(result.join(" &nbsp; &nbsp;"))

}

calculateSpringCron();
.ms-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding-left: 3em;
  padding-right: 3em;
  background: none !important;
  padding-bottom: 5em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/multi-select/0.9.12/css/multi-select.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/multi-select/0.9.12/js/jquery.multi-select.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/js/select2.min.js"></script>

<div class="row">
  <div class="col-12">
    <h1>Spring Schedule Cron Generator</h1>
  </div>
</div>
<div class="row">
  <div class="col-4">
    Seconds:
    <select id="secondsSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every seconds</option>
      <option value="*/2">Every even seconds</option>
      <option value="1-59/2">Every odd seconds</option>
      <option value="*/5">Every 5 seconds</option>
      <option value="*/10">Every 10 seconds</option>
      <option value="*/15">Every 15 seconds</option>
      <option value="*/30">Every 30 seconds</option>
    </select>
  </div>
  <div class="col-4">
    Minutes:
    <select id="minSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every minutes</option>
      <option value="*/2">Every even minutes</option>
      <option value="1-59/2">Every odd minutes</option>
      <option value="*/5">Every 5 minutes</option>
      <option value="*/10">Every 10 minutes</option>
      <option value="*/15">Every 15 minutes</option>
      <option value="*/30">Every 30 minutes</option>
    </select>
  </div>
  <div class="col-4">
    Hours:
    <select id="hoursSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every hour</option>
      <option value="*/2">Every even hour</option>
      <option value="1-11/2">Every odd hour</option>
      <option value="*/3">Every 3 hour</option>
      <option value="*/4">Every 4 hour</option>
      <option value="*/6">Every 6 hour</option>
    </select>
  </div>
</div>

<div class="row">
</div>

<div class="row">
  <div class="col-4">
    Days of month:
    <select id="dayOfMonthSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every day of month</option>
      <option value="*/2">Even day of month</option>
      <option value="1-31/2">Odd day of month</option>
      <option value="*/5">Every 5 days of month (5,10,15...)</option>
      <option value="*/10">Every 10 days of month (10,20,30...)</option>
    </select>
  </div>
  <div class="col-4">
    Months:
    <select id="monthsSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every month</option>
      <option value="*/2">Even months</option>
      <option value="1-11/2">Odd months</option>
      <option value="*/4">Every 4 months</option>
      <option value="*/6">Every 6 months(half year)</option>
      <option value="1">Jan</option>
      <option value="2">Feb</option>
      <option value="3">Mar</option>
      <option value="4">Apr</option>
      <option value="5">May</option>
      <option value="6">Jun</option>
      <option value="7">Jul</option>
      <option value="8">Aug</option>
      <option value="9">Sep</option>
      <option value="10">Oct</option>
      <option value="11">Nov</option>
      <option value="12">Dec</option>
    </select>
  </div>
  <div class="col-4">
    Weekday:
    <select id="weekdaySelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every weekday</option>
      <option value="MON-FRI">Weekdays (MON-FRI)</option>
      <option value="SAT,SUN">Weekend</option>
      <option value="SUN">SUN</option>
      <option value="MON">MON</option>
      <option value="TUE">TUE</option>
      <option value="WED">WED</option>
      <option value="THU">THU</option>
      <option value="FRI">FRI</option>
      <option value="SAT">SAT</option>
    </select>
  </div>
</div>
<div class="row">
  <div class="col-12">
    Result:
    <input id="result" class="form-control" /> With a bit of seperation for better viewing:<br/>
    <h1 id="result-expand"></h1>
  </div>
</div>

推荐