Spring Boot中使用GraphQL

1. 简介

GraphQL是Facebook的一个相对较新的概念,被称为Web API的REST的替代品。

在本文中,我们将学习如何使用 Spring Boot 设置 GraphQL 服务器,以便我们可以将其添加到现有应用程序中或在新应用程序中使用它。

2. 什么是GraphQL?

传统的 REST API 使用服务器管理资源的概念。我们可以使用各种HTTP请求以一些标准方式操作这些资源。只要我们的 API 符合资源概念,这就可以很好地工作,但当我们需要偏离它时,很快就会分崩离析。

当客户端需要同时来自多个资源的数据时,例如请求博客文章和评论时,也会受到影响。通常,这是通过让客户端发出多个请求或让服务器提供可能并不总是需要的额外数据来解决的,从而导致更大的响应大小。

GraphQL 为这两个问题提供了解决方案。它允许客户端准确指定所需的数据,包括在单个请求中导航子资源,并允许在单个请求中进行多个查询。

它还以更多的 RPC 方式工作,使用命名查询和突变,而不是标准的强制操作集。这适用于将控件放在它所属的位置,API 开发人员指定可用的内容,API 使用者指定所需的内容

例如,博客可能允许以下查询:

query {recentPosts(count: 10, offset: 0) {idtitlecategoryauthor {idnamethumbnail}}
}

此查询将:

  • 索取十个最新帖子
  • 对于每个帖子,请求 ID、标题和类别
  • 对于每个帖子,请求作者,返回 ID、姓名和缩略图

在传统的 REST API 中,这需要 11 个请求,一个用于帖子,10 个用于作者,或者需要在帖子详细信息中包含作者详细信息。

2.1. GraphQL 模式

GraphQL 服务器公开了一个描述 API 的模式。此架构由类型定义组成。每种类型都有一个或多个字段,每个字段接受零个或多个参数并返回特定类型。

graph派生自这些字段相互嵌套的方式。请注意,graph不需要是非循环的,循环是完全可以接受的,但它是定向的。客户端可以从一个字段获取到其子字段,但除非架构显式定义此字段,否则它无法自动返回到父字段。

博客的示例 GraphQL 架构可能包含以下定义,描述帖子、文章作者和根查询,以获取博客上的最新文章:

type Post {id: ID!title: String!text: String!category: Stringauthor: Author!
}type Author {id: ID!name: String!thumbnail: Stringposts: [Post]!
}# The Root Query for the application
type Query {recentPosts(count: Int, offset: Int): [Post]!
}# The Root Mutation for the application
type Mutation {createPost(title: String!, text: String!, category: String, authorId: String!) : Post!
}

某些名称末尾的“!”表示它是不可为空的类型。任何没有此值的类型都可以在服务器的响应中为 null。GraphQL 服务可以正确处理这些字段,使我们能够安全地请求可为空类型的子字段。

GraphQL 服务还使用一组标准字段公开架构,允许任何客户端提前查询架构定义。

这允许客户端自动检测架构何时更改,并允许客户端动态适应架构的工作方式。一个非常有用的例子是 GraphiQL 工具,它允许我们与任何 GraphQL API 进行交互。

3. 介绍 GraphQL Spring Boot Starter

Spring Boot GraphQL Starter 提供了一种在很短的时间内让 GraphQL 服务器运行的绝佳方法。使用自动配置和基于注释的编程方法,我们只需要编写服务所需的代码。

3.1. 设置服务

需要的依赖项:

<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>

因为 GraphQL 与传输无关,所以我们在配置中包含 Web 启动器。这会在默认的 /graphql 端点上使用 Spring MVC 通过 HTTP 公开 GraphQL API。其他启动器可用于其他底层实现,例如Spring Webflux。如有必要,我们还可以在 application.properties 文件中自定义此端点。

3.2. 编写模式

GraphQL Boot 启动器的工作原理是处理 GraphQL 模式文件来构建正确的结构,然后将特殊的 bean 连接到此结构。Spring Boot GraphQL 启动器会自动查找这些模式文件。

我们需要将这些“.graphqls”或“.gqls”模式文件保存在
src/main/resources/graphql/**位置下,Spring Boot会自动拾取它们。像往常一样,我们可以使用
spring.graphql.schema.locations 自定义位置,并使用
spring.graphql.schema.file-extensions 配置属性自定义文件扩展名。

一个要求是必须只有一个根查询和最多一个根突变。与架构的其余部分不同,我们不能将其拆分到文件之间。这是 GraphQL 模式定义的限制,而不是 Java 实现的限制。

3.3. Root Query Resolver

根查询需要具有特殊批注的方法来处理此根查询中的各种字段。与模式定义不同,根查询字段只有一个 Spring Bean 没有限制。

我们需要用@QueryMapping注释来注释处理程序方法,并将它们放在应用程序中的标准@Controller组件中。这会将带注释的类注册为 GraphQL 应用程序中的数据获取组件:

@Controller
public class PostController {private PostDao postDao;@QueryMappingpublic List<Post> recentPosts(@Argument int count, @Argument int offset) {return postDao.getRecentPosts(count, offset);}
}

上面定义了方法 recentPosts,我们将使用它来处理之前定义的模式中 recentPosts 字段的任何 GraphQL 查询。此外,该方法必须具有使用与架构中的相应参数对应的@Argument批注的参数。

它还可以选择采用其他与 GraphQL 相关的参数,例如 GraphQLContext、DataFetchingEnvironment 等,以访问底层上下文和环境。

该方法还必须为 GraphQL 模式中的类型返回正确的返回类型,正如我们将要看到的。我们可以使用任何简单的类型,String,Int,List等,以及等效的Java类型,系统只是自动映射它们。

3.4. 使用 bean 来表示Types

GraphQL 服务器中的每个复杂类型都由 Java Bean 表示无论是从根查询还是从结构中的其他任何位置加载。同一个 Java 类必须始终表示相同的 GraphQL 类型,但类的名称不是必需的。

Java Bean 中的字段将根据字段名称直接映射到 GraphQL 响应中的字段:

public class Post {private String id;private String title;private String category;private String authorId;
}

Java Bean 上任何未映射到 GraphQL 模式的字段或方法都将被忽略,但不会导致问题。

3.5. Complex Values的字段解析器

有时,字段的值对于加载来说并不重要。这可能涉及数据库查找、复杂计算或其他任何内容。@SchemaMapping注释将处理程序方法映射到架构中具有相同名称的字段,并将其用作该字段的 DataFetcher。

@SchemaMapping
public Author author(Post post) {return authorDao.getAuthor(post.getAuthorId());
}

重要的是,如果客户端不请求字段,那么 GraphQL 服务器将不会执行检索它的工作。这意味着,如果客户端检索帖子并且不要求作者字段,则不会执行上面的author() 方法,也不会进行 DAO 调用。或者,我们也可以在注释中指定父类型名称和字段名称:

@SchemaMapping(typeName="Post", field="author")
public Author getAuthor(Post post) {return authorDao.getAuthor(post.getAuthorId());
}

在这里,注释属性用于将其声明为架构中author字段的处理程序。

3.6. 可为空值

GraphQL 模式的概念是,某些类型可为空,而其他类型则不可为空。我们在 Java 代码中直接使用 null 值来处理这个问题。相反,我们可以将 Java 8 中的新 Optional 类型直接用于可为空的类型,系统将对这些值执行正确的操作。

这非常有用,因为这意味着我们的 Java 代码与方法定义中的 GraphQL 模式更明显地相同。

3.7. 突变

到目前为止,我们所做的一切都是为了从服务器检索数据。GraphQL 还能够通过突变更新存储在服务器上的数据。

从代码的角度来看,查询没有理由不能更改服务器上的数据。我们可以轻松编写接受参数、保存新数据并返回这些更改的查询解析器。这样做会给 API 客户端带来令人惊讶的副作用,并被视为不良做法。

相反,应使用突变来通知客户端这将导致正在存储的数据发生更改。

与 Query 类似,通过在控制器中用 @MutationMapping 注释处理程序方法来定义突变。然后,来自突变字段的返回值与来自查询字段的返回值完全相同,从而允许检索嵌套值:

@MutationMapping
public Post createPost(@Argument String title, @Argument String text,@Argument String category, @Argument String authorId) {Post post = new Post();post.setId(UUID.randomUUID().toString());post.setTitle(title);post.setText(text);post.setCategory(category);post.setAuthorId(authorId);postDao.savePost(post);return post;
}

4. GraphiQL

GraphQL 还有一个名为 GraphiQL 的配套工具。这个 UI 工具可以与任何 GraphQL 服务器通信,并有助于针对 GraphQL API 使用和开发。

Spring GraphQL 附带了一个默认的 GraphQL 页面,该页面在 /graphiql 端点处公开。默认情况下,终结点处于禁用状态,但可以通过启用
spring.graphql.graphiql.enabled 属性来打开它。这提供了一个非常有用的浏览器内工具来编写和测试查询,尤其是在开发和测试期间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/8940.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Centos7 扩容(LVM 和非 LVM)

一、磁盘扩容方式 CentOS 系统的磁盘扩容可以分为两种方式&#xff1a;LVM 管理和非 LVM 管理。 LVM 管理的分区和传统分区方式是可以共存的。在同一个系统中&#xff0c;你可以同时使用 LVM 管理的分区和传统分区。 例如&#xff0c;在 CentOS 系统中&#xff0c;你可以选择将…

while循环

while循环是一种常见的循环结构&#xff0c;它会重复执行一段代码&#xff0c;直到指定的条件不再满足。 基本语法如下&#xff1a; while 条件: # 循环体代码 其中&#xff0c;条件是一个布尔表达式&#xff0c;如果为True&#xff0c;则执行循环体中的代码&#xff1b;如果…

剑指offer51.数组中的逆序对

用类似于归并排序的方法解决这道题&#xff0c;把数组分成左右两个数组&#xff0c;然后归并排序&#xff0c;在排序的过程中统计逆序对的个数 class Solution {int[] nums, tmp;public int reversePairs(int[] nums) {this.nums nums;tmp new int[nums.length];return merge…

LX04 小米触屏音箱刷机教程

说明 这里的电脑是 win11 系统&#xff0c;win10 有差别但是不影响&#xff0c;自己解决,但不要使用精简版,尽量避免使用 win7 请看完此教程再问其他问题 此教程仅供学习使用&#xff0c;安装第三方软件出现的任何问题&#xff0c;小米都不会给予售后赔偿处理&#xff01;…

Web3将自己写在合约中的代币添加到MetaMask中管理

上文 Web3带着大家根据ERC-20文档编写自己的第一个代币solidity智能合约 带着大家在智能合约中创建了一个自己的代币系统 我们可以在MetaMask中去导入 ganache环境下模拟出来的第一和第二个账号 我们这里 可以看到他们的 ETH 但看不到自己的代币符号 没关系 我们点击这下面的…

MySQL必知必会 第27章 全球化和本地化

本章介绍MySQL处理不同字符集和语言的基础知识。 27.1 字符集和校对顺序 字符集&#xff1a;字母和符号的集合编码&#xff1a;某个字符集成员的内部标识校对&#xff1a;规定字符如何比较的指令 校对很重要 使用何种字符集和校对的决定在服务器、数据库和表级进行。 27.2 …

剑指 Offer. 翻转单词顺序

输入一个英文句子&#xff0c;翻转句子中单词的顺序&#xff0c;但单词内字符的顺序不变。为简单起见&#xff0c;标点符号和普通字母一样处理。例如输入字符串"I am a student. "&#xff0c;则输出"student. a am I"。 示例 1&#xff1a; 输入: "…

[howto] 使用git时,如何忽略本地文件

背景 有一些项目&#xff0c;需要在配置中填写自己的key&#xff0c;但是那个文件还在git的版本管理中&#xff0c;如果自己填了key&#xff0c;很容易把自己的key给commit上去了。所以要么每次提交之前检查一下&#xff0c;不提交这个文件&#xff0c;要么干脆忽略&#xff0…

Python学习笔记-Django框架基础,APP,数据模型,后台管理,路由

一、Django框架简介 Django框架是Python的常用web框架&#xff0c;遵循 MVC 设计模式的框架&#xff0c;采用了MTV的框架模式&#xff0c;即模型M&#xff0c;视图V和模版T。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的&#xff0c;即是CMS&…

新能源汽车的发展

目录 1.什么是新能源 2.什么是新能源汽车 3.新能源汽车的优点 4.新能源汽车的危害 5.新能源汽车未来的发展 1.什么是新能源 新能源是指与传统能源&#xff08;如化石燃料&#xff09;相比&#xff0c;更具可再生性、清洁性和低碳排放的能源形式。它主要通过利用自然资源和可…

rust学习-面向对象

面向对象编程&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09; 封装细节 main.rs use rust_demo::AveragedCollection;fn main() {let mut ac AveragedCollection::new();println!("ac{:?}", ac);ac.add(3);ac.add(5);ac.add(7);println!(&…

Vue如何配置eslint

eslint官网: eslint.bootcss.com eslicate如何配置 1、选择新的配置&#xff1a; 2、选择三个必选项 3、再选择Css预处理器 4、之后选择处理器 5、选择是提交的时候就进行保存模式 6、放到独立的配置文件上去 7、最后一句是将自己的数据存为预设 8、配合console不要出现的规则…

【Java中的Thread线程的简单方法介绍和使用详细分析】

文章目录 前言一、run() 和 start() 方法二、sleep() 方法三、join() 方法总结 前言 提示&#xff1a;若对Thread没有基本的了解&#xff0c;可以先阅读以下文章&#xff0c;同时部分的方法已经在如下两篇文章中介绍过了&#xff0c;本文不再重复介绍&#xff01;&#xff01;…

Java: Commons-io

Commons-io是apache开源基金组织提供的一组有关IO操作的开源工具包。 1.作用 提高IO流的开发效率。 2.FileUtils类&#xff08;文件夹/文件&#xff09; 1.常见方法 static void copyFile(File srcFile&#xff0c;File destFile): 复制文件static void copyDirectory(Fil…

【Luogu】 P3665 [USACO17OPEN] Switch Grass P

题目链接 点击打开链接 题目解法 首先给出 2 个结论&#xff1a; 最接近的不同颜色的点一定是相邻的点 证明&#xff1a;假设最接近的不同颜色的点 ( u , v ) (u,v) (u,v) 不相邻&#xff0c;那么 u , v u,v u,v 之间的路径中必有相邻的不同颜色点 ( u ′ , v ′ ) (u,v…

在nginx上部署nuxt项目

先安装Node.js 我安的18.17.0。 安装完成后&#xff0c;可以使用cmd&#xff0c;winr然cmd进入&#xff0c;测试是否安装成功。安装在哪个盘都可以测试。 测试 输入node -v 和 npm -v&#xff0c;&#xff08;中间有空格&#xff09;出现下图版本提示就是完成了NodeJS的安装…

【js Call、apply与bind 区别】

JavaScript 中的 Call、apply 和 bind 都是用来改变函数的执行上下文&#xff08;即 this 指向&#xff09;的方法&#xff0c;但它们之间有些区别&#xff1a; Call 和 apply Call 和 apply 都是 Function.prototype 的方法。它们的作用是改变函数的 this 指向&#xff0c;并…

electron 生成 arm64 的包

vue electron&#xff1a;https://blog.csdn.net/qq1195566313/article/details/131713875 打包配置修改如下 electronBuilder.build({config: {appId: com.example.app,productName: vite-electron,directories: {output: path.join(process.cwd(), "release"), …

Windows OS CMD 常用工具 の 命令合集

# First Of All 每次想要修改环境变量都要按部就班点开系统属性、高级系统设置、环境变量。这种操作实在是太繁琐了&#xff0c;对于我一个懒人来讲实在是 忍无可忍 。如果可以使用 WINR 或 CMD 直接打开系统内的一些工具&#xff0c;是不是就可以节省很多时间&#xff1b;是不…

【node.js】01-fs读写文件内容

目录 一、fs.readFile() 读取文件内容 二、fs.writeFile() 向指定的文件中写入内容 案例&#xff1a;整理txt 需求&#xff1a; 代码&#xff1a; 一、fs.readFile() 读取文件内容 代码&#xff1a; //导入fs模块&#xff0c;从来操作文件 const fs require(fs)// 2.调…