GraphQLとSpringBootの使用を開始する
1. 序章
GraphQL は、Facebookの比較的新しい概念であり、REST forWebAPIの代替として請求されます。
このチュートリアルでは、Spring Bootを使用してGraphQLサーバーをセットアップし、既存のアプリケーションに追加したり、新しいアプリケーションで使用したりできるようにする方法を学習します。
2. GraphQL とは何ですか?
従来のRESTAPIは、サーバーが管理するリソースの概念で機能します。 これらのリソースは、さまざまなHTTP動詞に従って、いくつかの標準的な方法で操作できます。 これは、APIがリソースの概念に適合している限り非常にうまく機能しますが、それから逸脱する必要がある場合はすぐに崩壊します。
これは、ブログの投稿やコメントのリクエストなど、クライアントが同時に複数のリソースからのデータを必要とする場合にも問題になります。 通常、これは、クライアントに複数の要求を行わせるか、サーバーに常に必要とは限らない追加のデータを提供させて、応答サイズを大きくすることで解決されます。
GraphQLは、これらの問題の両方に対する解決策を提供します。 これにより、クライアントは、単一のリクエストで子リソースをナビゲートするなど、必要なデータを正確に指定でき、単一のリクエストで複数のクエリを実行できます。
また、標準の必須のアクションセットの代わりに、名前付きクエリとミューテーションを使用して、はるかにRPCの方法で機能します。 これは、コントロールを所属する場所に配置するために機能します。API開発者は可能なことを指定し、APIコンシューマーは必要なものを指定します。
たとえば、ブログで次のクエリが許可される場合があります。
query {
recentPosts(count: 10, offset: 0) {
id
title
category
author {
id
name
thumbnail
}
}
}
このクエリは次のようになります。
- 最新の10件の投稿をリクエストする
- 投稿ごとに、ID、タイトル、カテゴリをリクエストします
- 投稿ごとに、作成者をリクエストし、ID、名前、サムネイルを返します
従来のRESTAPIでは、これには11のリクエスト(投稿用に1つ、作成者用に10つ)が必要であるか、投稿の詳細に作成者の詳細を含める必要があります。
2.1. GraphQLスキーマ
GraphQLサーバーは、APIを記述するスキーマを公開します。 このスキームは、タイプ定義で構成されています。 各タイプには1つ以上のフィールドがあり、それぞれが0個以上の引数を取り、特定のタイプを返します。
グラフは、これらのフィールドが互いにネストされている方法から導き出されます。 グラフは非周期的である必要はなく、サイクルは完全に許容可能ですが、方向付けられていることに注意してください。 つまり、クライアントは1つのフィールドからその子に到達できますが、スキーマでこれが明示的に定義されていない限り、自動的に親に戻ることはできません。
ブログのGraphQLスキーマの例には、投稿、投稿の作成者、およびブログの最新の投稿を取得するためのルートクエリを説明する次の定義が含まれている場合があります。
type Post {
id: ID!
title: String!
text: String!
category: String
author: Author!
}
type Author {
id: ID!
name: String!
thumbnail: String
posts: [Post]!
}
# The Root Query for the application
type Query {
recentPosts(count: Int, offset: Int): [Post]!
}
# The Root Mutation for the application
type Mutation {
writePost(title: String!, text: String!, category: String) : Post!
}
「!」 一部の名前の末尾にあるのは、それがnull許容型ではないことを示しています。 これがないタイプは、サーバーからの応答でnullになる可能性があります。 GraphQLサービスはこれらを正しく処理し、null許容型の子フィールドを安全に要求できるようにします。
GraphQLサービスは、標準のフィールドセットを使用してスキーマ自体も公開し、クライアントが事前にスキーマ定義を照会できるようにします。
これにより、クライアントはスキーマが変更されたことを自動的に検出でき、スキーマの動作方法に動的に適応できるようになります。 この非常に便利な例の1つは、GraphiQLツールです。これにより、任意のGraphQLAPIと対話できます。
3. GraphQL SpringBootStarterの紹介
Spring Boot GraphQL Starterは、GraphQLサーバーを非常に短時間で実行するための素晴らしい方法を提供します。 GraphQL Java Tools ライブラリと組み合わせると、サービスに必要なコードを記述するだけで済みます。
3.1. サービスの設定
これが機能するために必要なのは、正しい依存関係だけです。
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
</dependency>
Spring Bootはこれらを自動的に取得し、動作する適切なハンドラーを設定します。
デフォルトでは、これにより、アプリケーションの /graphql エンドポイントでGraphQLサービスが公開され、GraphQLペイロードを含むPOSTリクエストが受け入れられます。 必要に応じて、application.propertiesファイルでこのエンドポイントをカスタマイズできます。
3.2. スキーマの作成
GraphQL Toolsライブラリは、GraphQLスキーマファイルを処理して正しい構造を構築し、この構造に特別なBeanをワイヤリングすることで機能します。 SpringBootGraphQLスターターはこれらのスキーマファイルを自動的に検出します。
これらのファイルは拡張子「。graphqls、」で保存する必要があり、クラスパスのどこにでも存在できます。 これらのファイルは必要な数だけ持つことができるので、必要に応じてスキームをモジュールに分割できます。
1つの要件は、ルートクエリが1つだけで、ルートミューテーションが1つまででなければならないことです。 スキームの他の部分とは異なり、これをファイル間で分割することはできません。 これは、Java実装ではなく、GraphQLスキーマ定義自体の制限です。
3.3. ルートクエリリゾルバ
このルートクエリのさまざまなフィールドを処理するには、ルートクエリにSpringコンテキストで定義された特別なBeanが必要です。 スキーマ定義とは異なり、ルートクエリフィールドにはSpringbeanが1つしかないという制限はありません。
唯一の要件は、Beanが GraphQLQueryResolver、を実装し、スキームのルートクエリのすべてのフィールドに同じ名前のこれらのクラスの1つにメソッドがあることです。
public class Query implements GraphQLQueryResolver {
private PostDao postDao;
public List<Post> getRecentPosts(int count, int offset) {
return postsDao.getRecentPosts(count, offset);
}
}
メソッドの名前は、次のいずれかである必要があります。
- は
–フィールドがタイプの場合のみブール値 - 得る
メソッドには、GraphQLスキーマの任意のパラメーターに対応するパラメーターが必要であり、オプションでtypeDataFetchingEnvironment。の最終パラメーターを受け取ることができます。
これから説明するように、メソッドはGraphQLスキームの型に対して正しい戻り型も返す必要があります。 String、Int、List、などの単純な型を同等のJava型で使用でき、システムはそれらを自動的にマップします。
上記は、メソッド getRecentPosts、を定義します。このメソッドは、前に定義したスキーマのreservedPostsフィールドに対するGraphQLクエリを処理するために使用します。
3.4. Beanを使用したタイプの表現
GraphQLサーバーのすべての複合型は、Java Beanによって表されます。ルートクエリからロードされたか、構造内の他の場所からロードされたかは関係ありません。 同じJavaクラスは常に同じGraphQLタイプを表す必要がありますが、クラスの名前は必須ではありません。
Java Bean内のフィールドは、フィールドの名前に基づいてGraphQL応答のフィールドに直接マップされます。
public class Post {
private String id;
private String title;
private String category;
private String authorId;
}
GraphQLスキーマにマップされないJavabeanのフィールドまたはメソッドは無視されますが、問題は発生しません。 これは、フィールドリゾルバが機能するために重要です。
たとえば、ここでフィールド authorId は、前に定義したスキーマのいずれにも対応していませんが、次のステップで使用できます。
3.5. 複雑な値のフィールドリゾルバー
場合によっては、フィールドの値をロードするのは簡単ではありません。 これには、データベースの検索、複雑な計算などが含まれる場合があります。 GraphQL Toolsには、この目的で使用されるフィールドリゾルバーの概念があります。これらは、データbeanの代わりに値を提供できるSpringbeanです。
フィールドリゾルバーは、データBeanと同じ名前で、接尾辞 Resolver が付いた、Spring Context内の任意のBeanであり、GraphQLResolverインターフェイスを実装します。 フィールドリゾルバーBeanのメソッドは、データBeanの場合と同じルールをすべて実行しますが、データBean自体を最初のパラメーターとして提供します。
フィールドリゾルバーとデータBeanの両方に同じGraphQLフィールドのメソッドがある場合、フィールドリゾルバーが優先されます。
public class PostResolver implements GraphQLResolver<Post> {
private AuthorDao authorDao;
public Author getAuthor(Post post) {
return authorDao.getAuthorById(post.getAuthorId());
}
}
これらのフィールドリゾルバーがSpringコンテキストからロードすることが重要です。 これにより、他のSpringマネージドBeanを使用できるようになります。 DAO。
重要なのは、クライアントがフィールドを要求しない場合、GraphQLサーバーはフィールドを取得するための作業を行わない。 これは、クライアントが投稿を取得して作成者を要求しない場合、上記の getAuthor()メソッドは実行されず、DAO呼び出しは行われないことを意味します。
3.6. ヌル可能値
GraphQLスキーマには、一部の型はnull許容であり、他の型はnull可能ではないという概念があります。
これは、Javaコードでnull値を直接使用して処理します。 逆に、Java 8の新しいオプション型をnull許容型に直接使用すると、システムは値を使用して正しい処理を実行します。
これは、Javaコードがメソッド定義のGraphQLスキーマと明らかに同じであることを意味するため、非常に便利です。
3.7. 突然変異
これまでのところ、サーバーからデータを取得することだけを行ってきました。 GraphQLには、ミューテーションによってサーバーに保存されているデータを更新する機能もあります。
コードの観点からは、クエリがサーバー上のデータを変更できない理由はありません。 引数を受け入れ、新しいデータを保存し、それらの変更を返すクエリリゾルバーを簡単に作成できます。 これを行うと、APIクライアントに驚くべき副作用が発生し、悪い習慣と見なされます。
代わりに、 Mutationsを使用して、保存されているデータに変更が生じることをクライアントに通知する必要があります。
ミューテーションは、 GraphQLQueryResolverの代わりにGraphQLMutationResolver、を実装するクラスを使用してJavaコードで定義されます。
それ以外の場合は、クエリの場合と同じルールがすべて適用されます。 次に、Mutationフィールドからの戻り値は、Queryフィールドからの戻り値とまったく同じように扱われ、ネストされた値も取得できるようになります。
public class Mutation implements GraphQLMutationResolver {
private PostDao postDao;
public Post writePost(String title, String text, String category) {
return postDao.savePost(title, text, category);
}
}
4. GraphiQLの紹介
GraphQLには、GraphiQLと呼ばれるコンパニオンツールもあります。 これは、任意のGraphQLサーバーと通信し、それに対してクエリとミューテーションを実行できるUIです。 ダウンロード可能なバージョンはElectronアプリとして存在し、こちらから取得できます。
GraphiQL Spring Bootスターターの依存関係を追加することで、WebベースバージョンのGraphiQLをアプリケーションに自動的に含めることもできます。
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
これは、 /graphql;のデフォルトエンドポイントでGraphQLAPIをホストしている場合にのみ機能します。そうでない場合は、スタンドアロンアプリケーションが必要になります。
5. 概要
GraphQLは非常にエキサイティングな新しいテクノロジーであり、WebAPIの開発方法に革命をもたらす可能性があります。
Spring BootGraphQLStarterとGraphQLJavaToolsライブラリの組み合わせにより、このテクノロジーを新規または既存のSpringBootアプリケーションに非常に簡単に追加できます。
コードスニペットは、GitHubのにあります。