it-swarm.com.ru

Предоставить часовой пояс для Spring @Scheduled?

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

Фон:

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

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

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

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

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

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


Обновление

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

32
matsev

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

[SchedulingConfigurer is] Обычно используется для установки конкретного компонента 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 имеет новый атрибут zone именно для этой цели.

23
matsev

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

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

18
Vlasec

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

0
Stevo Slavić