GraphQl入门及深化知识总结

参考资料总结:

  • Resolver及Playground整合SpringBoot参考视频(后续作者还会跟进)
  • 所有的课程参考资料
  • Graphql官方文档(如果你有闲心或者想详细研究可以看看)
  • Graphql官方文档汉化版
  • Graphql-java文档(主要参考这个,里面详细介绍了怎么整合spring-boot)
  • 下面是几个写的比较好的博文
  • SDL方式整合SpringBoot
  • 非SDL方式整合SpringBoot
  • SDL和非SDL两种实现方式的总结
  • 关于自定义标量的拓展
  • SpringBoot整合多个Graphqls文件
  • 以及graphqls标量的介绍
  • 标量介绍以及resolver-provider方式

大致介绍:

  • Graphqls-java阶段 一般有三个重要的文件Resolver、Fetcher和Provider
  • 简单来说  dataFetchingEnvironment  就是获取架构中的变量  可以是指明的ID或者是通过getSource获取的上次提交的对象
  • 其中Resolver或Fetcher负责将graphqls文件进行解析,graphqls文件更像是一个接口,只指定了入参和回参,并没有具体的实现方式,在相应jar包的作用下,被resolver或者Fetcher文件解析,并实现graphqls里面的接口,然后resolver或fetcher被provider所整合,统一的注入到graphql变量中,然后被其他地方调用(绝大部分情况是controller),进行相关的操作。所以provider的存在对于Controller能否调用到graphql有着至关重要的作用。下面是一些图片说明:

GraphQl入门及深化知识总结_第1张图片

 GraphQl入门及深化知识总结_第2张图片

 GraphQl入门及深化知识总结_第3张图片

GraphQl入门及深化知识总结_第4张图片

  •  关于graphqls,  如果要通过provider整合graphqls,就必须有一个根文件 ,其他文件的query或者mutation类型都必须继承该根文件的类型才行,如果没有provider,那么多个根文件也可,它们的结构大概如下

GraphQl入门及深化知识总结_第5张图片  

  • 下面将分SDL方式和非SDL方式,两种方式进行讲解

注意事项:

  • 编译器  对于graphql后缀不会显示的报错  但是有时会出现启动错误  所以  一定要graphqls结尾
  • yml文件中尽量不要用中文注释  会报错  因为汉字一个字符占用两个字节,经常解析错误

各种框架的优缺点及搭建样例(resolver,resolver-provider,fetcher-provider)我做成文档了,欢迎下载查看


resolver方式的框架配置教程:

  • 主要来自于上述的参考视频以及一些文章的总结
  • 下面是整合SpringBoot过程:
  • 如果需要使用数据库及mybatis等,可以参考
  • 下面是一个不包含数据库的简易的例子,需要下载见参考demo
  • 利用idea,创建项目

GraphQl入门及深化知识总结_第6张图片

 GraphQl入门及深化知识总结_第7张图片

  • 创建好项目后,然后向pom中添加依赖,其中 ${graphql.version} 为 11.1.0

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            com.graphql-java-kickstart
            graphql-spring-boot-starter
            ${graphql.version}
        
        
        
            com.graphql-java-kickstart
            playground-spring-boot-starter
            ${graphql.version}
            runtime
        
        
        
            com.graphql-java-kickstart
            voyager-spring-boot-starter
            ${graphql.version}
            runtime
        
        
            org.hibernate.validator
            hibernate-validator
        
  • 在yml文件中添加以下内容,注意中文注释记得去掉,不然会出错
server:
  port: 8099
  servlet:
    multipart:
      max-file-size: 4MB
graphql:
  servlet:
    maxQueryDepth: 64
    exception-handlers-enabled: false
  playground:
    #enabled: false
    headers:
      Authorization: Bearer TOKEN_XYZ
    tabs:
      - name: mutationOP
        query: classpath:playground\mutationOP.graphqls
        variables: classpath:playground/mutationOP_variables.json
      - name: queryOP
        query: classpath:playground\queryOP.graphqls
        variables: classpath:playground/queryOP_variables.json
#voyager:
#  enabled: false

GraphQl入门及深化知识总结_第8张图片

  • 然后在resources文件夹下,创建playground文件夹,根据配置文件添加如下文件mutationOP.graphqls
# 查询样例,playground前端的默认显示
#下面的ID位于json中
mutation MUTATION_OP($num: NonNegativeInt) {
    #调用query.graphqls里面的方法进行
    #如果要调用其他的  需要手写在play ground里面
#    bankAccount(id: $num) {
#        name
#    }

    #然后着手加  增加操作

    createOrdes(num: $num) {
            msg
        }
}

mutationOP_variables.json

{
  "num": 15
}

queryOP.graphqls

query QUERY_OP{
    getOrders {
        msg
    }
}

queryOP_variables.json 

{
  "num": 15
}
  • 然后resource文件夹下,创建graphql文件夹,添加如下文件mutationOP.graphqls

mutationOP.graphqls

# 该服务器支持的所有查询   对应的类MutationOPResolver  实现GraphQLMutationResolver接口
type Mutation {
    createOrdes(num:NonNegativeInt ):R
}

queryOP.graphqls

# 该服务器支持的所有查询   对应的类BankAccountResolver  实现GraphQLQueryResolver接口

type Query {
    #查询所有订单的信息  对于不全的信息  给与提示
    getOrders: R
}
  • 然后在graphql文件夹下创建bank文件夹  添加如下文件

bankAccount.graphqls

type BankAccount {
    id: ID!
    name: String!
    currency: Currency!
}

currency.graphqls

# 支持的币种
enum Currency {
    RMB,
    USD
}

Res.graphqls

scalar NonNegativeInt


type R{
    code :NonNegativeInt
    msg  :String
}
  • 此时的项目结构为:

GraphQl入门及深化知识总结_第9张图片

  • 然后添加代码部分
  • 创建config文件夹 ,添加如下代码

ScalaConfig.java

package com.example.demo.config;

import graphql.scalars.ExtendedScalars;
import graphql.schema.GraphQLScalarType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ScalaConfig {
    @Bean
    public GraphQLScalarType nonNegativeInt() {
        return ExtendedScalars.NonNegativeInt;
    }

}
  • 创建resolver文件夹添加代码如下

MutationOPResolver.java

package com.example.demo.resolver;

import com.example.demo.entity.R;
import com.example.demo.entity.orderData;
import graphql.kickstart.tools.GraphQLMutationResolver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class MutationOPResolver implements GraphQLMutationResolver {

    //根据输入的量  进行
    public R createOrdes(Integer num){
        log.info("进入订单创建的方法, 参数为 {}", num);
        orderData.createOrders(num);
        return R.builder()
                .msg("创建成功,订单的数量为: "+orderData.getData().size())
                .build();
    }
}

QueryOPResolver.java

package com.example.demo.resolver;

import com.example.demo.entity.BankAccount;
import com.example.demo.entity.Currency;
import com.example.demo.entity.R;
import com.example.demo.entity.orderData;
import graphql.kickstart.tools.GraphQLQueryResolver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Slf4j
@Component
public class QueryOPResolver implements GraphQLQueryResolver {

    public R getOrders() {
        log.info("查询所有的数据");
        return R.builder().msg(orderData.getData().toString()).build();
    }

}
  • 创建entity文件夹添加代码如下

BankAccount.java

package com.example.demo.entity;

import lombok.Builder;
import lombok.Value;

import java.util.UUID;

@Builder
@Value
public class BankAccount {
    UUID id;
    String name;
    Currency Currency;
}

Commodity.java

package com.example.demo.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.Value;

//商品信息
@Builder
@Value
public class Commodity {
    String name;
    Integer num;
}

Currency.java

package com.example.demo.entity;

public enum Currency {
    RMB,
    USD
}

Logistics.java

package com.example.demo.entity;

import lombok.Builder;
import lombok.Value;

//物流信息
@Builder
@Value
public class Logistics {
    String orderNum;
    String company;
}

Order.java

package com.example.demo.entity;

import lombok.Builder;
import lombok.Value;

//订单信息
@Builder
@Value
public class Order {
    private Commodity commodity;
    private Logistics logistics;
}

orderData.java

package com.example.demo.entity;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

// 用于模拟数据库  存储订单信息  注意要存储的不完善  以测试  其他功能
public  class orderData {
    private static List orders  = new ArrayList<>();

    public static List  getData(){
        return orders;
    }

    public static void createOrders(Integer num){
        //创造订单数据  单数的是不全的  双数的是全的
        for (Integer i = 0; i < num; i++) {
            if(i%2 == 0){
                //创造全的订单信息
                orders.add(allOfInfo());
            }
            else{
                //创造不全的订单信息
                orders.add(partOfInfo());
            }
        }
    }
    //创造全的订单信息
    private static Order allOfInfo(){
        Commodity commodity = Commodity.builder().name(getStr(5)).num(getNum()).build();
        Logistics logistics = Logistics.builder().company(getStr(8)).orderNum(getStr(16)).build();
        return Order.builder().commodity(commodity).logistics(logistics).build();
    }
    //创造不全的订单信息
    private static Order partOfInfo(){
        //只有商品信息  没有物流信息
        Commodity commodity = Commodity.builder().name(getStr(5)).num(getNum()).build();
        return Order.builder().commodity(commodity).logistics(null).build();
    }

    //创造不同位数的UUID
    private static String getStr(Integer num){
        String uuid = UUID.randomUUID().toString().replaceAll("-","").toUpperCase();
        return uuid.substring(0,num);
    }
    //生成0~100的随机数
    private static Integer getNum(){
        Random r = new Random(1);
        return r.nextInt(100);
    }
}

R.java

package com.example.demo.entity;

import lombok.Builder;
import lombok.Value;

@Builder
@Value
public class R {
    Integer code;
    String msg;
}
  • 如果想启动自动访问仪表盘,还可以在启动类中添加
@SpringBootApplication
public class GraphqlDemoApplication {

    public static void main(String[] args) {
        int port = 8099;
        String playGround = "/playground";
        String voyager = "/voyager";
        String portPrefix = "--server.port=";
        for (String arg : args) {
            if (arg.startsWith(portPrefix)) {
                port = Integer.parseInt(arg.substring(portPrefix.length()));
            }
        }
        SpringApplication.run(GraphqlDemoApplication.class, args);
        try {
            Runtime.getRuntime().exec("cmd /c start http://localhost:" + port+playGround);
            Runtime.getRuntime().exec("cmd /c start http://localhost:" + port+voyager);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
  • 如果需要结合自定义网页进行,demo总也提供了controller文件夹和resources文件夹下的templates文件,欢迎参考

基础提升:

  • 上述仅仅是对graphql基本的整合,如果需要更丰富的功能可以参照视频

GraphQl入门及深化知识总结_第10张图片


你可能感兴趣的:(开发文档,框架搭建,graphql,后端)