SpringBootでホットデプロイを行う2つの方法

エキサイト株式会社でメディア事業でエンジニアをしている佐々木です。
2020/12/19のXTechGroupのアドベントカレンダー担当させていただきます。今回は、SpringBootの`初歩の初歩`になります。


#  はじめに
弊社のメディア開発では、PHPで開発するのがメインの会社でしたが、私が入社してからSpring/Java等のトライアルで導入を進めております。PHPからJavaに変更するにあたり、静的型付言語でもサクサク開発できるように2つの方法を説明していきます。

## SpringBoot + SpringBoot devtools

SpringBootには元々開発用のdevtoolsモジュールが提供されています。これを使用すると開発時に、 `Hot Restart` と `Live Reload` の機能が提供されます。


## (前提)SpringBootの最初の設定
※　もうプロジェクトがある人は読み飛ばしてください
ここ(`https://start.spring.io/`)にアクセスして、左側`Project`や`Language`を設定し、右側の`Dependencies`で `Spring Web` を選択し、下にある `Generate` ってボタンをクリックし、zipファイルをダウンロードし、展開して、`IntelliJ` で開きます。 これで準備完了です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/0a7d951f-acec-ed0f-c920-45dd92806e61.png)

下記のようなディレクトリ構成になっているかと思います。

```shell:ディレクトリ構成
├── HELP.md
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── demo
    │   │               ├── DemoApplication.java
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
    └── test
        └── java
            └── com
                └── example
                    └── demo
                        └── DemoApplicationTests.java
```

## 1. Spring Devtoolsを使ってホットデプロイする

### 1.1. 依存関係を追加

下記の設定をします。GradleとMaven両方記載しておきます。

```groovy:Gradleの場合
Gradleの設定

dependencies {
   ..
   developmentOnly 'org.springframework.boot:spring-boot-devtools' // これを追加
   ..
}
```


```xml:Mavenの場合
Mavenの設定

<dependencies>
   ..
    <!-- ここから -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <scope>runtime</scope>
      <optional>true</optional>
    </dependency>
    <!-- ここまでを追加 -->
   ..
</dependencies>
```

### 1.2. SpringBootの設定を追加

`resources/application.properties` or `resources/application.yml` のファイルに設定を追加。(デバッグモードではデフォルトで動作するので、記述は不要ですが一応)

```properties:application.propertiesの場合
application.propertiesの設定

## 下記2行を追加
spring.devtools.remote.restart.enabled=true
spring.devtools.livereload.enabled=true

```


```yml:application.ymlの場合
application.ymlの設定

## 下記を追加
spring:
  devtools:
    livereload:
      enabled: true
    restart:
      enabled: true
```

### 1.3. SampleControllerを作成
HTTPを受けるSampleControllerを作成します。

下記のファイルを作成し、中身を書きます。

```java:java/com/example/demo/SampleController.java
package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping
public class SampleController {

    @GetMapping
    public String index(){
        return "Hello, Java";
    }
}
```

### 1.4. SpringBootの起動
SpringBootを起動します

java/com/example/demo/DemoApplication.java のファイルの下記の画像のように赤い枠の緑のボタンをクリックして、 `デバッグ` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/21d6c336-5be5-201d-430c-4d22c900fd0b.png)

### 1.5. ブラウザで動作確認
http://localhost:8080/ を叩くと Hello , Spring が応答されるかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/84807b71-360c-cea0-1940-4532d497b8df.png)

### 1.6. ソースコード変更

Controllerのソースを変更してみましょう。

```java:java/com/example/demo/SampleController.java
package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping
public class SampleController {

    @GetMapping
    public String index(){
        return "Hello, Spring";  // Springに変更
    }
}

```

変更したら、 Macの方は cmd + F9 , Windowsの方は Ctrl + F9 を押してください。
ビルドが始まり、正常に完了すると、 SpringBootが HotRestartをしてくれます。


![ezgif-3-b933d4c2707a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/5385bfe7-2701-10fc-1ea3-cbbcc0191ea4.gif)
Compileが完了すると自動的に再起動してくれます

ブラウザで確認すると、`Hello Spring` になっています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/1b5fbeac-96c5-e1c6-4522-e27b410d6282.png)

この`Hot Restart` は再起動を手動でやるより高速です。体感では、30%〜50%くらい短くなるとおもいます。

### 1.7. ブラウザを自動で更新する `live reload` の設定
サーバが再起動する度にブラウザの更新ボタンを押すのは面倒です。 `live reload` と連携できるので、これを利用します。

1. ブラウザ拡張をインストールします。
  Chrome: https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei
  Firefox: https://addons.mozilla.org/en-US/firefox/addon/livereload/

2. ブラウザで先程の `http://localhost:8080` を開いて拡張を有効にします。

拡張のボタンをクリックして、画像のような状態にしてください。(※SpringBootが起動しているときしかできません)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/fb9be73c-b85c-82a5-405f-f90032f61cdc.png)

3. ソースコードを書き換えて、buildを走らせてみる

準備ができたら、ソースコードを書き換えて、 buildしてみましょう。 `Hot restart` が完了したタイミングで、ブラウザもリロードされます。

![ezgif-3-d8a0addb1a12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/7ec6b34e-3f1e-27e9-d7df-453636f565a4.gif)

`<h2>Hello, Java</h2>` にコードを書き換えてビルドすると、 `Hot restart` が完了したタイミングで、ブラウザがリロードされています。

SpringBoot devtools を使った Hot deployは以上になります。

## 2. DECVMによるホットデプロイ
SpringBoot devtools で`Hot Restart` もいいのですが、再起動をしなくてもコードを反映したかったりすることはあると思います。

DCEVMはここで下記にあります。
http://dcevm.github.io/

JDK8とJDK11でインストール方法が異なるのですが、今回は、JDK11を使うこととします。

### 2.1 DCEVMのダウンロードとインストール

[DCEVM:gihub](https://github.com/TravaOpenJDK/trava-jdk-11-dcevm/releases)こちらから、JDKをダウンロードして解凍します。

### 2.2 IntelliJでDCEVMを設定する

1. File -> Project Structure -> Platform Settings -> SDKs の `+` をクリックし、 `ADD JDK` にて、先程の解凍したディレクトリを指定します。

2. File -> Project Structure -> Project Settings -> Project の `Project SDK` を先程追加したJDKを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/a617652b-57ca-4eec-c5e5-a57823f7446b.png)

3. SpringBootの設定を変更する

```properties:application.properties
## ここを変更
spring.devtools.remote.restart.enabled=false

```


```yml:application.ymlの場合
application.ymlの設定

## 下記を変更
spring:
  devtools:
    restart:
      enabled: false
```

4. SpringBootを再起動して設定完了

### 2.2 コード変更する

では先程のコードを変更してみましょう。

![ezgif-4-1e0274b96d25.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/894051/2f57b6da-a777-e857-78c6-c3c7670cb58f.gif)

`<h2>Hello, Java</h2>`を`Hello, Java`に戻して、ブラウザ更新を手動で行っています。
DCEVMは、 `Hot Restart`の再起動の待ち時間がないので、その分速いのですが、 `live reload` が動作しません。

以上で、DCEVMを使った`Hot deploy`は以上になります。

# 最後に
PHPからJavaでWeb開発する際に、よく言われるのがこの再起動問題なので、少しでも軽減できるように紹介しました。本当は、DCEVM + LiveReloadの組み合わせが一番効率的かなと思いますが、現状`live reload`が動かないので、動かせるように試行錯誤を続けます。


エキサイト株式会社では、自社サービス開発ができるまたはやりたいエンジニアを広く募集しております。
連絡は下記からお願いいたします！

https://www.wantedly.com/companies/excite/projects