文档章节

Java 使用 Graphql , 搭建查询服务

-外星人-
 -外星人-
发布于 2016/12/09 00:46
字数 1146
阅读 627
收藏 9

背景

随着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最小粒度,又满足前端需要,减少请求,提高性能。

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

© 著作权归作者所有

共有 人打赏支持
-外星人-
粉丝 49
博文 48
码字总数 22995
作品 0
深圳
程序员
私信 提问
加载中

评论(6)

-外星人-
-外星人-

引用来自“-外星人-”的评论

引用来自“yuanshichao1988”的评论

楼主,请问这个还有继续研究么?

回复@yuanshichao1988 : 原来有一个项目用过, 现在没怎么用,感觉还不够火,很多人都不知道,推不动

引用来自“TommyLemon”的评论

GraphQL太复杂太难用了,一堆概念,前端/客户端要查的结构还要后端都定义好,手动对字段resolve,要做大量多余的工作。尤其是java版是个巨坑,定义太混乱太啰嗦。
我们公司之前也简单尝试过,后来改用APIJSON了
服务端确实有点繁琐,不过客户端还是挺行,JAVA 强类型,本身语法也这样,可以fork一个然后改进改进嘛,其实我一直想做一个lua版本的,放在nginx内部,提供兼容graphql,后端也不用改,在中间层提供一个这样的服务,无侵入,graphql 理念还是挺好的。。。
孤独的探索号
孤独的探索号

引用来自“-外星人-”的评论

引用来自“yuanshichao1988”的评论

楼主,请问这个还有继续研究么?

回复@yuanshichao1988 : 原来有一个项目用过, 现在没怎么用,感觉还不够火,很多人都不知道,推不动
GraphQL太复杂太难用了,一堆概念,前端/客户端要查的结构还要后端都定义好,手动对字段resolve,要做大量多余的工作。尤其是java版是个巨坑,定义太混乱太啰嗦。
我们公司之前也简单尝试过,后来改用APIJSON了
-外星人-
-外星人-

引用来自“yuanshichao1988”的评论

楼主,请问这个还有继续研究么?

回复@yuanshichao1988 : 原来有一个项目用过, 现在没怎么用,感觉还不够火,很多人都不知道,推不动
迪拜驻开源中国大使
迪拜驻开源中国大使
楼主,请问这个还有继续研究么?
-外星人-
-外星人-

引用来自“WeiXiaodong”的评论

fb版的junit?
GraphQL是一个由Facebook提出的应用层查询语言,用来做后端数据接口的
WeiXiaodong
WeiXiaodong
fb版的junit?
以LeetCode为例——如何发送GraphQL Query获取数据

前言 GraphQL 是一种用于 API 的查询语言,是由 Facebook 开源的一种用于提供数据查询服务的抽象框架。在服务端 API 开发中,很多时候定义一个接口返回的数据相对固定,因此要获得更多信息或...

zxzhang
07/19
0
0
Vue + GraphQL初试

基本用法 GraphQL概述 GraphQL基本语法特性 GraphQL类型系统 GraphQL类型系统内置基础类型 GraphQL类型系统内置修饰符 GraphQL工作原理 GraphQL执行过程 Vue工程接入GraphQL 基本用法(如何去...

清风0o0
06/17
0
0
阿里巴巴微服务下使用GraphQL构建BFF

作者“ThoughtWorks” 微服务架构,这个在几年前还算比较前卫的技术在如今遍地开花。得益于开源社区的支持,我们可以轻松地利用 Spring Cloud 以及 Docker 容器化快速搭建一个微服务架构的原...

美的让人心动
04/28
0
0
Apollo GraphQL 服务端实践

如果喜欢我们的文章别忘了点击关注阿里南京技术专刊呦~ 本文转载自 阿里南京技术专刊-知乎,欢迎大牛小牛投递阿里南京前端/后端开发等职位,详见 阿里南京诚邀前端小伙伴加入~。 在最近的项目...

阿里南京技术专刊
05/22
0
0
Elide 4.0.0 正式发布,基于 JSON API 的 Web 服务

Elide 4.0.0 发布了,Elide 是一个用 JPA 注释模型轻松搭建 JSON API Web 服务的 Java 库。Elide 可以迅速搭建和部署高性能 Web 服务,将数据模型以服务的形式开放访问。 该版本更新内容可参...

达尔文
02/02
1K
3

没有更多内容

加载失败,请刷新页面

加载更多

First Bad Version(leetcode278)

You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is......

woshixin
6分钟前
0
0
executor 和task 优先于线程(68)

java.util.concurrent 包里有一个Executor 框架 基于接口的任务执行工具 只需要一行代码 提交一个runnable 方法 优雅的终止(必须做到,不然虚拟机可能不会退出) 对于负载不重的服务 Execut...

Java搬砖工程师
6分钟前
0
0
一条SQL查询语句是如何执行的

123

writeademo
9分钟前
0
0
hive 集成sentry

环境 apache-hive-2.3.3-bin apache-sentry-2.1.0-bin 1 2 sentry是目前最新的版本,支持hive的最高版本为2.3.3,hive版本如果高于2.3.3,会出一些版本兼容问题[亲测] hive快速安装 wget htt...

hblt-j
9分钟前
0
0
CSS中position属性( absolute | relative | static | fixed )详解

四个属性的特点 static:无特殊定位,对象遵循正常文档流。top,right,bottom,left等属性不会被应用。 relative:对象遵循正常文档流,但将依据top,right,bottom,left等属性在正常文档流...

简心
14分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部