搬砖小弟
GraphQL学习笔记
2019-06-24 / 5 min read

GraphQL是什么?

GraphQl官方的定义是:

GraphQL是一种API的查询语言。 它用于运行时完成数据查询。 GraphQL服务与传输无关,但通常通过HTTP提供。

GraphQl特性

  • GraphQL query, 只请求需要的数据
  • GraphQL schema, 在服务器端定义了api的数据结构
  • 可以在一个请求中获取多个数据,如果是rest的话, 需要访问多个接口

与REST对比,REST的缺点的主要有以下:

  • Overfetching 往往会给客户端返回过多的数据
  • endpoints过多,管理endpoints是个问题。Endpoints修改,客户端也需要修改。

GraphQL只是一种协议, 官方提供了多种实现。如java, javascript.

GraphQL中的类型

  • scalar type

    GraphQL的Scalar Type有Int, String, Float, Boolean, ID

  • object type

  • Fragments

    fragment liftInfo on Lift {
      name
      status
      capacity
      night
      elevationGain
    }
    
    query {
        Lift(id: "jazz-cat") {
          ...liftInfo
          trailAccess {
            name
            difficulty
          }
        }
        Trail(id: "river-run") {
          name
          difficulty
          accessedByLifts {
            ...liftInfo
          }
        }
    }
    

    The fragment in this example is named liftInfo, and it is a selection set on the Lift type.

  • union type

    union AgendaItem = StudyGroup | Workout
    
    type StudyGroup {
        name: String!
        subject: String
        students: [User!]!
    }
    
    type Workout {
        name: String!
        reps: Int!
    }
    
    type Query {
        agenda: [AgendaItem!]!
    }
    
    
  • interface

    Interfaces are another option when dealing with multiple object types that could be returned by a single field. An interface is an abstract type that establishes a list of fields that should be implemented in similar object types. When another type implements the interface, it includes all of the fields from the interface and usually some of its own fields.

    interface AgendaItem {
        name: String!
        start: DateTime!
        end: DateTime!
    }
    
    type StudyGroup implements AgendaItem {
        name: String!
        start: DateTime!
        end: DateTime!
        participants: [User!]!
        topic: String!
    }
    
    type Workout implements AgendaItem {
        name: String!
        start: DateTime!
        end: DateTime!
        reps: Int!
    }
    
    type Query {
        agenda: [AgendaItem!]!
    }
    
  • enums

    enum PhotoCategory {
        SELFIE
        PORTRAIT
        ACTION
        LANDSCAPE
        GRAPHIC
    }
    
    type Photo {
        id: ID!
        name: String!
        url: String!
        description: String
        created: DateTime!
        category: PhotoCategory!
    }
    

GraphQL的Java使用

源码地址:https://github.com/caijh/samples/tree/master/sample-graphql

  1. 引入maven依赖

    <dependency>
        <groupId>com.graphql-java</groupId>
        <artifactId>graphql-java</artifactId>
        <version>11.0</version>
    </dependency>
    <dependency>
    <dependency>
                <groupId>com.graphql-java</groupId>
                <artifactId>graphql-spring-boot-starter</artifactId>
                <version>5.0.2</version>
     </dependency>
            <dependency>
                <groupId>com.graphql-java</groupId>
                <artifactId>graphql-java-tools</artifactId>
                <version>5.2.4</version>
            </dependency>
    <dependency>
        <groupId>com.graphql-java</groupId>
        <artifactId>graphiql-spring-boot-starter</artifactId>
        <version>5.0.2</version>
    </dependency>
    
  2. 建立表

    create table `author` (
    	id bigint primary key auto_increment,
        name varchar(45) not null,
        birthday datetime default null
    ) engine = InnoDB default charset=utf8 comment '作者';
    
    create table `article` (
    	id bigint primary key auto_increment,
        title varchar(100) not null,
        author_id bigint not null,
        content text not null
    ) engine = InnoDB default charset = utf8 comment '文章';
    
    
  3. 创建graphqls

    schema.graphql

    scalar Date
    
    type Query {
    
    }
    
    type Mutation {
    
    }
    

    author.graphqls

    extend type  Query {
        findAuthorById(id: Int): Author
    }
    
    extend type Mutation {
        newAuthor(name: String, birthday: Date): Boolean
    }
    
    type Author {
        id: ID
        name: String
        birthday: Date
    }
    
    

    article.graphqls

    extend type Query {
        findArticleById(id: Int) : Article
    }
    
    extend type Mutation {
        newArticle(title: String, content: String, authorId: Int): Boolean
    }
    
    type Article {
        id: ID
        title: String
        content: String
        authorId: Int
    }
    
  4. 创建Query和Mutation

    package com.coding.sample.graphql.component;
    
    import com.coding.sample.graphql.entity.Article;
    import com.coding.sample.graphql.entity.Author;
    import com.coding.sample.graphql.mapper.ArticleMapper;
    import com.coding.sample.graphql.mapper.AuthorMapper;
    import com.coxautodev.graphql.tools.GraphQLQueryResolver;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class Query implements GraphQLQueryResolver {
    
        @Autowired
        private AuthorMapper authorMapper;
        @Autowired
        private ArticleMapper articleMapper;
    
        public Author findAuthorById(Long id) {
            return authorMapper.selectByPrimaryKey(id);
        }
    
        public Article findArticleById(Long id) {
            return articleMapper.selectByPrimaryKey(id);
        }
    
    }
    
    package com.coding.sample.graphql.component;
    
    import java.util.Date;
    
    import com.coding.sample.graphql.entity.Article;
    import com.coding.sample.graphql.entity.Author;
    import com.coding.sample.graphql.mapper.ArticleMapper;
    import com.coding.sample.graphql.mapper.AuthorMapper;
    import com.coxautodev.graphql.tools.GraphQLMutationResolver;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class Mutation implements GraphQLMutationResolver {
    
        @Autowired
        private AuthorMapper authorMapper;
        @Autowired
        private ArticleMapper articleMapper;
    
        public boolean newAuthor(String name, Date birthday) {
            Author author = new Author();
            author.setName(name);
            author.setBirthday(birthday);
            return authorMapper.insert(author) > 0;
        }
    
        public boolean newArticle(String title, String content, Long authorId) {
            Article article = new Article();
            article.setTitle(title);
            article.setContent(content);
            article.setAuthorId(authorId);
            articleMapper.insert(article);
            return true;
        }
    
    }
    
  5. 测试