GraphQL是一种API查询语言,它是一种动态的API查询方式,同一个API可以返回不同的结果。
普通的REST请求是预先定义好的,前端需要什么数据会和后端讲,然后后端开始商量好返回数据格式,然后进行开发。而GraphQL是REST的升级版,定义好某个API之后,可以用GraphQL做多种操作,比如说只需要id那么可以在调用的时候指明只返回id,如果需要id, name, comments….等等,也可以指定。因此,它查询的结果是动态的,这样可以降低前后端的耦合。
官方解释:
GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。
为什么要用GraphQL?
它请求的结构和返回的结构很相似,可以很直观的设置参数并预知返回结果。
比如我只要id和name那么我指定一下,它就只返回id和name,而不会像API一样返回一堆没有用的数据(现在的VDM 有些查询的API会把所有引用到的对象的信息都查出来)
比如我们的VDM,里面基本都是数据库相应表的增删改查,不会有其他系统对接或特殊的逻辑处理,使用GraphQL就好像前端直接在操作数据库。
GraphQL的schema是用配置文件xxx.graphqls定义,里面定义了各种接口名、参数和返回对象,然后在所有实现了GraphQLQueryResolver, GraphQLMutationResolver的类中去做具体的操作。
只要后端将schema定义好之后,前端便可开始工作。
5.可以使用内联查询将多个API的信息拼接一次返回。
6. 活跃的社区
7. GitHub 最新的v4版本API已经完全采用GraphQL
两种,一种是标量类型(Scalar Type)一种是对象类型(Object Type)。有点类似java中的基本数据类型和对象类型。
GraphQL 自带一组默认标量类型:
Int:有符号 32 位整数。
Float:有符号双精度浮点值。
String:UTF‐8 字符序列。
Boolean:true 或者 false。
ID:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型。
大部分的 GraphQL 服务实现中,都有自定义标量类型的方式。例如,我们可以定义一个 Date 类型:
scalar Date
然后就取决于我们的实现中如何定义将其序列化、反序列化和验证。例如,你可以指定 Date 类型应该总是被序列化成整型时间戳,而客户端应该知道去要求任何 date 字段都是这个格式。
枚举类型(Enumeration Types)是一种特殊的标量,它限制在一个特殊的可选值集合内。这让你能够:
验证这个类型的任何参数是可选值的的某一个
与类型系统沟通,一个字段总是一个有限值集合的其中一个值。
下面是一个用 GraphQL schema 语言表示的 enum 定义:
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
接口类型是特殊的对象类型,一个对象类型继承了某个接口,就必须包含这个接口里面的所有字段。比如下面:
interface BaseResponseVO {
status:String
version:String
httpCode:Int
}
type TypeResponse implements BaseResponseVO {
status:String
version:String
statusDesc:String
httpCode:Int
data:[Type]
}
在GraphQL的schema中有两个特殊类型:
schema {
query: Query
mutation: Mutation
}
这是所有schema的入口,后面写的schema需要继承这两个类型。
Query 表示查询的入口,专门展示数据的
Mutation 是变更的入口,做增删改的。
每一个 GraphQL 服务都至少有一个 query
类型,可能有一个 mutation
类型。这两个类型和常规对象类型无差,但是它们之所以特殊,是因为它们定义了每一个 GraphQL 查询的入口。因此如果你看到一个像这样的查询:
那表示这个 GraphQL 服务需要一个 Query 类型,且其上有 hero 和 droid 字段:
type Query {
hero(episode: Episode): Character
droid(id: ID!): Droid
}
再来看看变更(Mutation):
变更和查询很类似,定义一些字段,然后就可以去调用并由前端定义需要返回的数据。
比如定义一个对象类型作为入参(注意所有入参的声明是input, 所有返回结果的声明是type):
input TestInput {
id:Int
name:String!
createdBy:String
}
然后定义一个返回对象:
type TestResponse {
statusCode:Int
messageCode:String
message:String
}
然后执行下面这个更新操作,语句如下:
mutation($testInput:TestInput!) {
update(testInput:$testInput) {
statusCode
messageCode
message
}
}
它的意思是:执行mutation下面的update方法,传入一个对象类型的变量$testInput作为参数,返回结果里面取statusCode, messageCode, message这三个字段。
这个变量类型也需要设置值,如果你是用的GraphiQL客户端工具,请在左下角查询变量设置区域填充值:
{
"testInput": {
"name": "testgraphql"
}
}
有必要记住的是,除了作为 schema 的入口,Query 和 Mutation 类型与其它 GraphQL 对象类型是一样的,它们的字段也是一样的工作方式。
Gradle加入下面这两个依赖:
compile group: 'com.graphql-java', name: 'graphql-spring-boot-starter', version: '4.0.0'
compile group: 'com.graphql-java', name: 'graphql-java-tools', version: '4.3.0'
加完依赖后,重新refresh一下项目,下载并resolve完之后,开始写代码:
数据库访问层(dao, repository, model)基本不需要改动,因为不管是用REST还是GraphQL这些数据库访问还是差不多的。GraphQL相当于替换了项目的视图层,有点类似SpringMVC中的controller包下面定义的接口信息,至于怎么处理业务逻辑和怎样去查询和操作数据库,这是你自己去决定的。
新建一个resolve包,然后建一个TestResolver类,这个类需要加个@Component注解,表示是Spring的bean,然后这个类需要实现GraphQLQueryResolver或者 GraphQLMutationResolver这两个接口,这两个接口里面没有任何方法,主要是GraphQL会根据这两个接口去查找相关的实现类。
如果只有查询,只需要implements GraphQLQueryResolver就好了。
如下所示:
这里面注入了一个service,所有具体的逻辑是可以在service里面去处理的,当然你也可以用resolver类代替service,将逻辑处理放在resolver里面,直接操作dao层。
在项目的resource目录下建一个graphql的文件夹,然后在里面去建graphql的schema文件:
比如建一个root.graphqls文件:
root.graphqls里面定义了Query和Mutation 的所有接口名、参数、返回信息:
Query和mutation语法格式很容易懂,[]表示是一个数组,!表示这是必要的,:后面是返回对象类型,括号里面的是入参类型。
还有一个配置文件:schema.graphqls 这个里面定义了所有的type和 input类型字段定义。
比如下面:
interface BaseResponseVO {
status:String
version:String
httpCode:Int
}
type TypeResponse implements BaseResponseVO {
status:String
version:String
httpCode:Int
data:[Type]
}
type Type {
id:Int
name:String
createUser:String
createTimestamp:String
updateUser:String
lastUpdateTimestamp:String
}
入参用Input声明,返回的类型用type声明。Input/Type都是在这个文件里面去定义的,如果Type那个对象里面还引用了其他对象,那么其他对象也要用Type去定义,直至保证所有引用到的对象类型都定义完,只有标量类型。
OK,这些做完了一个简单的GraphQL项目就跑起来了,请启动项目,然后用GraphQL的客户端程序去测试吧,客户端推荐GraphiQL, 附上下载链接:
https://electronjs.org/apps/graphiql
安装好之后,进入了这么个界面:
请在地址栏输入 http://{域名}:{项目端口号}/graphql
然后左边框输入查询语句,左下角是入参的声明和指定值,点击播放按钮,右边会显示结果。