[Spring Boot][Java] アノテーション@Scheduledを使用してタスクを定期実行する
はじめに
日次処理でJarを定期実行する場合にはcronを使ったりしますが、Spring Bootのアノテーション「scheduling」を使用した方法について調べた事を備忘録として書いておきます。
環境
Mac OSX 10.10.5 Yosemite Eclipse Mars2 4.5.2 Java 1.8.0_91
@Scheduledについて
必要な環境
・JDK1.8以上 ・Gradle2.3以上、もしくはMaven3.0以上
使用方法
方法は以下の2つが存在する様です。 ①アノテーションに記述 ②設定ファイル(YAML)を使用
パラメータ
34. Task Execution and Scheduling
句・引数 | 説明 |
---|---|
fixedDelay | メソッドの前回の実行完了時刻から何ミリ秒後に実行するか。 |
fixedRate | メソッドの前回の実行開始時刻から何ミリ秒後に実行するか。 |
initialDelay | メソッドの初回実行時の待機時間。 |
cron | cronを記述してスケジュールを設定。 zoneを使用して時間帯の指定も可能。 |
コード
build.gradle(依存関係)
lombokだけ追加しました。
dependencies { compile('org.springframework.boot:spring-boot-starter') compileOnly('org.projectlombok:lombok') testCompile('org.springframework.boot:spring-boot-starter-test') }
方法①②共通のコード
@EnableSchedulingを追記。
package com.schedule; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling public class SchedulingApplication { public static void main(String[] args) { SpringApplication.run(SchedulingApplication.class, args); } }
方法① アノテーションに記述
スケジュールで実行するクラス: Run
メソッド execute() をアプリケーション起動時に実行し、移行は3秒後ごとに実行する様にしました。 SimpleDateFormat を使用して実行時刻も表示します。
package com.schedule; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class Run { private int i = 0; private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); @Scheduled(initialDelay=0, fixedDelay=3000) public void execute() { System.out.println("実行回数: " + ++i + ", 実行時間: " + sdf.format(new Date())); } }
実行結果
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.4.3.RELEASE) 2017-01-14 17:28:19.725 INFO 26029 --- [ main] com.schedule.SchedulingApplication : Starting SchedulingApplication on HL00094-2 with PID 26029 (/Users/takahara.reo/Documents/workspace_eclipse_spring/Scheduling/bin started by takahara.reo in /Users/takahara.reo/Documents/workspace_eclipse_spring/Scheduling) 2017-01-14 17:28:19.730 INFO 26029 --- [ main] com.schedule.SchedulingApplication : No active profile set, falling back to default profiles: default 2017-01-14 17:28:19.790 INFO 26029 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@149e0f5d: startup date [Sat Jan 14 17:28:19 JST 2017]; root of context hierarchy 2017-01-14 17:28:20.627 INFO 26029 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2017-01-14 17:28:20.636 INFO 26029 --- [ main] s.a.ScheduledAnnotationBeanPostProcessor : No TaskScheduler/ScheduledExecutorService bean found for scheduled processing 実行回数: 1, 実行時間: 17:28:20 2017-01-14 17:28:20.647 INFO 26029 --- [ main] com.schedule.SchedulingApplication : Started SchedulingApplication in 1.373 seconds (JVM running for 2.99) 実行回数: 2, 実行時間: 17:28:23 実行回数: 3, 実行時間: 17:28:26 . . .
方法② 設定ファイル(YAML)を使用
設定ファイル: application.yml
src/main/resources/に配置しました。 アスタリスクの意味は左から、「秒/分/時/日/月/曜日」となっています。 cron1は時刻が0秒で実行。 cron2は時刻が1秒か31秒で実行。
# 秒/分/時/日/月/曜日 cron: cron1: 0 * * * * * cron2: 1,31 * * * * *
設定ファイルを読み込むクラス
package com.schedule; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import lombok.Getter; import lombok.Setter; @Getter @Setter @Component @ConfigurationProperties(prefix="cron") public class CronSetting { private String cron1; private String cron2; }
Setter/GetterはLombokで設定。
スケジュールで実行するクラス: Run
以下に書き換えました。 メソッド execute1() は、cron1を参照するので時刻が0秒で実行。 メソッド execute2() は、cron2を参照するので時刻が1秒か31秒で実行
package com.schedule; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class Run { @Autowired CronSetting cron; private int i1 = 0; private int i2 = 0; private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); @Scheduled(cron="${cron.cron1}") public void execute1() { System.out.println("cron1 実行回数: " + ++i1 + ", 実行時間: " + sdf.format(new Date())); } @Scheduled(cron="${cron.cron2}") public void execute2() { System.out.println("cron2 実行回数: " + ++i2 + ", 実行時間: " + sdf.format(new Date())); } }
①との違いは、 @Autowired で CronSetting を接続している事と、各メソッドの @Scheduled で CronSetting のcronを読み込んでいる事です。
実行結果
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.4.3.RELEASE) 2017-01-14 17:29:14.813 INFO 26032 --- [ main] com.schedule.SchedulingApplication : Starting SchedulingApplication on HL00094-2 with PID 26032 (/Users/takahara.reo/Documents/workspace_eclipse_spring/Scheduling/bin started by takahara.reo in /Users/takahara.reo/Documents/workspace_eclipse_spring/Scheduling) 2017-01-14 17:29:14.816 INFO 26032 --- [ main] com.schedule.SchedulingApplication : No active profile set, falling back to default profiles: default 2017-01-14 17:29:14.904 INFO 26032 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@149e0f5d: startup date [Sat Jan 14 17:29:14 JST 2017]; root of context hierarchy 2017-01-14 17:29:15.960 INFO 26032 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2017-01-14 17:29:15.970 INFO 26032 --- [ main] s.a.ScheduledAnnotationBeanPostProcessor : No TaskScheduler/ScheduledExecutorService bean found for scheduled processing 2017-01-14 17:29:15.987 INFO 26032 --- [ main] com.schedule.SchedulingApplication : Started SchedulingApplication in 1.653 seconds (JVM running for 2.807) cron2 実行回数: 1, 実行時間: 17:29:31 cron1 実行回数: 1, 実行時間: 17:30:00 cron2 実行回数: 2, 実行時間: 17:30:01 cron2 実行回数: 3, 実行時間: 17:30:31 cron1 実行回数: 2, 実行時間: 17:31:00 cron2 実行回数: 4, 実行時間: 17:31:01 cron2 実行回数: 5, 実行時間: 17:31:31 . . .
さいごに
かなり簡単に設定できました。実際に使用する際にアプリケーションがクラッシュした場合を考慮すると、サーバ内でアプリケーションのJarをcronで起動するのが良いとも考えますが、使い方次第でしょうか。