Java 使用 Graphql 搭建查询服务详解

 更新时间:2016年12月09日 11:24:47   投稿:lqh  
这篇文章主要介绍了Java 使用 Graphql 搭建查询服务详解的相关资料,需要的朋友可以参考下

背景

随着React的开源,facebook相继开源了很多相关的项目,这些项目在他们内部已经使用了多年,其中引起我注意的就是本次讨论的是graphql,目前官方只有nodejs版,由于很多公司的后台技术栈都是Java,所以便有了graphql的java版实现,在github上可以找到,废话不多说,直接看代码吧,具体介绍还是去看官网吧,不然就跑题了。

GraphQLSchema

Schema相当于一个数据库,它有很多GraphQLFieldDefinition组成,Field相当于数据库表/视图,每个表/视图又由名称、查询参数、数据结构、数据组成.

1) 先定义一个数据结构(GraphQLOutputType)字段,然后定义一个初始化方法

private GraphQLOutputType userType;

private void initOutputType() {
   /**
    * 会员对象结构
    */
   userType = newObject()
       .name("User")
       .field(newFieldDefinition().name("id").type(GraphQLInt).build())
       .field(newFieldDefinition().name("age").type(GraphQLInt).build())
       .field(newFieldDefinition().name("sex").type(GraphQLInt).build())
       .field(newFieldDefinition().name("name").type(GraphQLString).build())
       .field(newFieldDefinition().name("pic").type(GraphQLString).build())
       .build();
}

2)再定义两个表/视图,它包括名称,查询参数,数据结构,以及数据检索器

 /**
   * 查询单个用户信息
   * @return
   */
  private GraphQLFieldDefinition createUserField() {
    return GraphQLFieldDefinition.newFieldDefinition()
        .name("user")
        .argument(newArgument().name("id").type(GraphQLInt).build())
        .type(userType)
        .dataFetcher(environment -> {
          // 获取查询参数
          int id = environment.getArgument("id");

          // 执行查询, 这里随便用一些测试数据来说明问题
          User user = new User();
          user.setId(id);
          user.setAge(id + 15);
          user.setSex(id % 2);
          user.setName("Name_" + id);
          user.setPic("pic_" + id + ".jpg");
          return user;
        })
        .build();
  }

  /**
   * 查询多个会员信息
   * @return
   */
  private GraphQLFieldDefinition createUsersField() {
    return GraphQLFieldDefinition.newFieldDefinition()
        .name("users")
        .argument(newArgument().name("page").type(GraphQLInt).build())
        .argument(newArgument().name("size").type(GraphQLInt).build())
        .argument(newArgument().name("name").type(GraphQLString).build())
        .type(new GraphQLList(userType))
        .dataFetcher(environment -> {
          // 获取查询参数
          int page = environment.getArgument("page");
          int size = environment.getArgument("size");
          String name = environment.getArgument("name");

          // 执行查询, 这里随便用一些测试数据来说明问题
          List<User> list = new ArrayList<>(size);
          for (int i = 0; i < size; i++) {
            User user = new User();
            user.setId(i);
            user.setAge(i + 15);
            user.setSex(i % 2);
            user.setName(name + "_" + page + "_" + i);
            user.setPic("pic_" + i + ".jpg");
            list.add(user);
          }
          return list;
        })
        .build();
  }

3)接着定义一个Schema,并将其初始化,它包含一个名称,以及一个或多个表/视图(Field)

 private GraphQLSchema schema;

  public GraphSchema() {
    initOutputType();
    schema = GraphQLSchema.newSchema().query(newObject()
        .name("GraphQuery")
        .field(createUsersField())
        .field(createUserField())
        .build()).build();
  }

4)完成以上步骤之后,还需要定义一个model,类名不限,但是结构需要满足前面定义的数据结构,而且必须是public的

public class User {
  private int id;
  private int age;
  private int sex;
  private String name;
  private String pic;
  // getter, setter...
}  

5)之后写一个main方法,来测试一下

public static void main(String[] args) {
    GraphQLSchema schema = new GraphSchema().getSchema();

    String query1 = "{users(page:2,size:5,name:\"john\") {id,sex,name,pic}}";
    String query2 = "{user(id:6) {id,sex,name,pic}}";
    String query3 = "{user(id:6) {id,sex,name,pic},users(page:2,size:5,name:\"john\") {id,sex,name,pic}}";

    Map<String, Object> result1 = (Map<String, Object>) new GraphQL(schema).execute(query1).getData();
    Map<String, Object> result2 = (Map<String, Object>) new GraphQL(schema).execute(query2).getData();
    Map<String, Object> result3 = (Map<String, Object>) new GraphQL(schema).execute(query3).getData();

    // 查询用户列表
    System.out.println(result1);
    // 查询单个用户
    System.out.println(result2);
    // 单个用户、跟用户列表一起查
    System.out.println(result3);

}

输出:

{users=[{id=0, sex=0, name=john_2_0, pic=pic_0.jpg}, {id=1, sex=1, name=john_2_1, pic=pic_1.jpg}, {id=2, sex=0, name=john_2_2, pic=pic_2.jpg}, {id=3, sex=1, name=john_2_3, pic=pic_3.jpg}, {id=4, sex=0, name=john_2_4, pic=pic_4.jpg}]}
{user={id=6, sex=0, name=Name_6, pic=pic_6.jpg}}
{user={id=6, sex=0, name=Name_6, pic=pic_6.jpg}, users=[{id=0, sex=0, name=john_2_0, pic=pic_0.jpg}, {id=1, sex=1, name=john_2_1, pic=pic_1.jpg}, {id=2, sex=0, name=john_2_2, pic=pic_2.jpg}, {id=3, sex=1, name=john_2_3, pic=pic_3.jpg}, {id=4, sex=0, name=john_2_4, pic=pic_4.jpg}]}

6)最后把main方法里面的代码放到web层,只需要定义一个query参数,很容易就把查询服务搭建好了,dataFetcher 里面还是调用原来的查询接口

7)引入maven依赖

<dependency>
  <groupId>com.graphql-java</groupId>
  <artifactId>graphql-java</artifactId>
  <version>2.0.0</version>
</dependency>

关于graphql查询什么定义,看看这个或许对你有帮助

json


{
  id=6, 
  sex=0, 
  name="Name_6", 
  pic="pic_6.jpg"
}

query

{
  id,
  sex,
  name,
  pic
}

后面那部分,其实就是json字符串,去掉=和value的结果,还是可读的

结语

graphql 带了一种全新的思维方式,可以简化web api的开发,由客户端指定需要什么数据,服务端返回什么数据,减少不必要的流量传输,对移动端友好,还提供多种数据聚合查询,多个查询只是用一个请求,既满足api最小粒度,又满足前端需要,减少请求,提高性能。

感觉以后会朝这方面去发展,大趋所驱。

相关文章

  • SpringCloud远程服务调用三种方式及原理

    SpringCloud远程服务调用三种方式及原理

    本文给大家介绍SpringCloud远程服务调用实战笔记,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2022-12-12
  • 轻轻松松吃透Java并发fork/join框架

    轻轻松松吃透Java并发fork/join框架

    fork/join是一个工具框架 ,本文详细的介绍了fork/join框架的具体使用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • Java8 Stream教程之collect()的技巧

    Java8 Stream教程之collect()的技巧

    Java8引入了全新的Stream API,这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同,下面这篇文章主要给大家介绍了关于Java8 Stream教程之collect()的技巧,需要的朋友可以参考下
    2022-09-09
  • Java深入浅出说流的使用

    Java深入浅出说流的使用

    这篇文章主要介绍了Java深入浅出说流的使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • java开发使用BigDecimal避坑四则

    java开发使用BigDecimal避坑四则

    这篇文章主要为大家介绍了java开发使用BigDecimal的避坑四则,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • SpringMVC文件上传中要解决的问题大汇总

    SpringMVC文件上传中要解决的问题大汇总

    这篇文章主要介绍了SpringMVC文件上传中要解决的问题,主要有中文文件名编码问题,文件位置存储问题以及文件名冲突问题等等,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • 如何解决项目中java heap space的问题

    如何解决项目中java heap space的问题

    这篇文章主要介绍了如何解决项目中java heap space的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • 基于Java SSM的健康管理小程序的实现

    基于Java SSM的健康管理小程序的实现

    本篇文章主要为大家分享了基于SSM健康管理小程序的设计与实现。感兴趣的小伙伴可以了解一下
    2021-11-11
  • SpringBoot自定义注解使用读写分离Mysql数据库的实例教程

    SpringBoot自定义注解使用读写分离Mysql数据库的实例教程

    这篇文章主要给大家介绍了关于SpringBoot自定义注解使用读写分离Mysql数据库的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 基于雪花算法实现增强版ID生成器详解

    基于雪花算法实现增强版ID生成器详解

    这篇文章主要为大家详细介绍了如何基于雪花算法实现增强版ID生成器,文中的示例代码讲解详细,对我们学习具有一定的借鉴价值,需要的可以了解一下
    2022-10-10

最新评论