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
とすれば自動的にブラウザのリロードが行われるようになります。
簡単ですね。
今回はここまでで、次回に続きます。