zoukankan      html  css  js  c++  java
  • GraphQL介绍以及在Spring Boot/Cloud项目中搭建GraphQL并测试

    GraphQL what & why

    GraphQL是一种API查询语言,它是一种动态的API查询方式,同一个API可以返回不同的结果。

    普通的REST请求是预先定义好的,前端需要什么数据会和后端讲,然后后端开始商量好返回数据格式,然后进行开发。而GraphQL是REST的升级版,定义好某个API之后,可以用GraphQL做多种操作,比如说只需要id那么可以在调用的时候指明只返回id,如果需要id, name, comments….等等,也可以指定。因此,它查询的结果是动态的,这样可以降低前后端的耦合。

     

    官方解释:

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

     

    为什么要用GraphQL

    1. 强类型的schema

    它请求的结构和返回的结构很相似,可以很直观的设置参数并预知返回结果。

    1. 按需获取,节省网络负载,提高页面加载速度

    比如我只要id和name那么我指定一下,它就只返回id和name,而不会像API一样返回一堆没有用的数据(现在的VDM 有些查询的API会把所有引用到的对象的信息都查出来)

    1. 特别适用于结构固定,数据模型清晰的业务场景

    比如我们的VDM,里面基本都是数据库相应表的增删改查,不会有其他系统对接或特殊的逻辑处理,使用GraphQL就好像前端直接在操作数据库。

    1. 支持快速产品开发

    GraphQL的schema是用配置文件xxx.graphqls定义,里面定义了各种接口名、参数和返回对象,然后在所有实现了GraphQLQueryResolver, GraphQLMutationResolver的类中去做具体的操作。

    只要后端将schema定义好之后,前端便可开始工作。

    5.可以使用内联查询将多个API的信息拼接一次返回。

    6.  活跃的社区

    7.  GitHub 最新的v4版本API已经完全采用GraphQL

     

    GraphQL的Type:

    两种,一种是标量类型(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的查询和变更:

    在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 对象类型是一样的,它们的字段也是一样的工作方式。

     

     

    在Spring Boot/Cloud项目中使用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

    然后左边框输入查询语句,左下角是入参的声明和指定值,点击播放按钮,右边会显示结果。

     

     

  • 相关阅读:
    《Effective C#》读书笔记——了解.NET内存管理机制<.NET资源管理>
    《Effective C#》读书笔记——条目13:正确地初始化静态成员变量<.NET资源管理>
    用创新和务实的精神开创反洗钱检查工作的新局面
    《谈谈具有中国特色的“全能型”程序员》(2009/12/11)
    EOM与程序员话题的开场白(2009/12/07)
    从事反洗钱工作要有一定的高度
    程序员漫谈(2009/12/08)
    怎样快速确定程序员编程的水平(2009/12/10)
    重视或应付!当前金融机构反洗钱面临的一个问题
    反洗钱法律法规
  • 原文地址:https://www.cnblogs.com/cnsec/p/13407121.html
Copyright © 2011-2022 走看看