第一章: GraphQL 与gqlgen

1,631 阅读4分钟

 1、什么是 GraphQL

        GraphQL是一个开源的,面向API而创造出来的数据查询操作语言以及相应的运行环境。于2012年仍处于Facebook内部开发阶段,直到2015年才公开发布。 2018年11月7日,Facebook将GraphQL项目转移到新成立的GraphQL基金会(隶属于非营利性的Linux基金会)。

        GraphQL相较于REST以及其他web service架构提供了一种更加高效、强大和灵活的开发web APIs的方式。它通过由客户端根据所需定义数据结构,同时由服务端负责返回相同数据结构的对应数据的方式避免了服务端大量冗余数据的返回,但与此同时也意味着这种方式不能有效利用起查询结果的web缓存。GraphQL这种查询语言所带来的灵活性和丰富性的同时也增加了复杂性,导致简单的APIs有可能并不适合这种方式。

2、为什么我在重构时,想选用GraphQL

     YEE工资管理系统,一开始使用的是REST方案,REST有优点,也有缺点,对于我个人来说,它的缺点就是,很难描述好关系,通常url会变得复杂难懂,又长又臭。比如对于工资管理系统来说,想取得一个员工的所有数据 ,可能需要请求很多次http,才能组合成最终想要的数据 。而且无法定制数据 ,每次都是全部取出来 。

  比如如下REST:

/profile/:id   取得该员工的基本信息
/profile/:id/department 取得该员工所在部门
/profile/:id/salary  取得该员工的工资信息

类似以上这种信息,先取得员工的基本信息,用ID 去取得员工的工资单,还要显示出员工的部门信息。当然在真实的系统里没有这么简单,这里只是举个例子。

而转为graphsql 的话,就类似以下这样:

query profile{
   profile(filter:{id:10086}){
    total
    skip
    take
    rows{
      id 
      name
      picture
      #不需要的信息可以省略,rest方案的话,就会把profile的全部信息都请求回来了,对带宽是一种浪费
      department {
        id
        name
        #不需要的信息可以省略
      }
      
      salary {
        total 
        # 想要的数据随时添加
      }
    }
  }
}

对于工资管理系统这种管理数据的应用系统,我觉得,graphql还是很符合其使用场景的。

3、golang应该如何跟graphql结合?

    以前花了好多时间去选库,直到发现 github.com/99designs/g… 这个库,感觉完全改变了我组织代码的习惯。

    在这里,我简单说一下,gqlgen该如何使用

   (1) 安装

 go get github.com/99designs/gqlgen

   (2)初始化

go run github.com/99designs/gqlgen init.

   (3)编辑gqlgen.yml 

然后,在你的golang项目根目录里,会出现gqlgen.yml的文件,里面的内容大概如下:

   schema:    - graph/schema/*.graphqls
    #  graphql 的schema定义目录, 存放于graph/schema/里,*是通配符  
   exec:    
        filename: graph/generated/generated.go    
        package: generated  
   model:    
        filename: graph/model/models_gen.go    
        package: model  
   resolver:    
        layout: follow-schema    
        dir: graph    
        package: graph  
   autobind:    - "gohr/models"  
   omit_slice_element_pointers: true  
   models:    
        Glossary:   #这是我们系统里的一个model,      
            fields:        
                user:    # 定义在这里的原因是,我们希望user \chapter\word 强制生成resolver .后来你就会知道它的作用          
                    resolver: true        
                chapter:          
                    resolver: true        
                word:          
                    resolver: true   

   (4) 编写graphql文件

    新建一个目录,graph/schema/

    新建一个文件,app.graphqls

directive @hasRole(resolver: String!) on INPUT_FIELD_DEFINITION    | FIELD_DEFINITION
directive @needLogin(resolver: String!) on INPUT_FIELD_DEFINITION    | FIELD_DEFINITION


input Pagination {    skip: Int!    take: Int!} 

type LoginResponse {    token:String!    permissions:[String!]!}

input LoginInput {    username:String    email:String!    password:String!}

input LogoutInput {    username:String    email:String!}

input ResetPasword {    ids:[Int!]!}

type Mutation {    login(input:LoginInput!):LoginResponse!    

logout(input:LogoutInput!):Boolean!}

如上graphsql文件,只是一个很基本的,定义了login 和logout .

我定义了两个directive,是为了做权限控制所用,现在先不用管它,看到后面就会怎么使用。

(5) 生成代码

PS E:\project\gohr>  go run github.com/99designs/gqlgen generate .

会生成如下文件:

如上图,代码是gqlgen自动生成的,我们只要把panic(fmt.Errorf("not implemented"))的地方找出来 ,然后填入自己的代码即可,感觉是不是很想是在填空?

这也是为什么我说的,完全改变了我写代码的方案。在用了graphql之后,我会先去构思 graphql的定义文件,想清楚一个model的构成,需要什么的数据 ,需要什么样的操作。在定义好graphql文件之后 ,由gqlgen生成,之后 ,我们只需要去填空就行了。

(6) 验证数据API 

http://localhost:20191/playground

验证数据 真的很方便。

好晚,准备睡觉,接下来再准备写系统的权限控制的思路。

                                    

                                               个人主页: YEE领域

                                   背单词Flutter APP: 领域英语APP