it-swarm.com.de

Zeitzone für Spring @Scheduled bereitstellen?

Wie kann ich die Zeitzone für einen Spring-basierten @Scheduled Cron-Job konfigurieren? 

Hintergrund:

Ich habe einen Job, der einmal am Tag ausgeführt wird, beispielsweise um 2 Uhr nachmittags, mit der @Scheduled-Anmerkung von Spring:

@Scheduled(cron = "0 0 14 * * *")
public void execute() {
    // do scheduled job
}

Das Problem ist, dass sich 2 PM zwischen den verschiedenen Servern unterscheidet, da Spring TimeZone.getDefault()intern verwendet. Darüber hinaus gibt der JavaDoc von TimeZone.getDefault() Folgendes an:

Ruft die Standardzeitzone für diesen Host ab. Die Quelle der Standardzeitzone kann je nach Implementierung variieren.

Mit anderen Worten wird die Zeitzone nicht bestimmt. Dies kann von der JVM-Implementierung, der Konfiguration der Serverzeitzone, dem Serverstandort und/oder anderen unbekannten Faktoren abhängen. Folglich wird der Cron-Job zu unterschiedlichen Zeiten auf verschiedenen Servern ausgelöst, es sei denn, es gibt eine Möglichkeit, explizit festzulegen, welche Zeitzone verwendet werden soll.

Ich benutze Spring 3.2.2.


Update

Mit Spring 4 wurde die Spring Jira-Ausgabe SPR-10456 gelöst. Daher hat die Annotation @Scheduled genau für diesen Zweck ein neues zone -Attribut.

32
matsev

Es stellte sich heraus, dass ich die @Scheduled-Annotation nicht verwenden konnte, aber ich habe eine Problemumgehung implementiert. Im JavaDoc des SchedulingConfigurer wird Folgendes angegeben:

[SchedulingConfigurer wird verwendet] Wird normalerweise zum Festlegen einer bestimmten TaskScheduler-Bean verwendet, die zum Ausführen geplanter Tasks verwendet wird, oder zum programmierten Registrieren geplanter Tasks im Gegensatz zum deklarativen Ansatz der Verwendung der @Scheduled-Annotation.

Als Nächstes habe ich den Cron-Job geändert, um die Runnable-Schnittstelle zu implementieren, und dann meine Konfigurationsdatei aktualisiert, um die SchedulingConfigurer zu implementieren, siehe unten:

@Configuration
@EnableScheduling
@ComponentScan("package.that.contains.the.runnable.job.bean")
public class JobConfiguration implements SchedulingConfigurer {

    private static final String cronExpression = "0 0 14 * * *";
    private static final String timeZone = "CET";

    @Autowired
    private Runnable cronJob;

    @Bean
    CronTrigger cronTrigger() {
        return new CronTrigger(cronExpression, TimeZone.getTimeZone(timeZone));
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addCronTask(new CronTask(job, cronTrigger()));
    }
}

Bitte lesen Sie das JavaDoc des @EnableScheduling für weitere Informationen.


Update

Ab Frühjahr 4 wurde die Spring Jira-Ausgabe SPR-10456 gelöst. Folglich hat die Annotation @Scheduled genau für diesen Zweck ein neues Attribut zone .

23
matsev

In der Annotation @Scheduled gibt es ab Version 4.0 das Element zone.

Sie können eine Zeitzone als Zeichenfolge einfügen, die von Java.util.TimeZone akzeptiert werden kann.

18
Vlasec

Sie können die Zeitzone auch mit dem Tag @Scheduled Im Spring-Boot wie folgt verwenden:

@Scheduled(cron = "0 0 14 * * *" , zone = "GMT+5:00")
public void execute() {
    // do the scheduled job
}
1
Akshay Gupta

Ich bezweifle, dass verschiedene Jobs oder Teile der Anwendung unterschiedliche Zeitzonen verwenden sollen. Angenommen, Sie möchten, dass alles konsistent und DRY ist, konfigurieren Sie das Betriebssystem auf allen Servern so, dass es eine konsistente Zeitzone hat, oder legen Sie die Java-Systemeigenschaft user.timezone für alle Anwendungsserver fest. Die zentrale Verwaltung der Konfiguration (Betriebssystem, Anwendungsserver) und für diesen Puppen- und Küchenchef kann sehr nützlich sein.

0
Stevo Slavić

Ihr Code sollte so aussehen:

@Scheduled(cron = "0 0 14 * * *", zone = "GMT-5")
    public void execute() {
     // do scheduled job
}

"Zone" wird die Zeitzone des gewünschten Landes sein.

Hier ist ein nettes Tutorial über geplante Aufgaben mit Spring:

https://www.baeldung.com/cron-expressions

0
dmarquina