Укажите часовой пояс для Spring @Scheduled?

Как настроить часовой пояс для задания на основе Spring на основе Spring?

Задний план:

У меня есть работа, которая выполняется один раз в день, например, 2 часа дня, используя аннотацию Spring @Scheduled:

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

Проблема в том, что 2 PM отличается между разными серверами, потому что Spring использует внутри TimeZone.getDefault() внутренне. Более того, JavaDoc TimeZone.getDefault() утверждает, что:

Получает по умолчанию TimeZone для этого хоста. Источник TimeZone по умолчанию может отличаться в зависимости от реализации.

Другими словами, часовой пояс не определен. Это может зависеть от реализации JVM, конфигурации часового пояса сервера, местоположения сервера и/или других неизвестных факторов. Следовательно, задание cron запускается в разное время на разных серверах, если только не существует способа явно указать, какой часовой пояс должен использоваться?

Я использую Spring 3.2.2.


Обновить

С весны 4 выпущена проблема Spring Jira SPR-10456. Следовательно, аннотация @Scheduled имеет новый атрибут зоны именно для этой цели.

Ответ 1

Оказалось, что я не мог использовать аннотацию @Scheduled, но я реализовал @Scheduled. В JavaDoc SchedulingConfigurer указано, что:

[SchedulingConfigurer is] Обычно используется для установки определенного bean-компонента TaskScheduler, который будет использоваться при выполнении запланированных задач или для регистрации запланированных задач программным способом, в отличие от декларативного подхода с использованием аннотации @Scheduled.

Затем я изменил задание cron для реализации интерфейса Runnable а затем обновил свой файл конфигурации для реализации SchedulingConfigurer, см. Ниже:

@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()));
    }
}

Пожалуйста, прочитайте JavaDoc @EnableScheduling для получения дополнительной информации.


Обновить

По состоянию на весну 4 проблема Spring Jira SPR-10456 была решена. Следовательно, аннотация @Scheduled имеет новый атрибут зоны именно для этой цели, например

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

Ответ 2

В аннотации @Scheduled существует элементная zone, начиная с версии 4.0.

Вы можете вставить часовой пояс в виде строки, которая может быть принята java.util.TimeZone.

Ответ 3

Вы также можете использовать часовой пояс с тегом @Scheduled при весенней загрузке следующим образом:

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

Ответ 4

Я сомневаюсь, что вы хотите, чтобы разные рабочие места или части приложения использовали разные часовые пояса. Предполагая, что вы хотите, чтобы все было согласованным и сухим, либо настройте ОС на всех серверах так, чтобы они соответствовали часовому поясу, либо задали системное свойство user.timezone Java для всех серверов приложений. Централизованное управление конфигурацией (ОС, сервер приложений), а для этой марионетки и шеф-повара может быть очень полезным.

Ответ 5

Ваш код должен быть таким:

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

"Зона" будет желаемым часовым поясом страны.

Вот хороший урок о запланированных задачах с Spring:

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