前言

GraphQL已经被越来越多的开源项目作为业务接口的开发规范,而在此之前流行的是restful接口。那么GraphQL是什么?GraphQL相比restful有哪些好处?本文带你初窥GraphQL的门道,看看你们的业务是否适合使用GraphQL。

GraphQL是什么

GraphQL = Graph + QL (query language)

GraphQL是一种图表化(graph)的查询语言(query language),用于定义API的查询语法。GraphQL只定义api查询语法和数据规范,没有限制前端和后端的类型,也没有限制存储层的实现。

可以类比SQL,SQL仅定义了一套数据操作与查询语言的规范,Mysql,oracle等各大数据库开放了符合SQL标准的接口,当然你可以自己开发一个使用SQL查询的业务接口。

官网解释:

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data

GraphQL既是一种用于API的查询语言也是一个满足你数据查询的运行时

GraphQL的组成结构

1. schema

GraphQL通过schema定义api和数据结构,schema通常以文件形式存在,包含一系列的对象定义。对象结构为类json格式的字符串。

根据总结,对象定义的格式遵守以下规则:

${对象类型} ${对象名称} {#字段${字段名称}: ${字段类型}#字段类型为数组${字段名称}: [${字段类型}]#字段类型为非空对象${字段名称}: ${字段类型}!#带参数的字段${字段名称} (${对象名称} : ${对象类型}): ${字段类型}
}

GraphQL定义了一些标量类型,可作为对象的字段定义。标量类型有:Int、Float、String、Boolean、ID

其中ID类型是GraphQL定义的唯一标识符,其本质上也是字符串。

GraphQL支持枚举类型enum,枚举类型定义示意:

enum Gender {malefemale
}

GraphQL的对象类型主要分为两类,数据对象和接口对象,分别用于定义接口的输入输出和接口实体。

数据对象

  • type

自定义名称的类型(关键字除外),用于定义接口查询的返回对象类型以及内联对象类型。

type Man {name: Stringage: Intgender: Gender
}
  • interface

接口类型interface,和type对象定义基本一致。

interface Human {name: Stringage: Intgender: Gender
}

对象可以通过implements申明实现了某个接口对象,实现对象必须包含接口对象的所有字段,方便对相同业务属性进行抽象。

type Man implements Human {name: Stringage: Intgender: Gender
}
  • input

输入类型input本质上也是一个type类型,是作为Mutation接口的输入参数。换言之,想要定义一个修改接口(add,update,delete)的输入参数对象,就必须定义一个input输入类型。

input ManInput {name: Stringage: Intgender: Gender
}

值得一提的是,在input对象中的对象也必须是input类型,这可能是一个比较局限的设计。

接口对象

接口对象分为数据查询(select)接口和数据操作(add,update,delete)接口,分别用Query关键字和Mutation关键字来定义。下面举两个例子:

定义一个名为search的查询接口,返回对象为Human类型:

type Query {search(name: String): Human
}

定义一个名为add的数据插入方法,方法参数为Human类型,返回对象也为Human类型:

type Mutation {add(human: Human): Human
}

Mutation类型不对数据的操作含义进行区分,不像SQL一样,有ADD、UPDATE、DELETE,统一使用Mutation进行定义,具体的操作含义在接口的实现中完成。

2. query

通过schema对api进行定义之后,后续发起的graphql api请求都必须严格遵守这个定义。特别的,在graphql的api请求中可以指定返回对象的部分而非全部的字段,从而减少一些不必要的数据传输。

GraphQL的api请求只有Query和Mutation两种,下面简单介绍下Query和Mutation的查询语法。

简单query语句

//调用search接口,传入一个名为name的字符串参数,期望的返回类型是Human对象中的age字段
query {search(name: "马云"): {age}
}

带参数的graphql api请求附带一个专门用于描述请求参数json数据,json的key和api参数名称对应。

带对象参数的query语句

//调用search接口,传入一个名为human的Human对象参数,期望的返回值是Human对象中的age字段
query queryHuman($human: Human) {search(human: $human): {age}
}//graphql的参数,以json格式给出,对应类型Human
graphql variables
{"human": {"name": "马云"}
}

带对象参数的Mutation语句

//调用add接口,传入一个名为human的Human对象参数,期望的返回值是human对象的三个字段
mutation addHuman($human: Human) {add(human: $human): {nameagegender}
}//graphql的参数,以json格式给出,对象的结构和schema定义必须一致
graphql variables{"human": {"name": "马云","age": 50,"gender": "male"}
}

3. datafetchers

datafetcher其实是graphql-java中的一个组件,其作用是查询和操作业务数据,并提供api的返回值。datafetcher会通过显式的申明和query绑定起来,从而实现api和数据层的交互。

任何一门语言实现graphql都需要类似datafetcher这样一个组件来实现api和数据层的交互。

GraphQL能带来什么好处?

使用GraphQL能带来什么好处呢?我总结主要有以下几点:

  1. 强一致性

graphql的协议规定了api和schema的定义必须保持一致,这种文档先行的开发模式,使得项目的架构更加清晰,并且使得接口本身就多了一层校验。

  1. 减少数据冗余

graphql的api在请求时可以指定返回的字段,返回的字段和预期是一致的。这一特性可以让接口在不同的场景下返回必需的字段,减少部分网络开销,并且使得接口的通用性更高。

  1. 自文档性

得益于graphql的强一致性,使得graphql的schema本身就可以作为api接口文档使用。配合graphql的一些第三方库,可以做到api文档的在线调试和可视化展示,变成真正的图化(graph)查询语言(query language)。

graphiql插件的在线调试api功能

graphql voyager的图形化api查看

GraphQL有什么缺点?

来说说我认为graphql的主要缺点吧:

  1. 简单问题复杂化

为了实现graphql充分的规范性,也加重了一些开发成本(虽然已经有第三方库可以做到快速开发),任何一个api在开发时都有明确的两步走:1.在schema定义接口和对象 2.实现datafecher,哪怕是一个最简单的get请求。

  1. 不方便统一控制

graphql不像restful接口,有清晰的层级划分(/a/b/c的结构),graphql的api只能使用接口名称进行区分,接口名称不像层级结构那么容易管理。通常在restful结构下,我们可以通过拦截器对符合某一规则的接口路径进行统一处理(比如对/restful/*的接口进行身份认证),而graphql的请求路径是在同一个url下的,这种处理逻辑就比较难以实现了。

GraphQL框架支持

  1. graphql-js

graphql官方的js实现,可以快速的搭建js端的graphql服务器,和进行graphql请求。

官方文档地址:

https://graphql.cn/graphql-js/

  1. graphql-java

graphql官方的java实现,前文也介绍过了,是基于datafetcher的架构,代码比较容易理解,缺点是开发量较大。

官方文档地址:

https://www.graphql-java.com/documentation/v16/

使用graphql java开发graphql接口的demo


public static void main(String[] args) {//1. 定义schema,这里是字符串直接给出了schemaString schema = "type Query{hello: String}";SchemaParser schemaParser = new SchemaParser();TypeDefinitionRegistry typeDefinitionRegistry = schemaParser.parse(schema);//2. 定义datafetcher,并和query进行绑定;这里的datafetcher会返回一个固定值worldRuntimeWiring runtimeWiring = newRuntimeWiring().type("Query", builder ->builder.dataFetcher("hello", new StaticDataFetcher("world"))).build();SchemaGenerator schemaGenerator = new SchemaGenerator();GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeDefinitionRegistry, runtimeWiring);GraphQL build = GraphQL.newGraphQL(graphQLSchema).build();//3. 查询时指定查询名hello,不带任何参数,也不指定返回值ExecutionResult executionResult = build.execute("{hello}");System.out.println(executionResult.getData().toString());// Prints: {hello=world}
}
  1. graphql-kick-start

第三方实现的一个开源graphql java库,优点是能快速接入,配合springboot开发,几乎不需要写代码,并且集成了很多方便的插件如 graphiql,graphql voyager,可以实现真正的图化查询。

官方github地址:

https://github.com/graphql-java-kickstart/graphql-spring-boot

使用graphql-kick-start的graphql servlet插件快速开发graphql接口的demo

#启用 graphql servlet
graphql.servlet.enabled=true
#graphql servlet 使用的url
graphql.servlet.mapping=/graphql
#schema文件路径
graphql.tools.schema-location-pattern=person.schema
person.schematype Query {personByName(name: String): Person
}type Person {id: Intname: String
}
//GraphQLQueryResolver的实现类中的方法会自动和schema中的query绑定
@Component
public class PostQuery implements GraphQLQueryResolver {public Person personByName(String name) {PersonEntity personEntity = personMapper.findByName(name);return new Person(personEntity);}
}

GraphQL的用途

基于graphql的种种特性,以及graphql的库支持的程度来看(似乎官方也认定graphql是用于前后端接口开发的,并未提供除了js之外的客户端实现),目前而言,graphql似乎只适用于前后端之间的接口开发。所幸的是,graphql和restful并不冲突,前端接口可以直接剥离出来,使用graphql规范重新实现,且不影响原有接口。

综上所述,graphql主要用于实现前后端之间的接口,且有graphql本身的强一致性带来了很多规范上的优势。

GraphQL的认识与使用相关推荐

  1. 完爆Facebook/GraphQL,APIJSON全方位对比解析(一)-基础功能

    相关阅读: 完爆Facebook/GraphQL,APIJSON全方位对比解析(二)-权限控制 完爆Facebook/GraphQL,APIJSON全方位对比解析(三)-表关联查询 自APIJSON发 ...

  2. 【译】GraphQL vs. REST

    原文地址:GraphQL vs. REST 原文作者:Sashko Stubailo 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:wilsonandus ...

  3. fcm和firebase_我如何最终使Netlify Functions,Firebase和GraphQL一起工作

    fcm和firebase In a previous post I confessed defeat in attempting to get an AWS Lambda GraphQL server ...

  4. 如何使用FaunaDB + GraphQL

    I have one or two projects I maintain on Netlify, in addition to hosting my blog there. It's an easy ...

  5. 我希望支持JavaScript GraphQL实现的API

    The GraphQL schema language is great! It is certainly the best way to communicate anything about a G ...

  6. graphql是什么_为什么GraphQL是避免技术债务的关键

    graphql是什么 GraphQL (not to be confused with GraphDB or Open Graph or even an actual graph) is a rema ...

  7. graphql_普通英语GraphQL指南

    graphql by Luis Aguilar 路易斯·阿吉拉尔(Luis Aguilar) 普通英语GraphQL指南 (A Guide to GraphQL in Plain English) 您 ...

  8. react 错误边界_React with GraphQL和错误边界中的自定义错误页面

    react 错误边界 by Abi Noda 通过Abi Noda React with GraphQL和错误边界中的自定义错误页面 (Custom error pages in React with ...

  9. java通用象棋游戏_在通用国际象棋界面周围模拟GraphQL包装器

    java通用象棋游戏 The Universal Chess Interface (UCI) has been around a long time and used by many chess en ...

  10. graphql redux_如何在Redux应用程序中使用GraphQL

    graphql redux by Howon Song 通过宋颂恩 如何在Redux应用程序中使用GraphQL (How to use GraphQL in your Redux app) Fetc ...

最新文章

  1. 基于TF-IDF编码进行文本聚类分析:文档成对相似性计算、层次聚类(链接矩阵、树形图dendrogram绘制、聚类标签)
  2. 深入理解$watch ,$apply 和 $digest --- 理解数据绑定过程——续
  3. VS VC 读取 INI文件
  4. JAVA标识符命名规则及命名规范
  5. java写入carbondata_Carbondata使用过程中遇到的几个问题及解决办法
  6. java UTD对点发送信息_Java微信公众平台开发(九)--关键字回复以及客服接口实现(该公众号暂时无法提供服务解决方案)...
  7. vue打包运行并解决404问题
  8. 一台电脑有线连接路由器另一台无线连接_两个无线路由器怎么实现无线桥接【详细介绍】...
  9. 数据库学习一站式入门资料(纯干货)
  10. java 创建txt_JAVA读取TXT文件、新建TXT文件、写入TXT文件
  11. Android WIFI的管理方法
  12. Android储物柜代码,Android的应用程式储物柜安全性如何? | MOS86
  13. POI实现 Excel插入图片
  14. 内网服务器反弹映射到公网ip去访问
  15. ORA-01654: unable to extend index报错解决
  16. 最佳情侣身高差c语言函数,“最佳情侣身高差是多少为妙?”哈哈哈,神评尤为突出啊...
  17. 像李欣频一样思考人生~
  18. 自然几何之分形(2)
  19. 江淮500后桥壳体机械加工工艺及精镗两侧面孔工序夹具设计
  20. open_files打开输入输出文件

热门文章

  1. 中国信息安全测评中心-自主原创测评
  2. wps怎么把字缩到最小_WPS文字如何调节字体大小突破字号72的限制实现大小随意调...
  3. 2017第九届广州国际园林机械与园艺工具展 2017第九届广州国际园林景观与美好人居博览会 第九届广州国际花卉盆栽及花店花园用品展览会 2017中国花卉展览会 第九届广州国际绿化苗木展会刊(参展商名录
  4. 量子计算与区块链抗量子算法
  5. 次世代游戏建模制作工作流程 1
  6. 防止用户调整微信浏览器字体大小导致的显示异常
  7. 动态规划--01背包问题详解
  8. insert()用法
  9. uni-app z-index无效的解决办法(遮罩层)
  10. Python学习笔记:通过Headers字段模拟浏览器访问亚马逊界面爬取