93

ここに重複があることは知っていますが、これはおそらく私の場合ですが、ここで提供しようとするより良い説明に値するでしょう。

Spring アプリケーション コンテキストを使用して Java Web アプリケーションを操作しています。このコンテキストでは、Quartz を使用してスケジュールされたジョブを定義しました。これらのジョブは、.properties ファイルで定義された cron によってトリガーされます。

Spring コンテキストは war に組み込まれていますが、.properties ファイルはアプリケーション サーバー (この場合は Tomcat) にあります。

これは問題なく、環境 (開発、統合、運用など) に応じて異なる cron を定義できます。

現在、このアプリケーションを自分のコンピューターでローカルに実行している場合、これらのジョブが実行されることは望ましくありません。トリガーされないcron式を書く方法はありますか?

4

8 に答える 8

82

TL;DR

Quartz 1 では、この cron: 59 59 23 31 12 ? 2099(最後の有効な日付) を使用できます。
Quartz 2 では、次の cron を使用できます。0 0 0 1 1 ? 2200

遠い未来の表現を使う

を使用していくつかの簡単なテストを行いorg.quartz.CronExpressionました。

String exp = "0 0 0 1 1 ? 3000";
boolean valid = CronExpression.isValidExpression(exp);
System.out.println(valid);
if (valid) {
    CronExpression cronExpression = new CronExpression(exp);
    System.out.println(cronExpression.getNextValidTimeAfter(new Date()));
}

するとString exp = "# 0 0 0 1 1 ?";isValidテストは戻りますfalse

上記のサンプルを使用すると、出力は次のようになります。

true
null

意味:

  • 式は有効です。
  • この式に一致する次の日付はありません。

ただし、スケジューラが cron トリガーを受け入れるには、後者が将来の日付と一致する必要があります。

数年試してみたところ、年が2300年を超えると、Quartzはもう気にならないように見えることがわかりました(ただし、Quartz 2のドキュメントで年の最大値への言及は見つかりませんでした)。これを行うためのよりクリーンな方法があるかもしれませんが、これは今のところ私のニーズを満たします。

最後に、私が提案する cron は0 0 0 1 1 ? 2200.

クォーツ 1 バリアント

Quartz 1 では、2099 年が最後の有効な年であることに注意してください。したがって、 Maciej Matys の提案を使用するように cron 式を適合させることができます。59 59 23 31 12 ? 2099

代替手段: 過去の日付を使用する

Arnaud Denoyelleは、より洗練されたものを提案しました。上記の私のテストでは、正しい表現として検証されています。遠い未来の日付を選択する代わりに、遠い過去の日付を選択してください。

0 0 0 1 1 ? 1970(Quartz のドキュメントによると、最初の有効な式)。

ただし、このソリューションは機能しません。

hippofluffは、Quartz が過去に式が二度と実行されないことを検出し、例外をスローすることを強調しました。

org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire.

これは長い間Quartz にあったようです。

教訓: テストはそのままでは絶対確実ではない

これは私のテストの弱点を浮き彫りにします: a をテストしたい場合は、 1を持たなければならCronExpressionないことを覚えておいてください。それ以外の場合、渡すスケジューラーは、上記の例外で単純に拒否します。nextValidTime

テスト コードを次のように変更することをお勧めします。

String exp = "0 0 0 1 1 ? 3000";
boolean valid = CronExpression.isValidExpression(exp);
if (valid) {
    CronExpression cronExpression = new CronExpression(exp);
    valid = cronExpression.getNextValidTimeAfter(new Date()) != null;
}
System.out.println("Can I use <" + exp + ">? " + (valid ? "Go ahead!" : "This shall fail."));

では、考える必要はありません。出力を読むだけです。


1これは、Arnaud のソリューションをテストしたときに忘れてしまった部分であり、私をばかにして、私のテストが証明されていないことを証明しました。

于 2012-12-12T09:43:47.020 に答える
44

技術的には、オプションの Quartz 年フィールドの有効な値は 1970 ~ 2099 であるため、2300 は予期される値ではありません。本当にこれを行う必要あり、使用しているバージョンの Quartz が有効な cron 構文 (1 日から 31 日、1 月から 12 日など) を強制しようとしていると思います。

私は現在、検証済みの crontab 形式でスケジュール情報を受け入れる Resque-scheduler for Rails で次のコードを使用して、手動実行のみのテスト ジョブを作成しています。

cron: "0 5 31 2 *"

ジョブは、実行する前に2 月 31 日の早朝まで辛抱強く待ちます。Quartz crontriggerに相当するものについては、次の行またはその変形を試してください。

0 0 5 31 2 ?
于 2012-12-18T17:12:44.660 に答える
2

現在、このアプリケーションを自分のコンピューターでローカルに実行している場合、これらのジョブが実行されることは望ましくありません。トリガーされないcron式を書く方法はありますか?

コンピューターでスケジュールを無効にする場合は、いくつかの方法でそれを実現できます。

最初に、Quartz の構成を に@Profile基づく構成に移動し、このプロファイルをローカルで有効にしないようにすることができます。プロファイルがアクティブでない場合、Quartz はまったく起動しません。

別の方法は、自動的に起動しないように Quartz を構成することです。dev プロファイルSchedulerFactoryBean#setAutoStartup()に登録して設定できる があります。このスレッドはかなり古いものですが、Spring Boot はBean をBeanPostProcessor登録して同じことを行うという代替手段を提供しています。SchedulerFactoryBeanCustomizer

于 2018-08-08T09:42:37.290 に答える