Ich weiß, dass es hier ein Duplikat gibt , was wahrscheinlich genau mein Fall ist, obwohl es eine bessere Erklärung verdient, die ich hier zu liefern versuchen werde.
Ich arbeite mit einer Java-Webanwendung unter Verwendung eines Spring-Anwendungskontexts. In diesem Zusammenhang habe ich geplante Jobs mit Quartz definiert. Diese Jobs werden von einem Cron ausgelöst, der in einer .properties-Datei definiert ist.
Der Spring-Kontext ist in den Krieg eingebettet, während sich die .properties-Datei auf dem Anwendungsserver befindet (in diesem speziellen Fall Tomcat).
Dies ist in Ordnung und ermöglicht die Definition verschiedener Crones je nach Umgebung (Entwicklung, Integration, Produktion, ...).
Wenn ich diese Anwendung jetzt lokal auf meinem eigenen Computer ausführe, möchte ich nicht, dass diese Jobs ausgeführt werden. Gibt es eine Möglichkeit, einen Cron-Ausdruck zu schreiben, der niemals ausgelöst wird?
quelle
#
Kommentarzeichen zu beginnen .<property name="cronExpression" value="<expression>" />
Sie können den Job nicht deaktivieren, indem Sie die Zeile kommentieren. Trotzdem danke. Ich werde den vorgeschlagenen Weg verwenden, um ein Jahr anzugeben, das bisher in zukünftigen Computern, wie wir sie kennen, verschwunden sein wird.Antworten:
TL; DR
In Quarz 1 können Sie diesen Cron verwenden:
59 59 23 31 12 ? 2099
(letztes gültiges Datum).In Quartz 2 können Sie diesen Cron verwenden:
0 0 0 1 1 ? 2200
Verwenden Sie einen Ausdruck weit in der Zukunft
Habe einige schnelle Tests mit gemacht
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())); }
Wenn ich das tue
String exp = "# 0 0 0 1 1 ?";
,isValid
kehrt der Test zurückfalse
.Mit dem oben angegebenen Beispiel ist die Ausgabe wie folgt:
true null
Bedeutung:
Damit der Scheduler einen Cron-Trigger akzeptieren kann, muss dieser jedoch mit einem zukünftigen Datum übereinstimmen.
Ich habe es mehrere Jahre lang versucht und herausgefunden, dass Quarz, sobald das Jahr über 2300 liegt, nicht mehr zu stören scheint (obwohl ich keine Erwähnung eines Maximalwerts für das Jahr gefunden habe in der Dokumentation von Quarz 2 ). Es könnte einen saubereren Weg geben, dies zu tun, aber dies wird meine Bedürfnisse vorerst befriedigen.
Am Ende ist also der Cron, den ich vorschlage
0 0 0 1 1 ? 2200
.Variante Quarz 1
Beachten Sie, dass in Quarz 1 2099 das letzte gültige Jahr ist . Sie können daher Ihren Cron-Ausdruck anpassen, um den Vorschlag von Maciej Matys zu verwenden :
59 59 23 31 12 ? 2099
Alternative: Verwenden eines Datums in der Vergangenheit
Arnaud Denoyelle schlug etwas Eleganteres vor, was mein Test oben als korrekten Ausdruck bestätigt: Anstatt ein Datum in ferner Zukunft zu wählen, wählen Sie es in einer fernen Vergangenheit:
0 0 0 1 1 ? 1970
(der erste gültige Ausdruck gemäß Quarzdokumentation).Diese Lösung funktioniert jedoch nicht.
Hippofluff betonte, dass Quarz einen Ausdruck in der Vergangenheit erkennt , nie wieder ausgeführt wird und daher eine Ausnahme auslöst .
org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire.
Dies scheint schon lange in Quarz zu sein .
Lektionen gelernt: Der Test ist nicht so narrensicher wie er ist
Dies unterstreicht eine Schwäche meines Tests: Wenn Sie a testen möchten
CronExpression
, denken SienextValidTime
daran, dass es eine 1 haben muss . Andernfalls lehnt der Scheduler, an den Sie es übergeben, es einfach mit der oben genannten Ausnahme ab.Ich würde empfehlen, den Testcode wie folgt anzupassen:
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."));
Los geht's: Sie müssen nicht nachdenken, lesen Sie einfach die Ausgabe.
1 Dies ist der Teil, den ich vergessen habe, als ich Arnauds Lösung getestet habe, um mich zum Narren zu machen und zu beweisen, dass mein Test nicht für mich geeignet war.
quelle
0 0 0 1 1 ? 1970
? Würde Quarz es ablehnen?Technisch gesehen sind gültige Werte für das optionale Quarzjahresfeld 1970-2099, sodass 2300 kein erwarteter Wert ist. Ich nehme dich wirklich an tun müssen und Ihre Version von Quartz versucht, eine gültige Cron-Syntax durchzusetzen (Tag 1-31, Monat 1-12 usw.).
Ich verwende derzeit den folgenden Code im Resque-Scheduler für Rails, der Zeitplaninformationen im validierten Crontab-Format akzeptiert, um einen Testjob zu erstellen, der nur manuell ausgeführt werden kann:
cron: "0 5 31 2 *"
Der Job wartet geduldig auf den frühen Morgen des 31. Februar, bevor er ausgeführt wird. Versuchen Sie für ein Äquivalent in Quarz-Crontrigger diese Linie oder eine Variante davon:
quelle
.startAt(startTime)
den Auslöser verwenden, um zu glauben, dass er vor langer Zeit gestartet wurde, und ihn dann anweisen, nur auf ein bestimmtes Jahr zu feuern, das bereits vergangen ist. Das ist aber nicht ganz so elegant.0 5 31 2 *
scheint in Magento Cron gut zu funktionieren.Invalid cron expression "0 0 5 31 2 ?" led to runaway search for next trigger
Probieren Sie es aus:
59 59 23 31 12 ? 2099
quelle
0 0 0 1 1 ? 2200
? Meins würde an 2200 Ney Year's Eve ausgelöst werden, während deins erst hundert Jahre vorher sein wird, so wie ich es verstehe. Irre ich mich Wenn nicht, denke ich, je weiter es in Zukunft ist, desto besser, stimmst du nicht zu?0 0 0 1 1 ? 2200
mit der neuesten Version von Quartz. Es wurde jedoch eine intelligentere Lösung vorgeschlagen (siehe die Bearbeitung in meiner eigenen Antwort).Ich fand dies, als ich versuchte, ein ähnliches Problem zu lösen - das Deaktivieren eines Cron-Ausdrucks -, stieß jedoch auf die gleichen Probleme, ein gültiges zukünftiges Planungsdatum zu benötigen.
Ich habe auch Probleme mit der 7-Wert-Syntax - kann kein Jahr im Cron-Zeitplan angeben.
Also habe ich folgendes benutzt: 0 0 3? 2 MON # 5
Das nächste Mal, wenn dies ausgeführt wird, sind:
Im Grunde genommen ist es also in jeder Hinsicht deaktiviert. :) :)
Ah. Flüche, dies funktioniert nur für die Quarz-Scheduler-Syntax - Die Spring CronTrigger-Syntax erlaubt MON # 5 für den fünften Montag nicht
Das nächstbeste ist also 0 0 3 29 2? die erst am 29. Februar um 3 Uhr morgens ausgeführt wird (Schaltjahre)
quelle
Wenn Sie den Ausdruck in einem
@Scheduled(cron="")
Ausdruck verwenden (technisch gesehen wird kein Quarz verwendet, sondern eher im Frühling verwendet), können Sie nicht die 7-Feld-Lösung für das zukünftige Jahr verwenden, sondern die folgenden Optionen:"${your.cron.prop:-}
die Eigenschaft und setzen Sie sie nicht so, dass die Ausführung deaktiviert wird - siehe @Scheduled . Oder setzen Sie die Eigenschaft selbst auf "-" (stellen Sie sicher, dass Sie Anführungszeichen verwenden, wenn Sie eine yml verwenden).@Scheduled
Methode insgesamt, z. B. indem Sie eine@ConditionalOnProperty("my.scheduleproperty.active")
Anmerkung verwenden und die Eigenschaft nicht festlegen (oder auf festlegenfalse
).quelle
Wenn Sie die Zeitplanung auf Ihrem Computer deaktivieren möchten, haben Sie verschiedene Möglichkeiten, dies zu erreichen.
Zuerst können Sie die Konfiguration von Quartz auf a verschieben
@Profile
basierte Konfiguration verschieben und dieses Profil nicht lokal aktivieren. Quarz würde überhaupt nicht starten, wenn das Profil nicht aktiv ist.Eine Alternative besteht darin, Quartz so zu konfigurieren, dass es nicht automatisch startet. Es gibt eine
SchedulerFactoryBean#setAutoStartup()
, die SieBeanPostProcessor
in einem Entwicklerprofil registrieren können. Während dieser Thread ziemlich alt ist, bietet Spring Boot eine Alternative, indem eineSchedulerFactoryBeanCustomizer
Bean registriert wird , um dasselbe zu tun.quelle
Hallo, Sie können dies versuchen, es wird niemals Ihren Zeitplan ausführen, nur wie
-
in Cron@Scheduled(cron = "${schedular.cron.expression}") schedular.cron.expression=-
quelle