background
With the open source of React, Facebook has successively opened sourced many related projects. These projects have been used in them for many years. What attracted my attention was that this time is graphql. Currently, there is only the nodejs version of the official website. Since many companies' backend technology stacks are Java, there is a Java version implementation of graphql, which can be found on github. Without further ado, just look at the code. For the specific introduction, go to the official website cafe, otherwise it will be off topic.
GraphQLSchema
Schema is equivalent to a database, it consists of many GraphQLFieldDefinitions, Field is equivalent to database table/view, and each table/view is composed of name, query parameters, data structure, and data.
1) First define a data structure (GraphQLOutputType) field, and then define an initialization method
private GraphQLOutputType userType;private void initOutputType() { /** * Member object structure*/ userType = newObject() .name("User") .field(newFieldDefinition().name("id").type(GraphQLInt).build()) .field(newFieldDefinition().name("age").type(GraphQLInt).build()) .field(newFieldDefinition().name("name").type(GraphQLString).build()) .field(newFieldDefinition().name("pic").type(GraphQLString).build()) .build();}2) Define two more tables/views, which include names, query parameters, data structures, and data retrieval
/** * Query single user information* @return */ private GraphQLFieldDefinition createUserField() { return GraphQLFieldDefinition.newFieldDefinition() .name("user") .argument(newArgument().name("id").type(GraphQLInt).build()) .type(userType) .dataFetcher(environment -> { // Get query parameters int id = environment.getArgument("id"); // Execute the query, here you can use some test data to illustrate the problem 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(); } /** * Query multiple member information* @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 -> { // Get query parameters int page = environment.getArgument("page"); int size = environment.getArgument("size"); String name = environment.getArgument("name"); // Execute the query, here you can use some test data to illustrate the problem 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) Then define a schema and initialize it, it contains a name, and one or more tables/views (Fields)
private GraphQLSchema schema; public GraphSchema() { initOutputType(); schema = GraphQLSchema.newSchema().query(newObject() .name("GraphQuery") .field(createUsersField()) .field(createUserField()) .build()).build(); }4) After completing the above steps, you need to define a model, with no limit on the class name, but the structure needs to meet the data structure defined above, and it must be public.
public class User { private int id; private int age; private int sex; private String name; private String pic; // getter, setter...}5) Then write a main method to test it
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(); // Query the user list System.out.println(result1); // Query a single user System.out.println(result2); // Check System.out.println(result3);}Output:
{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) Finally, put the code in the main method on the web layer, and only need to define a query parameter, it is easy to build the query service. The original query interface is still called in the dataFetcher.
7) Introduce maven dependencies
<dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-java</artifactId> <version>2.0.0</version></dependency>
Regarding the definition of graphql query, see this may be helpful to you
json
{ id=6, sex=0, name="Name_6", pic="pic_6.jpg"}query
{ id, sex, name, pic}The latter part is actually a json string. The result of removing = and value is still readable.
Conclusion
graphql brings a new way of thinking, which can simplify the development of web APIs. The client specifies what data is needed and what data is returned by the server, reduces unnecessary traffic transmission, is friendly to mobile terminals, and also provides a variety of data aggregation queries. Multiple queries only use one request, which not only meets the minimum granularity of the API, but also meets the needs of the front-end, reduces requests, and improves performance.
I feel that I will develop in this direction in the future, driven by the general trend.