java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言, 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台 (即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se)) 的总称
这篇文章主要介绍了 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 最小粒度, 又满足前端需要, 减少请求, 提高性能
感觉以后会朝这方面去发展, 大趋所驱
来源: http://www.phperz.com/article/18/0219/359220.html