このガイドでは、Spring で「Hello, World」ハイパーメディア駆動型 REST Web サービスを作成するプロセスを順を追って説明します。
ハイパーメディア (英語) は REST の重要な側面です。これにより、クライアントとサーバーを大幅に分離し、独立して進化させるサービスを構築できます。REST リソースに対して返される表現には、データだけでなく、関連リソースへのリンクも含まれます。表現の設計はサービス全体の設計にとって重要です。
構築するもの
Spring HATEOAS でハイパーメディア駆動型 REST サービスを構築します:Spring MVC コントローラーを指すリンクを作成し、リソース表現を構築し、サポートされるハイパーメディア形式(HAL など)にレンダリングする方法を制御するために使用できる API のライブラリ)。
サービスは http://localhost:8080/greeting
で HTTP GET リクエストを受け入れます。
これは、可能な限り単純なハイパーメディア要素、リソース自体を指すリンクで強化された挨拶の JSON 表現で応答します。次のリストに出力を示します。
{
"content":"Hello, World!",
"_links":{
"self":{
"href":"http://localhost:8080/greeting?name=World"
}
}
}
次のリストに示すように、レスポンスはクエリ文字列にオプションの name
パラメーターを使用してグリーティングをカスタマイズできることをすでに示しています。
http://localhost:8080/greeting?name=User
name
パラメーター値は、次のリストに示すように、World
のデフォルト値をオーバーライドし、レスポンスに反映されます。
{
"content":"Hello, User!",
"_links":{
"self":{
"href":"http://localhost:8080/greeting?name=User"
}
}
}
必要なもの
約 15 分
お気に入りのテキストエディターまたは IDE
コードを直接 IDE にインポートすることもできます。
このガイドを完了する方法
ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。
最初から始めるには、Spring Initializr から開始に進みます。
基本をスキップするには、次の手順を実行します。
このガイドのソースリポジトリをダウンロードして解凍するか、Git (英語) を使用してクローンを作成します。
git clone https://github.com/spring-guides/gs-rest-hateoas.git (英語)
gs-rest-hateoas/initial
に cdリソース表現クラスを作成するにジャンプしてください。
完了したときは、gs-rest-hateoas/complete
のコードに対して結果を確認できます。
Spring Initializr から開始
すべての Spring アプリケーションでは、Spring Initializr (英語) から始める必要があります。Initializr は、アプリケーションに必要なすべての依存関係をすばやく取り込む方法を提供し、多くの設定を行います。この例では、Spring HATEOAS 依存関係が必要です。
次のリストは、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.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>rest-hateoas</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rest-hateoas</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
次のリストは、Gradle を選択したときに作成される build.gradle
ファイルを示しています。
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
JSON ライブラリの追加
JSON を使用して情報を送受信するため、JSON ライブラリが必要です。このガイドでは、Jayway JsonPath ライブラリを使用します。
ライブラリを Maven ビルドに含めるには、pom.xml
ファイルに次の依存関係を追加します。
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
次のリストは、完成した 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.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>rest-hateoas</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rest-hateoas</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
ライブラリを Gradle ビルドに含めるには、build.gradle
ファイルに次の依存関係を追加します。
testCompile 'com.jayway.jsonpath:json-path'
次のリストは、完成した build.gradle
ファイルを示しています。
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
リソース表現クラスを作成する
プロジェクトとビルドシステムをセットアップしたため、Web サービスを作成できます。
サービスの相互作用について考えることでプロセスを開始します。
サービスは、/greeting
でリソースを公開し、GET
リクエストを処理します。オプションで、クエリ文字列に name
パラメーターを使用します。GET
リクエストは、挨拶を表すために本文に JSON を含む 200 OK
レスポンスを返す必要があります。
さらに、リソースの JSON 表現は、_links
プロパティのハイパーメディア要素のリストで強化されます。これの最も基本的な形式は、リソース自体を指すリンクです。表現は次のリストのようになります。
{
"content":"Hello, World!",
"_links":{
"self":{
"href":"http://localhost:8080/greeting?name=World"
}
}
}
content
は、挨拶のテキスト表現です。_links
エレメントには、リンクのリストが含まれます(この場合、リレーションタイプが rel
で、アクセスされたリソースを指す href
属性を持つものだけです)。
挨拶表現をモデル化するには、リソース表現クラスを作成します。_links
プロパティはリプレゼンテーションモデルの基本的なプロパティであるため、Spring HATEOAS には、Link
のインスタンスを追加し、それらが前述のようにレンダリングされることを保証する基本クラス(RepresentationModel
と呼ばれます)が付属しています。
次のリスト(src/main/java/com/example/resthateoas/Greeting.java
から)が示すように、RepresentationModel
を継承し、コンテンツのフィールドとアクセッサ、およびコンストラクターを追加するプレーンな古い java オブジェクトを作成します。
package com.example.resthateoas;
import org.springframework.hateoas.RepresentationModel;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Greeting extends RepresentationModel<Greeting> {
private final String content;
@JsonCreator
public Greeting(@JsonProperty("content") String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
@JsonCreator: Jackson がこの POJO のインスタンスを作成する方法を通知します。
@JsonProperty: Jackson がこのコンストラクター引数を配置するフィールドをマークします。
このガイドで後述するように、Spring は Jackson JSON ライブラリを使用して、タイプ Greeting のインスタンスを JSON に自動的にマーシャリングします。 |
次に、これらのグリーティングを提供するリソースコントローラーを作成します。
REST コントローラーを作成する
RESTful Web サービスを構築する Spring のアプローチでは、HTTP リクエストはコントローラーによって処理されます。コンポーネントは、@RestController
(Javadoc) アノテーションによって識別されます。これは、@Controller
(Javadoc) アノテーションと @ResponseBody
(Javadoc) アノテーションを組み合わせたものです。次の GreetingController
(src/main/java/com/example/resthateoas/GreetingController.java
から)は、Greeting
クラスの新しいインスタンスを返すことにより、/greeting
に対する GET
リクエストを処理します。
package com.example.resthateoas;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RestController
public class GreetingController {
private static final String TEMPLATE = "Hello, %s!";
@RequestMapping("/greeting")
public HttpEntity<Greeting> greeting(
@RequestParam(value = "name", defaultValue = "World") String name) {
Greeting greeting = new Greeting(String.format(TEMPLATE, name));
greeting.add(linkTo(methodOn(GreetingController.class).greeting(name)).withSelfRel());
return new ResponseEntity<>(greeting, HttpStatus.OK);
}
}
このコントローラーは簡潔でシンプルですが、多くのことを示しています。段階的に分解していきましょう。
@RequestMapping
アノテーションは、/greeting
への HTTP リクエストが greeting()
メソッドにマップされることを保証します。
上記の例では、GET と PUT 、POST などを指定していません。これは、@RequestMapping がデフォルトですべての HTTP 操作をマップするためです。@GetMapping("/greeting") を使用して、このマッピングを絞り込みます。その場合は、import org.springframework.web.bind.annotation.GetMapping; も使用します。 |
@RequestParam
は、クエリ文字列パラメーター name
の値を greeting()
メソッドの name
パラメーターにバインドします。defaultValue
属性を使用しているため、このクエリ文字列パラメーターは暗黙的に required
ではありません。リクエストにない場合、World
の defaultValue
が使用されます。
@RestController
アノテーションがクラスに存在するため、暗黙的な @ResponseBody
(Javadoc) アノテーションが greeting
メソッドに追加されます。これにより、Spring MVC は返された HttpEntity
とそのペイロード(Greeting
)を直接レスポンスにレンダリングします。
メソッド実装の最も興味深い部分は、コントローラーメソッドを指すリンクを作成する方法と、それを表現モデルに追加する方法です。linkTo(…)
と methodOn(…)
はどちらも ControllerLinkBuilder
の静的メソッドであり、コントローラーでメソッド呼び出しを偽装できます。返された LinkBuilder
は、コントローラーメソッドのマッピングアノテーションをインスペクションして、メソッドがマッピングされる URI を正確に構築します。
Spring HATEOAS は、さまざまな X-FORWARDED- ヘッダーを考慮します。Spring HATEOAS サービスをプロキシの背後に配置し、X-FORWARDED-HOST ヘッダーで適切に構成すると、結果のリンクは適切にフォーマットされます。 |
withSelfRel()
を呼び出すと、Link
インスタンスが作成され、Greeting
表現モデルに追加されます。
@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 であり、接続機能やインフラストラクチャの構成に対処する必要はありませんでした。
実行可能 JAR を構築する
コマンドラインから Gradle または Maven を使用してアプリケーションを実行できます。必要なすべての依存関係、クラス、リソースを含む単一の実行可能 JAR ファイルを構築して実行することもできます。実行可能な jar を構築すると、開発ライフサイクル全体、さまざまな環境などで、アプリケーションとしてサービスを簡単に提供、バージョン管理、デプロイできます。
Gradle を使用する場合、./gradlew bootRun
を使用してアプリケーションを実行できます。または、次のように、./gradlew build
を使用して JAR ファイルをビルドしてから、JAR ファイルを実行できます。
Maven を使用する場合、./mvnw spring-boot:run
を使用してアプリケーションを実行できます。または、次のように、./mvnw clean package
で JAR ファイルをビルドしてから、JAR ファイルを実行できます。
ここで説明する手順は、実行可能な JAR を作成します。クラシック WAR ファイルを作成することもできます。 |
ロギング出力が表示されます。サービスは数秒以内に起動して実行されるはずです。
サービスをテストする
サービスが起動したら、http://localhost:8080/greeting にアクセスして、次のコンテンツを確認します。
{
"content":"Hello, World!",
"_links":{
"self":{
"href":"http://localhost:8080/greeting?name=World"
}
}
}
次の URL にアクセスして、name
クエリ文字列パラメーターを指定します: http://localhost:8080/greeting?name=User
次のリストに示すように、content
属性の値が Hello, World!
から Hello, User!
にどのように変化し、self
リンクの href
属性にもその変化が反映されることに注意してください。
{
"content":"Hello, User!",
"_links":{
"self":{
"href":"http://localhost:8080/greeting?name=User"
}
}
}
この変更は、GreetingController
の @RequestParam
配置が期待どおりに機能することを示しています。name
パラメーターには World
のデフォルト値が指定されていますが、照会ストリングを介して常に明示的にオーバーライドできます。
要約
おめでとう! Spring HATEOAS でハイパーメディア駆動型 RESTful Web サービスを開発しました。
関連事項
次のガイドも役立ちます。
新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください: GitHub (英語) 。
すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の Attribution、NoDerivatives クリエイティブコモンズライセンス (英語) でリリースされています。 |