Spring Boot/第四回 Spring Bootで REST(POST時のLocation設定)

RESTではPOSTでデータを新規作成した時は、そのデータにアクセスするURLをLocationヘッダーで返すのが一般的とのことで、それを試してみる。

新規にデータを登録して、オートインクリメントに設定したプライマリキー「ID」が「5」として登録できたら、以下のURLを返すということ。

api/customer/5

CustomerRestController の postCustomer メソッドを以下のように修正する。

    @RequestMapping(method=RequestMethod.POST)
    public ResponseEntity<Customer> postCustomer(@RequestBody Customer customer,
            UriComponentsBuilder uriBuilder) {    // a
        Customer createdCustomer = service.create(customer);    // b

        // Locationで設定するURLを作成する
        URI location = uriBuilder.path("api/customer/{id}")    // c
                        .buildAndExpand(createdCustomer.getId())    // d
                        .toUri();

        // レスポンスのHTTPヘッダー
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(location);    // e

        // レスポンス情報を作成
        return new ResponseEntity<>(
                createdCustomer, headers, HttpStatus.CREATED);    // f
    }

a -> URI作成用クラスを引数で受け取る。
b -> 顧客情報の登録。
c -> プレースホルダ付の作りたいURLを指定する。
d -> プレースホルダに登録したIDを当てはめる。
e -> HTTPヘッダーにLocationのURLを設定。
f -> HTTPボディに createdCustomer の内容、
   HTTPヘッダーに headers の内容、
   HTTPステータスに CREATED を指定。

ビルドして Spring Boot を起動して curl で以下のように登録をする。

curl http://localhost:8080/api/customer -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"name04\", \"email\":\"name04@test\"}"

実行結果は下記の通り。

# curl http://localhost:8080/api/customer -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"name04\", \"email\":\"name04@test\"}"
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> POST /api/customer HTTP/1.1
> User-Agent: curl/7.41.0
> Host: localhost:8080
> Accept: */*
> Content-Type: application/json
> Content-Length: 40
>
* upload completely sent off: 40 out of 40 bytes
< HTTP/1.1 201 Created
< Server: Apache-Coyote/1.1
< Location: http://localhost:8080/api/customer/4
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Fri, 03 Apr 2015 16:09:41 GMT
<
{"id":4,"name":"name04","email":"name04@test"}* Connection #0 to host localhost left intact

レスポンスヘッダーに今までなかった下記が追加されている。

< Location: http://localhost:8080/api/customer/4

うまく出来たようだ。


ちなみに、プレースホルダを解決する buildAndExpand メソッドには Map を引数に指定もできる。

        // プレースホルダ解決用Map
        Map<String, Integer> map = new HashMap<>();
        map.put("id", createdCustomer.getId());

        // Locationで設定するURLを作成する
        URI location = uriBuilder.path("api/customer/{id}")    // c
//                        .buildAndExpand(createdCustomer.getId())    // d
                        .buildAndExpand(map)    // d
                        .toUri();

プレースホルダの「{id}」を Map のキーにして値を当てはめてくれる。

■ 参考文献 ■

この記事で参考にしたのは「はじめての Spring Boot」です。