REST API コントローラーの作成 - @RestController

JSON を応答するコントローラーには、@RestController、および @RequestMapping を使用します。要求に応じて、データを保存したり、モデルを JSON レイアウトで応答したりする、api/v1/memo というエンドポイントを、以下を参考に作成します。

// src/main/java/io/github/yo1000/sss/controller/api/v1/MemoResource.java
package io.github.yo1000.sss.controller.api.v1;

import io.github.yo1000.sss.aspect.ExceptionControllerAdvice;
import io.github.yo1000.sss.model.Memo;
import io.github.yo1000.sss.service.MemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("api/v1/memo")
public class MemoResource {
    private MemoService memoService;

    @Autowired
    public MemoResource(MemoService memoService) {
        this.memoService = memoService;
    }

    @RequestMapping("")
    public List<Memo> get() {
        return getMemoService().readAll();
    }

    @RequestMapping("{author}")
    public List<Memo> get(@PathVariable String author) {
        return getMemoService().readByAuthor(author);
    }

    @RequestMapping("param/{memo:[a-zA-Z0-9]+}")
    public List<Memo> getParams(@PathVariable String memo,
                            @RequestParam(required = false, defaultValue = "Default Author") String author) {
        List<Memo> items = new ArrayList<>();
        items.add(getMemoService().join(memo, author));

        return items;
    }

    @RequestMapping(value = "", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    public List<Memo> post(@RequestBody Memo item) {
        getMemoService().write(item.getMemo(), item.getAuthor());
        List<Memo> items = new ArrayList<>();
        items.add(item);

        return items;
    }

    @RequestMapping("error")
    public List<Memo> getError() {
        throw new ExceptionControllerAdvice.MemoException();
    }

    public MemoService getMemoService() {
        return memoService;
    }
}

基本的には、前章で作成した MemoController と同じ機能を持ったエンドポイント群になります。大きく変わったのは、以下の3点です。

  • クラスアノテーションを、@RestController に変更
  • 返却値を、ビューテンプレート名から、モデルに変更
  • POST メソッドのパラメーターアノテーションを、@ModelAttribute から、@RequestBody に変更

基本的に変更点はこれだけで、主だった使用感は通常のコントローラーと変わりありません。ですが、これだけで、API 用エンドポイントに変化しているのです。

アプリケーションを再起動して、それぞれのエンドポイントを要求してみます。

$ curl -v -X GET http://localhost:8080/api/v1/memo
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /api/v1/memo HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 25 May 2016 06:49:18 GMT
<
* Connection #0 to host localhost left intact
[{"memo":"ドキュメント書く","author":"銀次郎","created":"2016-05-25"},{"memo":"リファクタリングする","author":"銀次郎","created":"2016-05-25"},{"memo":"Springを学ぶ","author":"金次郎","created":"2016-05-23"},{"memo":"Thymeleafを学ぶ","author":"金次郎","created":"2016-05-23"},{"memo":"Flywayを学ぶ","author":"金次郎","created":"2016-05-23"},{"memo":"AspectJを生麩","author":"金字塔","created":"2016-05-23"}]

$ curl -v -X GET http://localhost:8080/api/v1/memo/銀次郎
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /api/v1/memo/銀次郎 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 25 May 2016 06:51:46 GMT
<
* Connection #0 to host localhost left intact
[{"memo":"ドキュメント書く","author":"銀次郎","created":"2016-05-25"},{"memo":"リファクタリングする","author":"銀次郎","created":"2016-05-25"}]

$ curl -v -H "Content-type: application/json;charset=UTF-8" \
-X POST -d '{"memo":"REST対応する", "author":"銀河万丈"}' \
http://localhost:8080/api/v1/memo
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> POST /api/v1/memo HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
> Content-type: application/json;charset=UTF-8
> Content-Length: 52
>
* upload completely sent off: 52 out of 52 bytes
< HTTP/1.1 201 Created
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 25 May 2016 06:57:36 GMT
<
* Connection #0 to host localhost left intact
[{"memo":"REST対応する","author":"銀河万丈","created":null}]

それぞれ 200 OK が応答され、正しく処理されたことが確認できました。

アノテーション

今回、新たに登場したアノテーションを簡単に説明しておきます。

@RestController

REST コントローラーに設定します。このアノテーションが設定されると、クラスが DI コンテナへの登録対象としてマークされます。

このアノテーションは、クラスに @Controller@ResponseBody を一緒に設定するのと同義です。

@RequestBody

リクエストボディに設定された文字列を、そのままパラメーターとして解釈して、モデルや、マップに割り当てます。

サンプル

ここまでのコードサンプルは、以下より入手できます。

$ git clone -b appendix/1 https://github.com/yo1000/self-study-spring.git

results matching ""

    No results matching ""