9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Spring JPA Data with REST と Lombokで恐ろしく簡単にREST APIを作成する。

Last updated at Posted at 2017-12-08

#昨今のWebアプリケーションといえばREST
昨今、Webアプリケーションといえば、HTML+JavaScriptによるクライアント層ブラウザ上で動作し、サーバはREST APIでデータを配信するアーキテクチャを取ります。
本記事ではサーバのREST APIをJavaで恐ろしく簡単に作れるぞ、ということをご紹介します。

#Spring Boot + Lombok
Spring Boot を使うと、簡単にWebアプリケーションを作成することができます。
また、Lombokを使うと、冗長なコードをJavaから排除することができます。
今回は、この2つを組み合わせることで、恐ろしく簡単にREST APIを作成します。
サンプルとして、TODOをRESTできるAPIを作成します。

#手順

  1. SPRING INITIALIZR でアプリケーションのベースを作成する。
    image.png
    Selected Dependenciesには、
    JPA, H2, Lombok, Rest Repositories
    を指定します。
    Generate Projectを押すとzipファイルがダウンロードできるので、解凍します。

  2. データ定義とアプリケーションの作成
    データ構造を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を使いこなしてください。

サンプルコードはこちらにおいておきます。

現場からは以上です。

9
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?