この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
日次処理で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で起動するのが良いとも考えますが、使い方次第でしょうか。