我是靠谱客的博主 粗心石头,最近开发中收集的这篇文章主要介绍基于java的Graphql学习笔记Graphql 简介Graphql 核心概念,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

最近有需要使用Graphql +SpringBoot 实现一个BFF 服务,因此对Graphql 进行了学习和整合SpringBoot进行使用,简单写个笔记记录下学习心得(差不多是官网的内容,只是笔者是学习java的,所有借用java方便理解graphql概念,在这里简单记录下,整合SpringBoot原理和使用心得有空再整理一篇)

Graphql 简介

官网的定义是:GraphQL 用于API的查询语言,是通过使用为数据定义的类型系统执行查询的服务器端运行时。GraphQL不绑定任何特定的数据库或存储引擎,而是由您现有的代码和数据支持

个人理解(个人学习是基于java 和SpringBoot的基础上进行学习使用的感悟):
Graphql 是一种协议,可以使前端的查询精确到字段级别,不在是http的接口级别,数据由前端决定返回什么数据,使得接口不再传输冗余字段(前端用不到的字段),其他的写不出来了。

个人理解浅薄,也结合了SpringBoot进行整合使用,使用过程中并未真正理解其优势,可能是学习不够深入,如果读者有其他更深的感悟,也请不吝指导一二

Graphql 核心概念

Fields

​ 字段 ,可以是一个字符串类型(String),也可以是一个对象类型(Object)(同java中的字段)

Arguments

​ 每一个字段和嵌套对象都能有自己的一组参数,从而使得 GraphQL 可以替代多次 API 获取请求。甚至你也可以给 标量(scalar)字段传递参数(例如java中提供了获取标量的有参get方法)

Schema 和类型

Type System

​ 每一个 GraphQL 服务都会定义一套类型,用以描述你可能从那个服务查询到的数据。每当查询到来,服务器就会根据 schema 验证并执行查询.

​ GraphQL 查询语言本质就是在选择对象上的字段, 会有一个特殊的对象 “root” 开始,基于该对象上面进行字段选择

Object Types and Fields

type Character {
name: String!
appearsIn: [Episode!]!
}
类比java :
class Character {
@NotNull
String name;
@NoEmpty
List<Episode> appearsIn;
}

Scalar Types

​ 标量类型,(类同Java中的基础数据类型,已经是最小的类型,没有属性),一个对象类型有自己的名字和字段,而某些时候,这些字段必然会解析到具体数据。这就是标量类型的来源:它们表示对应 GraphQL 查询的叶子节点

默认Scalar Types

Int:有符号 32 位整数。

Float:有符号双精度浮点值。

String:UTF‐8 字符序列。

Booleantrue 或者 false

ID:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型(如果定义了类型为ID,在返回的数据中存在从重复ID的数据,则会直接异常)

Enumeration Types

​ 枚举类型是一种特殊的Scalar Type(可以当成Java中枚举类的无属性简化版)

enum FundType {
CURRENCY
LOF
}

Lists and Non-Null

Lists 列表,同Java中的集合
Non-Null,用于检查数据入参,或者返回值是否为空

用于返回值上面:

type Character {
name: String!
appearsIn: [Episode]!
}

用于定义字段上的参数:

query DroidById($id: ID!) {
droid(id: $id) {
name
}
}

Interfaces

​ 一个接口是一个抽象类型,它包含某些字段,而对象类型必须包含这些字段,才能算实现了这个接口(类似Java中的父类,但是graphql “子类” 必须全部定义“父类中的字段”)

interface Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
}
type Droid implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
primaryFunction: String
}

Inline Fragments

如果要查询一个只存在于特定对象类型上的字段,你需要使用Inline Fragments,格式:... on Type
(有点像java中的多态,但是java多态为程序执行过程自动处理,而graphql需要通过… on Type 制定实际对象的类型和字段)
如:


products(productType:null){
code
name
... on Fund {
fundType
manager (code:"test"){
id
name
}
}
... on Portfolio{
funds{
code
name
fundType
manager (code:"test"){
id
desc
}
}
}
}

Union Types

Union Types和接口十分相似,区别在于Union的类型之间不一定存在“继承”关系,类型之间的字段无需有共同字段等联系(目前没发现在java中可起到什么比较有意义的作用)

union SearchResult = Manager | Fund
type Query{
search(type:String): SearchResult # Union Types
}

search(type:"rf"){
__typename # 获取Fund类型名,用于在客户端区分不同的数据类型
... on Fund{
code
name
}
}

Input Types

传递复杂作为新建对象

type Mutation{
createFund(input: FundInput!): String!
}
input FundInput {
code: ID!
name: String!
}

verify

通过使用类型系统,你可以预判一个查询是否有效。这让服务器和客户端可以在无效查询创建时就有效地通知开发者,而不用依赖运行时检查

  1. 通过使用类型系统,你可以预判一个查询是否有效。这让服务器和客户端可以在无效查询创建时就有效地通知开发者,而不用依赖运行时检查
  2. 查询字段的时候,我们只能查询给定类型上的字段
  3. 查询一个字段时,如果其返回值不是标量或者枚举型,那我们就需要指明想要从这个字段中获取的数据
  4. 类似地,如果一个字段是标量,进一步查询它上面的字段也没有意义

execute

一个 GraphQL 查询在被验证后,GraphQL 服务器会将之执行,并返回与请求的结构相对应的结果,该结果通常会是 JSON 的格式

Query And Mutation Type

每一个 GraphQL 服务都有一个 query 类型,可能有一个 mutation 类型。这两个类型和常规对象类型无差,但是它们之所以特殊,是因为它们定义了每一个 GraphQL 查询的入口。因此如果你看到一个像这样的查询:

type Query {
hero(episode: Episode): Character
droid(id: ID!): Droid
}

自定义Scalar Types

 scalar Date

Aliases

{
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}

Fragments

fragment fundsFields on Fund{
code
name
fundType
manager (code:"test"){
id
desc
}
}
{
funds {
... fundsFields
}
}

Inline Fragments

如果你查询的字段返回的是接口或者联合类型,那么你可能需要使用Inline Fragments来取出下层具体类型的数据

products(productType:null){
code
name
__typename
... on Fund {
fundType
manager (code:"test"){
id
name
}
}
... on Portfolio{
funds{
code
name
fundType
manager (code:"test"){
id
desc
}
}
}
}

Operation name

操作类型:query*、*mutation 、subscription

操作名称是你的操作的有意义和明确的名称

Variables

一级方法将动态值提取到查询之外,然后作为分离的字典传进去。这些动态值即称为变量

使用变量:

  1. 使用 $variableName 替代查询中的静态值。
  2. 声明 $variableName 为查询接受的变量之一。
  3. variableName: value 通过传输专用(通常是 JSON)的分离的变量字典中

Variable definitions

$episode: Episode

Default variables

$episode: Episode = "JEDI"

Directives

变量动态地改变我们查询的结构,比如详情比普通概要显示更多字段,则可以通过指令动态调整获取的字段、结构

@include(if: Boolean) 仅在参数为 true 时,包含此字段。
@skip(if: Boolean) 如果参数为 true,跳过此字段

服务端实现也可以定义新的指令来添加新的特性。 TODO ?

Mutations

查询字段时,是并行执行,而变更字段时,是线性执行,一个接着一个

Meta fields

__typename,一个元字段,以获得那个位置的对象类型名称,常配合Inline Fragments一起使用

内省

GraphQL 通过内省系统可以知道 GraphQL Schema 它支持哪些查询

query querySchema{
__schema{
types{
name
}
}
Fund:__type(name: "Fund") {
name
kind
fields{
name
type{
name
kind
}
}
}
ProductType: __type(name: "ProductType") {
name
kind
}
}

中文官网:https://graphql.cn/

最后

以上就是粗心石头为你收集整理的基于java的Graphql学习笔记Graphql 简介Graphql 核心概念的全部内容,希望文章能够帮你解决基于java的Graphql学习笔记Graphql 简介Graphql 核心概念所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(33)

评论列表共有 0 条评论

立即
投稿
返回
顶部