本文首次发布于我的博客,原文地址vio.vin/article/use-puppeteer
GraphQL API は Restful API に似ており、データをクエリするための言語です。Restful API と比較して、GraphQL API はクエリにおいてより柔軟で、フロントエンドとバックエンドのコード作成もより便利です。本記事では、SpringBoot3.0 を基に GraphQL API アプリケーションを構築する方法、GraphQL API インターフェースが利用可能かどうかをテストする方法、そしてフロントエンドが GraphQL API インターフェースをどのように呼び出すか(Nuxt プロジェクトを例に)を紹介します。
GraphQL とは#
以下の内容はGraphQL Wikiからの抜粋です。
GraphQL はオープンソースの API 向けに作成されたデータクエリ操作言語およびそれに対応する実行環境です。2012 年に Facebook 内部で開発されていたが、2015 年に公開されました。2018 年 11 月 7 日、Facebook は GraphQL プロジェクトを新設された GraphQL 基金(非営利の Linux 基金に属する)に移管しました。
GraphQL は REST や他の Web サービスアーキテクチャに比べて、Web API を開発するためのより効率的で強力かつ柔軟な方法を提供します。クライアントが必要に応じてデータ構造を定義し、サーバーが同じデータ構造の対応データを返すことで、サーバーからの冗長なデータの返却を避けますが、一方でこの方法はクエリ結果の Web キャッシュを効果的に利用できないことを意味します。GraphQL のクエリ言語がもたらす柔軟性と豊かさは同時に複雑さを増し、シンプルな API がこの方法に適さない可能性があります。
なぜ GraphQL を使用するのか#
- フロントエンドがどのデータを返すかを決定します。これはバックエンドが複雑な形式の JSON を必要とする場合に特に便利で、フロントエンドは必要なデータと不要なデータを自分で決定し、冗長なデータを減らし、バックエンドの負担を軽減します。
- クエリだけでなく、更新にも使用できます。名前は Graph Query Language ですが、GraphQL は作成、更新、削除操作にも使用できます。
使用方法#
GraphQL インターフェースを呼び出して、バックエンドにこのようなデータを送信します。これは JSON ではないことに注意してください。
ここで渡されるパラメータは記事の ID であり、特定の記事をクエリするために使用されます。
query Article {
article(id: "2") {
id
title
content
author {
id
firstName
lastName
}
tags {
id
name
description
}
}
}
バックエンドはリクエスト内のデータ構造に基づいて対応するデータを返します。
{
"data": {
"article": {
"id": "2",
"title": "title2",
"content": "content2",
"author": {
"id": "author-2",
"firstName": "Douglas",
"lastName": "Adams"
},
"tags": [
{
"id": "2",
"name": "Python",
"description": "Python関連の記事"
},
{
"id": "3",
"name": "JavaScript",
"description": "JavaScript関連の記事"
}
]
}
}
}
複数のデータを一度にクエリすることもできます。
query Article {
articles {
id
title
content
author {
id
firstName
lastName
}
tags {
id
name
description
}
}
}
Reponse
{
"data": {
"articles": [
{
"id": "1",
"title": "title1",
"content": "content1",
"author": {
"id": "author-1",
"firstName": "Joshua",
"lastName": "Bloch"
},
"tags": [
{
"id": "1",
"name": "Java",
"description": "Java関連の記事"
},
{
"id": "2",
"name": "Python",
"description": "Python関連の記事"
},
{
"id": "1",
"name": "Java",
"description": "Java関連の記事"
}
]
},
{
"id": "2",
"title": "title2",
"content": "content2",
"author": {
"id": "author-2",
"firstName": "Douglas",
"lastName": "Adams"
},
"tags": [
{
"id": "2",
"name": "Python",
"description": "Python関連の記事"
},
{
"id": "3",
"name": "JavaScript",
"description": "JavaScript関連の記事"
}
]
}
]
}
}
SpringBoot アプリケーションの構築#
IDEA に GraphQL 関連のプラグインを先にインストールすることをお勧めします。GraphQLこのプラグインはschema.graphqls
ファイルの構文ハイライトをサポートします。
プロジェクトの作成#
pom.xml に以下の依存関係を追加する必要があります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
エンティティクラスの定義#
エンティティクラスはデータベースのフィールドに対応することも、自作の VO であることもできます。ここでは record を使用していますが、従来の class を使用することも選択できます。
public record Article(String id, String title, String content, String authorId, String tagId) {}
public record Author (String id, String firstName, String lastName) {}
public record Tag(String id, String name, String description) {}
データのクエリ#
schema.graphqls
の定義#
schema.graphqls
ファイルは GraphQL スキーマを定義し、データ構造とデータ間の関係、クライアントが行える操作を記述するために使用されます。
ファイルは以下の内容を定義します。
- タイプ
- クエリ
- 関係
以下は具体的なschema.graphqls
ファイルの例です。
# クエリのインターフェース、クライアントがアクセスできる内容
type Query {
# idはクエリのパラメータを示し、Articleは下のtypeで定義された返却データ構造です
article(id: String): Article
# [Article]を使用して多くのデータが配列形式で返されることを示します
articles: [Article]
tag(id: String): Tag
tags: [Tag]
author(id: String): Author
}
# データ構造の定義
type Author {
id: String
firstName: String
lastName: String
}
# tagsは複数のデータを持つため、[Tag]で示します
type Article {
id: String
title: String
content: String
author: Author
tags: [Tag]
}
type Tag {
id: String
name: String
description: String
}
コントローラーの作成#
GraphQL もコントローラーを通じてアクセスする必要があります。MVC で@RequsetMapping
を使用するのに対し、GraphQL では@QueryMapping
を使用する必要があります。この@QueryMapping
はリクエストパスを定義する必要がありません。以下は具体的な例です。
@QueryMapping#
@QueryMapping
public Collection<Article> articles()
{
return queryService.listArticles();
}
ここでのメソッド名はarticles()
で、schema.graphqls
ファイルのtype Query
で定義された名前と一致する必要があります。
フロントエンドが
query Article { articles { id } }
を送信すると、このインターフェースにマッチします。このメソッドはtype Article
に含まれるすべての属性を返し、その後GraphQL
はフロントエンドから渡されたパラメータに基づいて必要なデータを自動的に保持します。
例えば、この例ではフロントエンドが id と title だけをリクエストしたため、id と title のみが返され、他のデータは隠されます / 削除されます。
query Article {
articles {
id
title
}
}
クエリのパラメータには@Argument
注釈を追加する必要があります。さもなければエラーが発生します。
@QueryMapping
public Article article(@Argument String id) {
return queryService.getArticleById(id);
}
@SchemaMapping#
@QueryMapping
と@SchemaMapping
は GraphQL の最も重要な 2 つの注釈です。@QueryMapping
はリクエストアドレスをマッチさせるために使用され、@SchemaMapping
はデータ関係を構築するために使用されます。
具体的な例を挙げると、
@QueryMapping
public Article article(@Argument String id) {
return queryService.getArticleById(id);
}
@SchemaMapping
public Collection<Tag> tags(Article article)
{
return queryService.getTagsByArticleId(article.id());
}
@SchemaMapping
public Author author(Article article)
{
return queryService.getAuthorByAuthorId(article.authorId());
}
tags()
メソッドは Article に関連する Tag をクエリするために使用されるため、メソッドのパラメータはArticle article
であり、返却データは複数の Tag です。同様に、author は Article に関連する Author をクエリするために使用され、返却データは Author 型です。
データの保存#
schema.graphqls
の定義#
type Mutation {
# !はこのパラメータが必須であることを示し、:Articleは挿入後に返されるデータ型を示します
createArticle(article: ArticleInput!): Article
}
input ArticleInput {
title: String
content: String
authorId: String
tagId: String
}
コントローラー#
@MutationMapping
public Article createArticle(@Argument("article") ArticleInput article) {
return createService.createArticle(article);
}
このインターフェースを呼び出す#
mutation {
createArticle(
article: {title: "Sample Title", content: "Sample Content", authorId: "author-3", tagId: "2"}
) {
id
title
content
author {
id
firstName
lastName
}
tags {
id
name
description
}
}
}
データの削除 / 更新#
データの削除もMutation
内で操作を定義する必要があります。: の後は操作が完了した後の返却型です。ここでは詳細には説明しません。
type Mutation {
deleteArticle(id: String!): Boolean
updateArticle(id: String!, article: ArticleInput!): Article
}
バックエンドプロジェクトのアドレスhttps://github.com/lnbiuc/graphql-start