背景
隨著React的開源,facebook相繼開源了很多相關的項目,這些項目在他們內部已經使用了多年,其中引起我注意的就是本次討論的是graphql,目前官方只有nodejs版,由于很多公司的后臺技術棧都是Java,所以便有了graphql的java版實現,在github上可以找到,廢話不多說,直接看代碼吧,具體介紹還是去看官網吧,不然就跑題了。
GraphQLSchema
Schema相當于一個數據庫,它有很多GraphQLFieldDefinition組成,Field相當于數據庫表/視圖,每個表/視圖又由名稱、查詢參數、數據結構、數據組成.
1) 先定義一個數據結構(GraphQLOutputType)字段,然后定義一個初始化方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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)再定義兩個表/視圖,它包括名稱,查詢參數,數據結構,以及數據檢索器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
/** * 查詢單個用戶信息 * @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)
1
2
3
4
5
6
7
8
9
10
|
private GraphQLSchema schema; public GraphSchema() { initOutputType(); schema = GraphQLSchema.newSchema().query(newObject() .name( "GraphQuery" ) .field(createUsersField()) .field(createUserField()) .build()).build(); } |
4)完成以上步驟之后,還需要定義一個model,類名不限,但是結構需要滿足前面定義的數據結構,而且必須是public的
1
2
3
4
5
6
7
8
|
public class User { private int id; private int age; private int sex; private String name; private String pic; // getter, setter... } |
5)之后寫一個main方法,來測試一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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); } |
輸出:
1
2
3
|
{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依賴
1
2
3
4
5
|
<dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-java</artifactId> <version> 2.0 . 0 </version> </dependency> |
關于graphql查詢什么定義,看看這個或許對你有幫助
json
1
2
3
4
5
6
|
{ id= 6 , sex= 0 , name= "Name_6" , pic= "pic_6.jpg" } |
query
1
2
3
4
5
6
|
{ id, sex, name, pic } |
后面那部分,其實就是json字符串,去掉=和value的結果,還是可讀的
結語
graphql 帶了一種全新的思維方式,可以簡化web api的開發,由客戶端指定需要什么數據,服務端返回什么數據,減少不必要的流量傳輸,對移動端友好,還提供多種數據聚合查詢,多個查詢只是用一個請求,既滿足api最小粒度,又滿足前端需要,減少請求,提高性能。
感覺以后會朝這方面去發展,大趨所驅。
原文鏈接:http://blog.csdn.net/qq362228416/article/details/50854980