• GraphQL入门


    GraphQL入门

    GraphQL 是由 Facebook 创造的用于描述复杂数据模型的一种查询语言。这里查询语言所指的并不是常规意义上的类似 sql 语句的查询语言,而是一种用于前后端数据查询方式的规范。
    在这里插入图片描述

    GraphQL查询的规范

    字段(Fields)在GraphQL的查询中,请求结构中包含了所预期结果的结构,这个就是字段。并且响应的结构和请求结构基本一致,这是GraphQL的一个特性,这样就可以让请求发起者很清楚的知道自己想要什么。
    在这里插入图片描述
    参数(Arguments)在查询数据时,离不开传递参数,在GraphQL的查询中,也是可以传递参数的,语法:(参数名:参数值)
    在这里插入图片描述
    别名(Aliases)如果一次查询多个相同对象,但是值不同,这个时候就需要起别名了,否则json的语法就不能通过了
    在这里插入图片描述
    片段(Fragments)
    查询对的属相如果相同,可以采用片段的方式进行简化定义
    在这里插入图片描述

    GraphQL的Schema 和类型规范

    Schema 是用于定义数据结构的,比如说,User对象中有哪些属性,对象与对象之间是什么关系等。
    Schema定义结构

    schema { #定义查询
    query: UserQuery
    }
    type UserQuery { #定义查询的类型
    user(id:ID) : User #指定对象以及参数类型
    }
    type User { #定义对象
    id:ID! # !表示该属性是非空项
    name:String
    age:Int
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    标量类型(Scalar Types)
    GraphQL规范中,默认定义了5种类型:
    Int :有符号 32 位整数。
    Float :有符号双精度浮点值。
    String :UTF‐8 字符序列。
    Boolean : true 或者 false 。
    ID :ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。
    规范中定义的这5种类型,显然是不能满足需求的,所以在各种语言实现中,都有对类型进行了扩充,也就是GraphQL支持自定义类型,比如在graphql-java实现中增加了:Long、Byte等
    枚举类型
    枚举类型是一种特殊的标量,它限制在一个特殊的可选值集合内

    enum Episode { #定义枚举
    NEWHOPE
    EMPIRE
    JEDI
    }
    type Human {
    id: ID!
    name: String!
    appearsIn: [Episode]! #使用枚举类型
    homePlanet: String
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    接口(interface)
    跟许多类型系统一样,GraphQL 支持接口。一个接口是一个抽象类型,它包含某些字段,而对象类型必须包含这些字段,才能算实现了这个接口。例如,你可以用一个 Character 接口用以表示《星球大战》三部曲中的任何角色:

    interface Character { #定义接口
    id: ID!
    name: String!
    friends: [Character]
    appearsIn: [Episode]!
    }
    #实现接口
    type Human implements Character {
    id: ID!
    name: String!
    friends: [Character]
    appearsIn: [Episode]!
    starships: [Starship]
    totalCredits: Int
    }
    type Droid implements Character {
    id: ID!
    name: String!
    friends: [Character]
    appearsIn: [Episode]!
    primaryFunction: String
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    GraphQL的Java实现

    通过前面的讲解,我们对GraphQL有了解,官方只是定义了规范并没有做实现,就需要有第三方来进行实现了,关于GraphQL的java实现有几种,我们选择使用官方推荐的实现:graphql-java,我们通过该实现就可以编写GraphQL的服务端了。

    开始使用

    创建工程工程名:itcast-graphql-java-2
    导入依赖:

     <dependency>
                <groupId>com.graphql-javagroupId>
                <artifactId>graphql-javaartifactId>
                <version>11.0version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    说明:graphql-java包并没有发布到maven中央仓库,需要配置第三方仓库才能使用。
    在setting.xml文件里进行配置:

        <profile>
          <id>bintrayid>
          <repositories>
          <repository>
          <id>bintrayid>
          <url>http://dl.bintray.com/andimarek/graphql-javaurl>
          <releases>
          <enabled>trueenabled>
          releases>
          <snapshots>
          <enabled>falseenabled>
          snapshots>
          repository>
          repositories>
          <pluginRepositories>
          <pluginRepository>
          <id>bintrayid>
          <url>http://dl.bintray.com/andimarek/graphql-javaurl>
          <releases>
          <enabled>trueenabled>
          releases>
          <snapshots>
          <enabled>falseenabled>
          snapshots>
          pluginRepository>
          pluginRepositories>
        profile>
    
      <activeProfiles>
        <activeProfile>bintrayactiveProfile>
      activeProfiles>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    创建User对象

    package cn.itcast.graphql.vo;
    
    public class User {
    
        private Long id;
        private String name;
        private Integer age;
        private Card card;
    
        public User() {
        }
    
        public User(Long id, String name, Integer age, Card card) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.card = card;
        }
    
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Integer getAge() {
            return age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
        public Card getCard() {
            return card;
        }
        public void setCard(Card card) {
            this.card = card;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    编写查询User对象实现

    schema {
        query: UserQuery
    }
    type UserQuery {
        user(id:Long) : User
    }
    type User {
        id:Long!
        name:String
        age:Int
        card:Card
    }
    
    type Card{
        cardNumber:String
        userId:Long
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    Java实现:

    package cn.itcast.graphql.demo;
    
    import cn.itcast.graphql.vo.User;
    import graphql.ExecutionResult;
    import graphql.GraphQL;
    import graphql.schema.GraphQLFieldDefinition;
    import graphql.schema.GraphQLObjectType;
    import graphql.schema.GraphQLSchema;
    
    import static graphql.Scalars.*;
    import static graphql.schema.GraphQLArgument.newArgument;
    import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
    import static graphql.schema.GraphQLObjectType.newObject;
    
    public class GraphQLDemo {
    
        public static void main(String[] args) {
    
            /**
             * type User { #定义对象}
             */
            GraphQLObjectType userObjectType = newObject()
                    .name("User")
                    .field(newFieldDefinition().name("id").type(GraphQLLong))
                    .field(newFieldDefinition().name("name").type(GraphQLString))
                    .field(newFieldDefinition().name("age").type(GraphQLInt))
                    .build();
    
            /**
             * user : User #指定对象以及参数类型
             */
            GraphQLFieldDefinition userFieldDefinition = newFieldDefinition()
                    .name("user")
                    .type(userObjectType)
                    .argument(newArgument().name("id").type(GraphQLLong).build())
                    .dataFetcher(environment -> {
                        Long id = environment.getArgument("id");
                        // 查询数据库了
                        // TODO 先模式实现
                        return  new User(id, "张三:"+id, 20+id.intValue(), null);
                    })
    //                .dataFetcher(new StaticDataFetcher(new User(1L, "张三", 20)))
                    .build();
    
            /**
             * type UserQuery { #定义查询的类型}
             */
            GraphQLObjectType userQueryObjectType = newObject()
                    .name("UserQuery")
                    .field(userFieldDefinition)
                    .build();
    
            /**
             * schema { #定义查询 }
             */
            GraphQLSchema graphQLSchema = GraphQLSchema.newSchema().query(userQueryObjectType).build();
    
            GraphQL graphQL = GraphQL.newGraphQL(graphQLSchema).build();
    
            String query = "{user(id:100){id,name}}";
            ExecutionResult result = graphQL.execute(query);
    
            System.out.println("query:" + query);
    //        System.out.println(result.getErrors());
    //        System.out.println(result.getData());
    
            System.out.println(result.toSpecification());
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    运行结果:
    query:{user(id:100){id,name}}
    {data={user={id=100, name=张三:100}}}
    在这里插入图片描述

    如果运行错误提示:Error:(36, 42) java: -source 1.5 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式)
    那原因就是在用maven编译项目是由于项目中用了jdk 1.8, 编译是报错 -source 1.5 中不支持 lambda 表达式。在pom.xml中添加如下代码,使用支持JDK1.8的maven插件

    <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.pluginsgroupId>
                    <artifactId>maven-compiler-pluginartifactId>
                    <version>3.2version>
                    <configuration>
                        <source>1.8source>
                        <target>1.8target>
                    configuration>
                plugin>
            plugins>
        build>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    使用SDL构建schema

    graphql-java 提供了两种不同的方式来定义模式:以编程方式作为Java代码或通过特殊的graphql dsl(称为SDL)。
    在resources目录下创建user.graphqls文件:

    schema {
        query: UserQuery
    }
    type UserQuery {
        user(id:Long) : User
    }
    type User {
        id:Long!
        name:String
        age:Int
        card:Card
    }
    
    type Card{
        cardNumber:String
        userId:Long
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    安装GraphQL插件:
    在这里插入图片描述
    构建schema

    package cn.itcast.graphql.demo;
    
    import cn.itcast.graphql.vo.Card;
    import cn.itcast.graphql.vo.User;
    import graphql.ExecutionResult;
    import graphql.GraphQL;
    import graphql.schema.GraphQLSchema;
    import graphql.schema.idl.RuntimeWiring;
    import graphql.schema.idl.SchemaGenerator;
    import graphql.schema.idl.SchemaParser;
    import graphql.schema.idl.TypeDefinitionRegistry;
    import org.apache.commons.io.IOUtils;
    
    import java.io.IOException;
    
    public class GraphQLSDLDemo {
    
        public static void main(String[] args) throws IOException {
    
            // 读取GraphQL文件,进行解析
            String fileName = "user.graphqls";
            String fileContent = IOUtils.toString(GraphQLSDLDemo.class.getClassLoader().getResource(fileName), "UTF-8");
            TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(fileContent);
    
            // 解决的是数据的查询
            RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring()
                    .type("UserQuery", builder ->
                            builder.dataFetcher("user", environment -> {
                                Long id = environment.getArgument("id");
                                Card card = new Card("123456789", id);
                                return new User(id, "张三:" + id, 20 + id.intValue(), card);
                            })
                    )
                    .build();
    
            // 生成Schema
            GraphQLSchema graphQLSchema = new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring);
    
            // 根据Schema对象生成GraphQL对象
            GraphQL graphQL = GraphQL.newGraphQL(graphQLSchema).build();
    
            String query = "{user(id:100){id,name,age,card{cardNumber}}}";
            ExecutionResult result = graphQL.execute(query);
    
            System.out.println("query:" + query);
            System.out.println(result.toSpecification());
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    在这里插入图片描述

    运行结果
    在这里插入图片描述

    源代码

    链接:https://pan.baidu.com/s/14Zyl54BbYjWwQdIzwuzNpg?pwd=16kf
    提取码:16kf
    –来自百度网盘超级会员V3的分享

  • 相关阅读:
    数据库的备份和恢复
    ubuntu离线编译安装cmake 3.22.5(could not fonud OPENSSL) and cmake-versinon查不到版本问题
    NLog配置文件详解
    springboot基于BS结构的企业人事管理系统的设计与实现毕业设计源码121727
    mysql图书管理系统(49-56)源代码
    《30天吃掉那只 TensorFlow2.0》 2-3 自动微分机制
    UE基础必学系列:UMG
    从Spring中学到的--读懂继承链
    Canvas 图片上传,JAVA后端使用 MultipartFile 接收
    leetcode每日一题——Split With Minimum Sum
  • 原文地址:https://blog.csdn.net/peacezhi/article/details/126103733