このガイドでは、ハイパーメディアベースの RESTful (英語) フロントエンドを介してリレーショナル JPA データにアクセスするアプリケーションを作成するプロセスについて説明します。
構築するもの
Spring Data REST を使用して、データベースに保存された Person
オブジェクトを作成および取得できる Spring アプリケーションを構築します。Spring Data REST は、Spring HATEOAS と Spring Data JPA の機能を使用し、自動的に組み合わせます。
Spring Data REST は、バックエンドデータストアとして Spring Data Neo4j、Spring Data Gemfire、Spring Data MongoDB もサポートしていますが、これらはこのガイドの一部ではありません。 |
必要なもの
約 15 分
お気に入りのテキストエディターまたは IDE
コードを直接 IDE にインポートすることもできます。
このガイドを完了する方法
ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。
最初から始めるには、Spring Initializr から開始に進みます。
基本をスキップするには、次の手順を実行します。
このガイドのソースリポジトリをダウンロードして解凍するか、Git (英語) を使用してクローンを作成します。
git clone https://github.com/spring-guides/gs-accessing-data-rest.git (英語)
gs-accessing-data-rest/initial
に cdドメインオブジェクトを作成するにジャンプしてください。
完了したときは、gs-accessing-data-rest/complete
のコードに対して結果を確認できます。
Spring Initializr から開始
すべての Spring アプリケーションでは、Spring Initializr (英語) から始める必要があります。Initializr は、アプリケーションに必要なすべての依存関係をすばやく取り込む方法を提供し、多くの設定を行います。この例では、Rest リポジトリ、Spring Data JPA、および H2 の依存関係が必要です。
必要な依存関係を含む Maven ビルドファイルを Spring Initializr (英語) から直接取得できます。次のリストは、Maven を選択したときに作成される pom.xml
ファイルを示しています。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>accessing-data-rest</artifactId> <version>0.0.1-SNAPSHOT</version> <name>accessing-data-rest</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
必要な依存関係を含む Gradle ビルドファイルを Spring Initializr (英語) から直接取得できます。次のリストは、Gradle を選択したときに作成される build.gradle
ファイルを示しています。
plugins { id 'org.springframework.boot' version '2.4.2' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-rest' runtimeOnly 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { useJUnitPlatform() }
ドメインオブジェクトを作成する
次のリスト(src/main/java/com/example/accessingdatarest/Person.java
内)が示すように、新しいドメインオブジェクトを作成して人を表示します。
package com.example.accessingdatarest;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Person
オブジェクトには、名と姓があります。(また、自動生成されるように構成された ID オブジェクトもあるため、それに対処する必要はありません。)
個人リポジトリを作成する
次に、次のリスト(src/main/java/com/example/accessingdatarest/PersonRepository.java
内)が示すように、単純なリポジトリを作成する必要があります。
package com.example.accessingdatarest;
import java.util.List;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(@Param("name") String name);
}
このリポジトリは、Person
オブジェクトに関連するさまざまな操作を実行できるインターフェースです。Spring Data Commons で定義されている PagingAndSortingRepository
(Javadoc) インターフェースを継承することにより、これらの操作を取得します。
実行時に、Spring Data REST はこのインターフェースの実装を自動的に作成します。次に、@RepositoryRestResource (英語) アノテーションを使用して Spring MVC に /people
で RESTful エンドポイントを作成するよう指示します。
@RepositoryRestResource は、リポジトリのエクスポートには必要ありません。/persons のデフォルト値の代わりに /people を使用するなど、エクスポートの詳細を変更するためにのみ使用されます。 |
ここでは、lastName
に基づいて Person
オブジェクトのリストを取得するカスタムクエリも定義しました。このガイドの後半で呼び出す方法を確認できます。
@SpringBootApplication
は、次のすべてを追加する便利なアノテーションです。
@Configuration
: アプリケーションコンテキストの Bean 定義のソースとしてクラスにタグを付けます。@EnableAutoConfiguration
: クラスパス設定、他の Bean、さまざまなプロパティ設定に基づいて Bean の追加を開始するよう Spring Boot に指示します。例:spring-webmvc
がクラスパスにある場合、このアノテーションはアプリケーションに Web アプリケーションとしてフラグを立て、DispatcherServlet
のセットアップなどの主要な動作をアクティブにします。@ComponentScan
: Spring に、com/example
パッケージ内の他のコンポーネント、構成、サービスを探して、コントローラーを検出させるように指示します。
main()
メソッドは、Spring Boot の SpringApplication.run()
メソッドを使用してアプリケーションを起動します。XML が 1 行もないことに気付きましたか? web.xml
ファイルもありません。この Web アプリケーションは 100% 純粋な Java であり、接続機能やインフラストラクチャの構成に対処する必要はありませんでした。
Spring Boot は Spring Data JPA を自動的に起動して、PersonRepository
の具体的な実装を作成し、JPA を使用してバックエンドインメモリデータベースと通信するように構成します。
Spring Data REST は、Spring MVC の上に構築されます。Spring MVC コントローラー、JSON コンバーター、その他の Bean のコレクションを作成して、RESTful フロントエンドを提供します。これらのコンポーネントは、Spring Data JPA バックエンドにリンクします。Spring Boot を使用すると、これはすべて自動構成されます。Spring Data REST の RepositoryRestMvcConfiguration
を見て、その仕組みを調査したい場合。
実行可能 JAR を構築する
コマンドラインから Gradle または Maven を使用してアプリケーションを実行できます。必要なすべての依存関係、クラス、リソースを含む単一の実行可能 JAR ファイルを構築して実行することもできます。実行可能な jar を構築すると、開発ライフサイクル全体、さまざまな環境などで、アプリケーションとしてサービスを簡単に提供、バージョン管理、デプロイできます。
Gradle を使用する場合、./gradlew bootRun
を使用してアプリケーションを実行できます。または、次のように、./gradlew build
を使用して JAR ファイルをビルドしてから、JAR ファイルを実行できます。
Maven を使用する場合、./mvnw spring-boot:run
を使用してアプリケーションを実行できます。または、次のように、./mvnw clean package
で JAR ファイルをビルドしてから、JAR ファイルを実行できます。
ここで説明する手順は、実行可能な JAR を作成します。クラシック WAR ファイルを作成することもできます。 |
ロギング出力が表示されます。サービスは数秒以内に起動して実行されるはずです。
アプリケーションをテストする
アプリケーションが実行されたため、テストできます。任意の REST クライアントを使用できます。以下の例では、*nix ツール curl
を使用しています。
最初に、トップレベルのサービスを見たいです。次の例は、その方法を示しています。
$ curl http://localhost:8080 { "_links" : { "people" : { "href" : "http://localhost:8080/people{?page,size,sort}", "templated" : true } } }
上記の例は、このサーバーが提供するものを最初に垣間見せます。http://localhost:8080/people
には people
リンクがあります。?page
、?size
や ?sort
などのオプションがあります。
Spring Data REST は、JSON 出力に HAL フォーマット (英語) を使用します。柔軟性があり、提供されるデータに隣接するリンクを提供する便利な方法を提供します。 |
次の例は、人物レコードを表示する方法を示しています(現時点ではなし)。
$ curl http://localhost:8080/people { "_embedded" : { "people" : [] }, "_links" : { "self" : { "href" : "http://localhost:8080/people{?page,size,sort}", "templated" : true }, "search" : { "href" : "http://localhost:8080/people/search" } }, "page" : { "size" : 20, "totalElements" : 0, "totalPages" : 0, "number" : 0 } }
現在、要素はないため、ページはありません。新しい Person
を作成する時間です!次のリストは、その方法を示しています。
$ curl -i -H "Content-Type:application/json" -d '{"firstName": "Frodo", "lastName": "Baggins"}' http://localhost:8080/people HTTP/1.1 201 Created Server: Apache-Coyote/1.1 Location: http://localhost:8080/people/1 Content-Length: 0 Date: Wed, 26 Feb 2014 20:26:55 GMT
-i
: ヘッダーを含むレスポンスメッセージを確認できるようにします。新しく作成されたPerson
の URI が表示されます。-H "Content-Type:application/json"
: コンテンツタイプを設定して、ペイロードが JSON オブジェクトを含むことをアプリケーションが認識できるようにします。-d '{"firstName": "Frodo", "lastName": "Baggins"}'
: データが送信されています。Windows を使用している場合、上記のコマンドは WSL (英語) で機能します。WSL をインストールできない場合は、一重引用符を二重引用符に置き換え、既存の二重引用符をエスケープする必要がある場合があります(例:
-d "{\"firstName\": \"Frodo\", \"lastName\": \"Baggins\"}"
)。
POST 操作へのレスポンスに Location ヘッダーが含まれていることに注意してください。これには、新しく作成されたリソースの URI が含まれます。Spring Data REST には 2 つのメソッド(RepositoryRestConfiguration.setReturnBodyOnCreate(…) および setReturnBodyOnUpdate(…) )もあり、作成したリソースの表現をすぐに返すようにフレームワークを構成するために使用できます。RepositoryRestConfiguration.setReturnBodyForPutAndPost(…) は、作成および更新操作の表現レスポンスを有効にするショートカットメソッドです。 |
次の例に示すように、すべての人を照会できます。
$ curl http://localhost:8080/people { "_links" : { "self" : { "href" : "http://localhost:8080/people{?page,size,sort}", "templated" : true }, "search" : { "href" : "http://localhost:8080/people/search" } }, "_embedded" : { "people" : [ { "firstName" : "Frodo", "lastName" : "Baggins", "_links" : { "self" : { "href" : "http://localhost:8080/people/1" } } } ] }, "page" : { "size" : 20, "totalElements" : 1, "totalPages" : 1, "number" : 0 } }
people
オブジェクトには、Frodo
を含むリストが含まれています。self
リンクが含まれていることに注意してください。Spring Data REST はまた、Evo インフレクター (英語) を使用して、グループ化のためにエンティティの名前を複数形にします。
次のように、個々のレコードを直接照会できます。
$ curl http://localhost:8080/people/1 { "firstName" : "Frodo", "lastName" : "Baggins", "_links" : { "self" : { "href" : "http://localhost:8080/people/1" } } }
これは、純粋に Web ベースのように見える場合があります。ただし、バックグラウンドでは、H2 リレーショナルデータベースがあります。本番環境では、おそらく PostgreSQL などの実際のものを使用します。 |
このガイドでは、ドメインオブジェクトは 1 つだけです。ドメインオブジェクトが互いに関連しているより複雑なシステムでは、Spring Data REST は追加のリンクをレンダリングして、接続されたレコードへのナビゲートを支援します。 |
次の例に示すように、すべてのカスタムクエリを見つけることができます。
$ curl http://localhost:8080/people/search { "_links" : { "findByLastName" : { "href" : "http://localhost:8080/people/search/findByLastName{?name}", "templated" : true } } }
HTTP クエリパラメーター name
を含む、クエリの URL を確認できます。これは、インターフェースに埋め込まれた @Param("name")
アノテーションと一致することに注意してください。
次の例は、findByLastName
クエリの使用方法を示しています。
$ curl http://localhost:8080/people/search/findByLastName?name=Baggins { "_embedded" : { "persons" : [ { "firstName" : "Frodo", "lastName" : "Baggins", "_links" : { "self" : { "href" : "http://localhost:8080/people/1" } } } ] } }
コードで List<Person>
を返すように定義しているため、すべての結果が返されます。Person
のみを返すように定義していた場合、Person
オブジェクトの 1 つを選択して返します。これは予測できないため、複数のエントリを返す可能性のあるクエリに対してはそうしたくないでしょう。
PUT
、PATCH
および DELETE
REST 呼び出しを発行して、既存のレコードを(それぞれ)置換、更新、または削除することもできます。次の例では、PUT
呼び出しを使用しています。
$ curl -X PUT -H "Content-Type:application/json" -d '{"firstName": "Bilbo", "lastName": "Baggins"}' http://localhost:8080/people/1 $ curl http://localhost:8080/people/1 { "firstName" : "Bilbo", "lastName" : "Baggins", "_links" : { "self" : { "href" : "http://localhost:8080/people/1" } } }
次の例では、PATCH
呼び出しを使用しています。
$ curl -X PATCH -H "Content-Type:application/json" -d '{"firstName": "Bilbo Jr."}' http://localhost:8080/people/1 $ curl http://localhost:8080/people/1 { "firstName" : "Bilbo Jr.", "lastName" : "Baggins", "_links" : { "self" : { "href" : "http://localhost:8080/people/1" } } }
PUT はレコード全体を置き換えます。指定されていないフィールドは null に置き換えられます。PATCH を使用して、アイテムのサブセットを更新できます。 |
次の例に示すように、レコードを削除することもできます。
$ curl -X DELETE http://localhost:8080/people/1 $ curl http://localhost:8080/people { "_links" : { "self" : { "href" : "http://localhost:8080/people{?page,size,sort}", "templated" : true }, "search" : { "href" : "http://localhost:8080/people/search" } }, "page" : { "size" : 20, "totalElements" : 0, "totalPages" : 0, "number" : 0 } }
このハイパーメディア駆動型インターフェースの便利な側面は、curl(または任意の REST クライアント)を使用して、すべての RESTful エンドポイントを検出できることです。正式な契約書やインターフェースドキュメントを顧客と交換する必要はありません。
要約
おめでとう!ハイパーメディアベースの RESTful フロントエンドと JPA ベースのバックエンドを備えたアプリケーションを開発しました。
関連事項
次のガイドも役立ちます。
新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください: GitHub (英語) 。
すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の Attribution、NoDerivatives クリエイティブコモンズライセンス (英語) でリリースされています。 |