読者です 読者をやめる 読者になる 読者になる

Building a RESTful Web Service


f:id:Naotsugu:20150110034558p:plain

このガイドでは "hello world" RESTful web service を作っていきます。

What you’ll build

以下の GET リクエストで、

http://localhost:8080/greeting

JSON 形式の挨拶を返します。

{"id":1,"content":"Hello, World!"}

name というパラメータつけると

http://localhost:8080/greeting?name=User

名前付きでレスポンスを返します。

{"id":1,"content":"Hello, User!"}

What you’ll need

How to complete this guide

以下から雛形をダウンロードできます

git clone https://github.com/spring-guides/gs-rest-service.git

が、ここではスクラッチで Gradle 使って進めることにします。

Build with Gradle

プロジェクト用のディレクトリを用意して、その中にソースディレクトリ作成します。

mkdir -p src/main/java/hello

build.gradle 作成していきます。

touch build.gradle

内容は以下。

buildscript {
    repositories {
        maven { url "https://repo.spring.io/libs-release" }
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.10.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'gs-rest-service'
    version =  '0.1.0'
}

repositories {
    mavenLocal()
    mavenCentral()
    maven { url "https://repo.spring.io/libs-release" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}

Create a resource representation class

これから作るwebサービスの仕様を考えます。

サービスは /greeting という GET リクエストを受けつけます。これには name パラメータをクエリ文字として受け取ることもできます。 GET リクエストは 以下の json をメッセージボディとして 200 OK レスポンスを返します。

{
    "id": 1,
    "content": "Hello, World!"
}

id フィールドは挨拶のためのユニークな識別子で content は挨拶の文字列となります。 挨拶の表現となるモデルは POJO で、普通のコンストラクタとアクセッサを持ちます。

touch src/main/java/hello/Greeting.java

Greeting クラスは以下のようになります。

package hello;

public class Greeting {

    private final long id;
    private final String content;

    public Greeting(long id, String content) {
        this.id = id;
        this.content = content;
    }

    public long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }
}

後で見ますが、Spring は Greeting クラスを JSON にマーシャリングするために Jackson ライブラリを使います。

ではリソースコントローラの作成に移ります。

Create a resource controller

RESTful web サービス構築のための Spring のアプローチは、HTTP リクエストをコントローラで扱います。 コントローラコンポーネント@RestController アノテーションを付けて GET リクエストにより新しい Greeting クラスのインスタンスを返却します。

touch src/main/java/hello/GreetingController.java

GreetingController は以下のようになります。

package hello;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
        return new Greeting(counter.incrementAndGet(),
                            String.format(template, name));
    }
}

このようにコントローラはとても簡単です。すこし掘り下げて見ていきましょう。

この例ではPUTやPOSTなどを扱っていません。@RequestMapping はデフォルトで全てのHTTPメソッドを受けつけます。 個別に指定したい場合は @RequestMapping(method=GET) のようにします。

@RequestParamname パラメータとして受けたクエリ文字列をgreeting()メソッドの引数値としてバインドします。 リクエストパラメータは任意値なので、defaultValue としてデフォルト値を定義しています。

伝統的な MVC コントローラとRESTful ウェブサービスコントローラの違いは、HTTP レスポンスボディの作られ方です。 MVC コントローラではサーバサイドで HTML をレンダリングするビューテクノロジを利用するのに対して、RESTful ウェブサービスコントローラでは Greeting オブジェクトを単に返却します。このオブジェクトは json として直接 HTTP レスポンスに書き込まれます。

このコードでは Spring 4 の新しい @RestController アノテーションを使っています。これはviewの代わりに全てのメソッドドメインオブジェクトを返却するマークとなります。 @Controller@ResponseBody が同時に定義されることとなります。

Greeting オブジェクトは SpringのHTTPメッセージコンバータにより自動的に json となります。これは Jackson2 がクラスパスにあるため、Spring の MappingJackson2HttpMessageConverterjson 変換として自動的に選択されるためです。

Make the application executable

サービスは伝統的なWARパッケージにすることもできますが、ここでは簡単なスタンドアロンアプリケーションにするアプローチとします。 Javamain() メソッドで実行可能な全部入りの単一 jar ファイルを作ります。この jar には組み込みの Tomcat サーブレットコンテナを HTTP ランタイムとして組み込みます。

アプリケーションクラスを作りましょう。

touch src/main/java/hello/Application.java

Application は以下です。

package hello;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
@EnableAutoConfiguration
public class Application {

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

main() メソッドで SpringApplication ヘルパークラスで Application クラスを指定します。 これにより Spring は、Application からアノテーション定義を読み Spring アプリケーションコンテキストとして管理します。

@ComponentScan アノテーションは Spring にhello パッケージ内の @Component で(直接/間接に)アノテートされたクラスを探すよう指示しています。 これにより @Component の仲間である @RestController でアノテートされた GreetingController を Springが見つけて登録されます。

@EnableAutoConfiguration アノテーションはクラスパスに基づいて合理的なデフォルトの振る舞いを設定します。 例えばアプリケーションが組み込みバージョンの Tomcat (tomcat-embed-core.jar) に依存していれば、あなたに代わって合理的なデフォルト設定が設定されます。 Spring MVC (spring-webmvc.jar) に依存していれば、Spring MVC DispatcherServlet が設定されて登録されます(web.xml は不要です)。 この自動設定の仕組みは柔軟で強力です。

Build an executable JAR

Gradle を使っているなら、アプリケーションの実行は ./gradlew bootRun とするだけです。

実行可能 jar を作成するには以下のようにし、

./gradlew build

jar を実行すればアプリケーションが起動します。

java -jar build/libs/gs-rest-service-0.1.0.jar