IK.AM

@making's tech note


Spring BootとSpring LoadedでサクサクHot Reloading Java Webアプリ開発 springboot

🗃 {Programming/Java/org/springframework/boot}
🏷 Java 🏷 Spring 🏷 Spring Boot 
🗓 Updated at 2014-06-03T06:02:56Z  🗓 Created at 2014-06-03T06:02:56Z   🌎 English Page

Spring Loadedを使うとSpringアプリでHot Reloadingが可能です!

maven-spring-boot-pluginと組み合わせてサクサクWebアプリ開発方法を紹介します。

雛形プロジェクト作成

とりあえず汎用的にmaven-archetype-quickstartからプロジェクトをつくります。

$ mvn -B archetype:generate -DgroupId=com.example -DartifactId=hajiboot -Dversion=1.0.0-SNAPSHOT -DarchetypeArtifactId=maven-archetype-quickstart
$ cd hajiboot

pom.xmlの修正

以下のようにspring-bootのdependencyとplugin(+spring loaded)の設定を追加します。

(2014/06/03時点での最新の安定版1.0.2.RELEASEだとWindows環境でこの先の作業中に問題が発生したので1.1.0.RC1で説明します。1.1.0.RELEASEがリリースされたら修正します。→2014/06/12 1.1.1.RELEASE版に修正)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.example</groupId>
    <artifactId>hajiboot</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>hajiboot</name>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>springloaded</artifactId>
                        <version>1.2.0.RELEASE</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
 
    <properties>
        <java.version>1.8</java.version>
    </properties>
</project>

spring-boot-starter-testなくてもいいけど、archetypeでTestのゴミが出力されるのでコンパイルエラーにならんように追加しておく。(どうせテストコード書くしね)

Java8入れていない人は1.8のところを1.7に変えておいてください。

App.java修正

アプリケーションのコードをsrc/main/java/com/example/App.javaに書きます。

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@EnableAutoConfiguration
public class App {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

短いですね。

実行!

spring-loadedの制約でMAVEN_OPTS=-noverifyの設定が必要。 (2014/06/12削除: 1.1.0.RELEASEからいらなくなった?)

$ mvn spring-boot:run

動いた! -> http://localhost:8080

image

Hot Reload!

ここからが本番。mvn spring-boot:runを立ち上げっぱなしで、コードを修正しましょう。

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@EnableAutoConfiguration
public class App {

    @RequestMapping("/")
    String home() {
        return "Hello Spring Boot!";
    }

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

文字列を変えました。

コンパイルすると、

2014-06-03 23:35:42.443  INFO 19756 --- [Loader@3db88bb9] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto java.lang.String com.example.App.home()

というログが・・・!(IntelliJ IDEAだと、右クリック→Compile 'App.java'が必要?) IDEがない人はmvn compileでもOK。

ブラウザをリロードすると、

image

更新された!

次に以下のメソッドを追加してみましょう。

@RequestMapping("hello")
String hello(@RequestParam("name") String name) {
    return "Hello " + name + "!";
}

コンパイルすると、

2014-06-04 08:14:40.249  INFO 4036 --- [Loader@58644d46] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/hello],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto java.lang.String com.example.App.hello(java.lang.String)

ロードされました。

http://localhost:8080/hello?name=making にアクセスすると・・・

image

いけました。

Spring Bootと直接関係ない(Spring MVCの話)けど、日本語で出力したいなら

@RequestMapping(value = "hello", produces = "text/plain;charset=utf-8")
String hello(@RequestParam("name") String name) {
    return "こんにちは " + name + "!";
}

でOK。この変更も即反映。

image

Spring Boot + Spring Loadedな開発良さげですね。

(実際のところ、Spring LoadedでどこまでHot Reloadに耐えうるか未検証なので、これから試していきます・・・)


2014-06-05追記

  • 現状、起動中にインジェクション対象フィールドを増やしてもインジェクションされないみたい・・・

ちなみに、このへん含めたSpring Bootの入門書を執筆中です。

2ヶ月くらいで書ききる目標なので、Spring Bootに期待している方は少々お待ちください!


✒️️ Edit  ⏰ History  🗑 Delete