Java 使用 Graphql , 搭建查询服务
Java 使用 Graphql , 搭建查询服务
-外星人- 发表于1年前
Java 使用 Graphql , 搭建查询服务
  • 发表于 1年前
  • 阅读 527
  • 收藏 9
  • 点赞 0
  • 评论 6

腾讯云 技术升级10大核心产品年终让利>>>   

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

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

标签: graphql-java react
共有 人打赏支持
粉丝 47
博文 45
码字总数 22101
评论 (6)
WeiXiaodong
fb版的junit?
-外星人-

引用来自“WeiXiaodong”的评论

fb版的junit?
GraphQL是一个由Facebook提出的应用层查询语言,用来做后端数据接口的
迪拜驻开源中国大使
楼主,请问这个还有继续研究么?
-外星人-

引用来自“yuanshichao1988”的评论

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

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

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

引用来自“yuanshichao1988”的评论

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

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

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

引用来自“yuanshichao1988”的评论

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

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

引用来自“TommyLemon”的评论

GraphQL太复杂太难用了,一堆概念,前端/客户端要查的结构还要后端都定义好,手动对字段resolve,要做大量多余的工作。尤其是java版是个巨坑,定义太混乱太啰嗦。
我们公司之前也简单尝试过,后来改用APIJSON了
服务端确实有点繁琐,不过客户端还是挺行,JAVA 强类型,本身语法也这样,可以fork一个然后改进改进嘛,其实我一直想做一个lua版本的,放在nginx内部,提供兼容graphql,后端也不用改,在中间层提供一个这样的服务,无侵入,graphql 理念还是挺好的。。。
×
-外星人-
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: