Spring Boot 2 で、なるべく標準的なやり方で、トラディショナルな Spring MVC による Web Application を作成するチュートリアルを数回に分けて。
の5回目です。
目次
- Spring MVC で Hello World
- Spring Data JPA でデータベースアクセス
- 登録・更新処理と Bean Validataion
- Bootstrap と Thymeleaf でページネーション
- Spring Boot DevTools で Automatic Restart
- Spring Security でログイン認証
- ファイルアップロード
- T.B.D
今回は 「Spring Boot DevTools で Automatic Restart」の回となります。
Spring Boot DevTools
spring-boot-devtools を使うと Automatic Restart と LiveReload が実現できます。
Automatic Restart はクラスの変更を検知してアプリケーションの再起動を自動的行うものです。
LiveReload はファイルの変更を自動で検知してブラウザのリロードを自動でおこなうものです。
いずれも開発時の時間短縮に効果を発揮します。
spring-boot-devtools の導入
導入は build.gradle に以下の依存を追加するだけです。
dependencies {
// ・・・
compile 'org.springframework.boot:spring-boot-devtools'
}
Automatic Restart はクラスパス上のファイル変更を検知して自動的にアプリケーションを再起動させることができます。
Automatic Restart は2つのクラスローダを使ってい実現されており、再読込が不要なサードパーティーJar などを読み込むベースクラスローダと、開発しているアプリケーションを読み込むリスタートクラスローダがそれです。アプリケーションの再起動は、ベースクラスローダはそのままに、リスタートクラスローダを破棄して再作成することで実現されます(Spring-Loaded は javaagent を利用してバイトコードを動的に書き換えることで変更を反映しておりアプローチが違う)。
LiveReload はフロントエンド開発でよくあるのと同じで、ファイルの変更を検知してブラウザのリロードを自動的に行うものです。
組み込みの LiveReload サーバが起動し、ブラウザのエクステンションと通信することでページのリロードが自動で行われます。
Automatic Restart の実行
といっても、普通に bootRun すれば使えます。
IDE に依存しないやり方はターミナルを2つ使います。
- 一つのターミナルで
./gradlew bootRunでアプリケーションを起動する - もう一つのターミナルで
./gradlew classesで変更内容をコンパイルする
Gradle の classes は compileJava と processResources に依存するのでクラスファイルとリソースファイルが変更され、この変更が自動で検知され、アプリケーションの再起動が自動的に行われるようになります。
Automatic Restart の設定
Thymeleaf はデフォルトでテンプレートのコンパイル結果をキャッシュします。
これを変更するには application.properties または application.yml でキャッシュ設定を Off にする必要があります。
これは例えば、src/main/resources/config/application.yml に以下のように設定します(環境別の設定切り替えは連載の後半で説明します)。
spring.thymeleaf.cache: false
しかし、 spring-boot-devtools モジュールは、これらのプロパティを開発時設定に自動的適用します。なので、 processResources でリソースがコピーされただけでテンプレートの変更点が反映されるようになります。
これは Groovy テンプレートの spring.groovy.template.cache であったりVelocityテンプレートの spring.velocity.cache であったりも同様です。
spring-boot-devtools はデフォルトで次のリソースは再起動のトリガ対象から除外されています。
/META-INF/maven, /META-INF/resources, /resources, /static, /public, /templates
つまり、Thymeleaf のテンプレートを変更し、./gradlew processResources しても再起動は行われません。が、前述のキャッシュがoffとなっているため変更内容は反映されます。
この除外対象を変更するには、application.properties または application.yml で spring.devtools.restart.exclude(デフォルトの上書き) や spring.devtools.restart.additional-exclude(デフォルトへの追加) を設定します。
その他は以下のような設定があります。
spring: devtools: restart: enabled: true # 再起動の有効/無効 exclude: "static/**, public/**" # 除外パターン additional-exclude: "**/*.xml" # 追加の除外パターン additional-paths: ['src/main/resources/sql'] # 監視パスを配列で指定 trigger-file: .reload # 再起動のトリガファイルを指定
IntelliJ IDEA で Automatic Restart
bootRun ではなく、IDEA からmainメソッドを実行した場合、リスタートの監視対象は out/production/classes/ となります(bootRun の場合は build/classes/java/main/ build/resources/main/ )。
これは起動時のログを見るとわかります。
org.springframework.boot.devtools.restart.ChangeableUrls - Matching URLs for reloading : [file:/・・・/spring-boot-stdweb/out/production/classes/]
IDEA のデフォルト設定では、ソース編集内容は自動的に保存されます。そしてそのタイミングでビルドは行われません。よって、main メソッドから起動時には 「Build」-「Build Project」を行ったタイミングでリスタートが行われます。
なので、Eclipse のようにファイル保存を ⌘ F9 (Build Project) と読み替えると良いです。
どうしてもファイル保存時にリスタートしたいという場合は、
Preferences…-build,execution,deployment-compiler-build project automaticallyにチェックCtrl+SHIFT+A->Registry-compiler.automake.allow.when.app.runningにチェック
とすることで自動ビルドが有効になりますが、先に述べたように編集内容は自動的に保存されてしまい、意図しないタイミングでリスタートが走るためあまりオススメできません。普通に Build Project (⌘ F9) した方がよいです。
やるのであれば、File - Save All、Build - Build Project をマクロ登録してお好みのキーバインドに割り当てる方が良いですね。
IntelliJ IDEA と Gradle プロジェクト
IDEA で Gradle プロジェクトを開くには、File - New - Project from Existing Sources…から build.gradle を開いてやればよいです。
この場合、Build Project (⌘ F9) した結果は ./out ディレクトリ以下にコンパイル結果が保存されます。
これを Gradle と同じ出力先 build 以下に変えるには idea プラグインを使います。
plugins {
id 'java'
id 'idea'
id 'org.springframework.boot' version '2.0.1.RELEASE'
}
・・・
idea{
module{
inheritOutputDirs = false
outputDir = compileJava.destinationDir
testOutputDir = compileTestJava.destinationDir
}
}
idea プラグインを入れた後、以下のようにすれば、
$ ./gradlew idea ... Generated IDEA project at file:///・・・/spring-boot-stdweb/spring-boot-stdweb.ipr
ipr ファイルが作成されます。
この ipr ファイル からIDEA でプロジェクトを開くとビルドの出力先が build 以下になり、main メソッドから実行した場合も、bootRun した場合と同様に build/classes/java/main/ build/resources/main/ になります。
こうすることで、ターミナルからbootRun して、IDEA からビルドした結果でアプリケーションのリスタートを行うことができるようになります。
個人的には idea プラグインは入れず、ターミナルで bootRun しつつ、IDEA から Gradle の classes タスクを実行するやり方の方がいいと思います。
LiveReload
LiveReload を行うには spring-boot-devtools の導入の他にブラウザにアドオンを入れる必要があります。
Firefox Add-ons
https://addons.mozilla.org/ja/firefox/addon/livereload-web-extension/
Chrome ウェブストア
https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei?hl=ja
アドオンを入れると、以下のように LiveReload ボタンが現れるので、ボタンを押して有効化すれば準備完了です(緑色のアイコンです)。

テンプレート変更して
$ ./gradlew processResources
とすれば自動的にブラウザのリロードが行われるようになります。
簡単ですね。
今回はここまでで、次回に続きます。