Java Spring cron 与普通 cron?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30887822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 10:19:31  来源:igfitidea点击:

Spring cron vs normal cron?

javaspringcron

提问by Paul

I'm trying to get a cron job working within a legacy Java/Spring/Hibernate project, so I decided to use the spring scheduler.

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

I want myTask.doStuff to run at 12:00 on the first Sunday of every month.

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

In my application-context.xml I've configured my task scheduler like:

在我的 application-context.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"/>

with the problem cron expression itself being the: 0 0 12 ? 1/1 SUN#1 *

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

and myTaskis a bean, which has a method called doStuffthat works perfectly when run from unit tests.

andmyTask是一个 bean,它有一个调用的方法doStuff,当从单元测试运行时可以完美地工作。

When I build and deploy I get a bootime exception from spring:

当我构建和部署时,我从 spring 收到一个启动时异常:

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)

Given that i'm using cron expressions for the first time, my first assumption was that I was doing something wrong, but I double checked using cronmakerand it gave me the same result.

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

All the documentations says: A cron expression is a string consisting of six or seven subexpressions (fields).1

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

despite this I tried knocking off the 7th element(year) since it's not in any of the examples, and got a different error message:

尽管如此,我还是尝试取消第 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"

... does org.springframework.scheduling support a different flavor of cron from everything else? the spring-specific documentationjust says 'cron expressions'.

... org.springframework.scheduling 是否支持与其他一切不同的 cron 风格?特定于 spring 的文档只是说“cron 表达式”。

How can I get this cron expression to work as expected in this context? Any help at all would be appreciated.

我怎样才能让这个 cron 表达式在这种情况下按预期工作?任何帮助都将不胜感激。

At the moment my solution would be to simplify this expression to just run every Sunday, and prepend some Java logic to calculate which Sunday of the month it is, and see if that works - but that sort of defeats the purpose of the configuration approach and seems like an antipattern.

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

采纳答案by Dezso Gabos

Spring Scheduled tasks are not in the same format as cron expressions.

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

They don't follow the same format as UNIX cron expressions.

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

There are only 6 fields: second, minute, hour, day of month, month, day(s) of week. Asterisk (*) means match any. */X means "every X" (see examples). Numeric days of the week do not work for me. Besides, "MON-FRI" is much easier to read. Here are some example expressions:

只有 6 个字段:秒、分、小时、月中的天、月、周中的天。星号 (*) 表示匹配任何。*/X 表示“每个 X”(参见示例)。一周中的数字天数对我不起作用。此外,“MON-FRI”更容易阅读。以下是一些示例表达式:

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

“0 0 18 * * MON-FRI”表示每个工作日下午 6:00。

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

“0 0 */1 * * *”表示每小时整点。

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

“0 0 */8 * * *”表示每小时每8小时一次。

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

“0 0 12 1 * *”表示每月第一天的中午12:00。

Here you can find some additional information: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html

在这里你可以找到一些额外的信息:http: //docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html

Also you may find the spring documentation useful: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/integration.html#scheduling

您也可能会发现 spring 文档很有用:https: //docs.spring.io/spring-framework/docs/current/spring-framework-reference/integration.html#scheduling

回答by Ng Sek Long

Taking some note from: https://www.baeldung.com/cron-expressions

请注意:https: //www.baeldung.com/cron-expressions

A Spring Scheduled tasks is like this:

一个 Spring Scheduled 任务是这样的:

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)

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

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

A Linux Cron job is like this:

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)

Side note:

边注:

  • Some article said it is possible to have a 7 optional param which is year, I have tried using latest spring and it show error, so I don't think it is working.
  • If your Linux cron job expressionis simple enough, seems like it is possible to just put an 0 in frontand it will convert to the spring scheduled tasks expression
    • E.g. Every 5 minutes
      • */5 * * * *Linux cron job
      • 0 */5 * * * *Spring schedule tasks
  • 一些文章说可能有一个 7 可选参数是year,我尝试使用最新的 spring 并且它显示错误,所以我认为它不起作用。
  • 如果您的Linux cron 作业表达式足够简单,似乎可以只在前面放一个 0,它将转换为spring 计划任务表达式
    • 例如每 5 分钟
      • */5 * * * *Linux 定时任务
      • 0 */5 * * * *春季计划任务

Bonus: Spring Schedule Cron Generator

奖励:Spring Schedule Cron Generator

  1. Click on Show code snippet
  2. Click on Run Code snippet
  3. Have fun!
  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">MON</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>