Укажите часовой пояс для 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