#昨今のWebアプリケーションといえばREST
昨今、Webアプリケーションといえば、HTML+JavaScriptによるクライアント層ブラウザ上で動作し、サーバはREST APIでデータを配信するアーキテクチャを取ります。
本記事ではサーバのREST APIをJavaで恐ろしく簡単に作れるぞ、ということをご紹介します。
#Spring Boot + Lombok
Spring Boot を使うと、簡単にWebアプリケーションを作成することができます。
また、Lombokを使うと、冗長なコードをJavaから排除することができます。
今回は、この2つを組み合わせることで、恐ろしく簡単にREST APIを作成します。
サンプルとして、TODOをRESTできるAPIを作成します。
#手順
-
SPRING INITIALIZR でアプリケーションのベースを作成する。
Selected Dependenciesには、
JPA, H2, Lombok, Rest Repositories
を指定します。
Generate Projectを押すとzipファイルがダウンロードできるので、解凍します。 -
データ定義とアプリケーションの作成
データ構造をJavaのクラスとして作成します。
package com.ukiuni.easyrest.entity;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import lombok.Data;
@Data
@Entity
public class Todo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String title;
private String description;
private boolean done;
@Temporal(TemporalType.TIMESTAMP)
private Date deadline;
}
キモはクラスに付いているアノテーションの@Dataです。Lombokが定義するアノテーションで、アクセサメソッドを自動的に付与してくれます。これによりプログラマは冗長なgetter/setterを記述することなく、フィールドによるデータ定義に集中することができます。
このデータ構造をそのままREST APIのCRUDの型構造にするためのクラスを定義します。
package com.ukiuni.easyrest.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import com.ukiuni.easyrest.entity.Todo;
@RepositoryRestResource(collectionResourceRel = "todos", path = "todos")
public interface TodoRepository extends PagingAndSortingRepository<Todo, Long> {
}
インターフェースを定義するのみです。中身の実装は不要です。
以上でソースコードの記述は終わりです。簡単。
起動と操作
起動します。アプリケーションのディレクトリで
gradle bootRun
で起動します。
操作してみましょう。
curlコマンドを使用します。
$ curl -i http://localhost:8080/todos
HTTP/1.1 200
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 16 Nov 2017 11:47:24 GMT
{
"_embedded" : {
"todos" : [ ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/todos{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/profile/todos"
}
},
"page" : {
"size" : 20,
"totalElements" : 0,
"totalPages" : 0,
"number" : 0
}
}
"todos": [ ] と、空データが取得できているのがわかります。
さて、Todoを一件作成してみます。curlコマンドを利用します。
$ curl -i -X POST -H "Content-Type:application/json" -d "{ \"title\" : \"アドベントカレンダー\", \"description\" : \"記事書かなきゃ。\", \"deadline\":\"2017-12-21T07:00:00.000Z\" }" http://localhost:8080/todos
{
"title" : "アドベントカレンダー",
"description" : "記事書かなきゃ。",
"done" : false,
"deadline" : "2017-12-21T07:00:00.000+0000",
"_links" : {
"self" : {
"href" : "http://localhost:8080/todos/1"
},
"todo" : {
"href" : "http://localhost:8080/todos/1"
}
}
}
1番が作成されたようです。確認してみます。
$ curl -i http://localhost:8080/todos
HTTP/1.1 200
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 16 Nov 2017 11:50:57 GMT
{
"_embedded" : {
"todos" : [ {
"title" : "アドベントカレンダー",
"description" : "記事書かなきゃ。",
"done" : false,
"deadline" : "2017-12-21T07:00:00.000+0000",
"_links" : {
"self" : {
"href" : "http://localhost:8080/todos/1"
},
"todo" : {
"href" : "http://localhost:8080/todos/1"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/todos{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/profile/todos"
}
},
"page" : {
"size" : 20,
"totalElements" : 1,
"totalPages" : 1,
"number" : 0
}
}
作成したものが取得できてますね。
PUTでUPDATEしてみます。
$curl -i -X PUT -H "Content-Type:application/json" -d "{ \"title\" : \"アドベントカレンダー\", \"description\" : \"記事書かなきゃ。頑張ろう。\", \"deadline\":\"2017-12-21T07:00:00.000Z\" }" http://localhost:8080/todos/1
HTTP/1.1 200
Location: http://localhost:8080/todos/1
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 16 Nov 2017 11:43:30 GMT
{
"title" : "アドベントカレンダー",
"description" : "記事書かなきゃ。頑張ろう。",
"done" : false,
"deadline" : "2017-12-21T07:00:00.000+0000",
"_links" : {
"self" : {
"href" : "http://localhost:8080/todos/1"
},
"todo" : {
"href" : "http://localhost:8080/todos/1"
}
}
}
確認してみます。
$ curl -i http://localhost:8080/todos
HTTP/1.1 200
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 16 Nov 2017 11:51:55 GMT
{
"_embedded" : {
"todos" : [ {
"title" : "アドベントカレンダー",
"description" : "記事書かなきゃ。頑張ろう。",
"done" : false,
"deadline" : "2017-12-21T07:00:00.000+0000",
"_links" : {
"self" : {
"href" : "http://localhost:8080/todos/1"
},
"todo" : {
"href" : "http://localhost:8080/todos/1"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/todos{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/profile/todos"
}
},
"page" : {
"size" : 20,
"totalElements" : 1,
"totalPages" : 1,
"number" : 0
}
}
アップデートされてますね。
最後、Deleteします。
$ curl -i -X DELETE http://localhost:8080/todos/1
HTTP/1.1 204
Date: Thu, 16 Nov 2017 11:45:45 GMT
消えたことを確認します。
$ curl -i http://localhost:8080/todos
HTTP/1.1 200
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 16 Nov 2017 11:47:24 GMT
{
"_embedded" : {
"todos" : [ ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/todos{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/profile/todos"
}
},
"page" : {
"size" : 20,
"totalElements" : 0,
"totalPages" : 0,
"number" : 0
}
}
"todos" : [ ] 消えてますね。
どうです?恐ろしく簡単でしょう?
データ構造と公開するためのRepositoryクラスを作成するだけでREST APIを作成することができました。
Javaの型定義の強さとアノテーション機能を使うことでこんなに簡単にREST APIを作成することができます。
どうですか?最近毛嫌いされがちなJavaですが、見直しました?
みなさんもエレガントにJavaを使いこなしてください。
サンプルコードはこちらにおいておきます。
現場からは以上です。