Graphql Tutorials(Episode 02)
阅读原文时间:2023年07月09日阅读:1

1.前言

我们在上篇已经了解Graphql的使命以及Graphql的概况,接下来,我们跑起来另外一个Helloworld来开启继续学习。

2.Helloworld(使用Graphql 原生API)

这里呢,我们会用Graphql的原生API来搭建helloword

Java 8

SpringBoot

OKTA:洛杉矶的一个公司,为系统提供信息安全验证。

GraphQL Playground: 类似于Postman的工具,这里呢用Postman也可以,但是,我更喜欢GraphQL Playground黑色页面的风格。

Download:https://www.electronjs.org/apps/graphql-playground

完整Demo的地址:

https://github.com/lihao5257/GraphqlDemo.git     代码在master分支

我们进入正题。首先是schema.graphqls, 里面定义了Graphql API的结构。

# This is a comment
type Query {
bookById(id: ID): Book
allBooks: [Book]
}

type Book {
id: ID
name: String
pageCount: Int
author: Author
}

type Author {
id: ID
firstName: String
lastName: String
}

然后我们需要将上述文件进行解析,将解析后的关键字与逻辑的处理进行匹配。

1 public void init() throws IOException {
2 URL url = Resources.getResource("schema.graphqls");
3 String sdl = Resources.toString(url, Charsets.UTF_8);
4 GraphQLSchema graphQLSchema = buildSchema(sdl);
5 this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
6 }
7 // 解析SDL文件,然后,进行属性的绑定。
8 private GraphQLSchema buildSchema(String sdl) {
9 TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
10 RuntimeWiring runtimeWiring = buildWiring();
11 SchemaGenerator schemaGenerator = new SchemaGenerator();
12 return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
13 }
14
15 private RuntimeWiring buildWiring() {
16 return RuntimeWiring.newRuntimeWiring()
17 .type(TypeRuntimeWiring.newTypeWiring("Query")
// bookById的查询,与右边的逻辑进行绑定。当API调用bookById这个方法时,程序就知道该如何进行查询了。
18 .dataFetcher("bookById", graphQLDataFetchers.getBookByIdDataFetcher()))
19 .type(TypeRuntimeWiring.newTypeWiring("Book")
20 .dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher()))
21 .type(TypeRuntimeWiring.newTypeWiring("Query")
22 .dataFetcher("allBooks", graphQLDataFetchers.getAllBooksDataFetcher()))
23 .build();
24 }

接下来,我们要编辑与bookById绑定的方法,比如,从DB里查数据,或是从缓存中查找等等。

1 public DataFetcher getBookByIdDataFetcher() {
2 return dataFetchingEnvironment -> {
3 String bookId = dataFetchingEnvironment.getArgument("id");
4 return books
5 .stream()
6 .filter(book -> book.get("id").equals(bookId))
7 .findFirst()
8 .orElse(null);
9 };
10 }
11
12 public DataFetcher getAuthorDataFetcher() {
13 return dataFetchingEnvironment -> {
14 Map book = dataFetchingEnvironment.getSource();
15 String authorId = book.get("authorId");
16 return authors
17 .stream()
18 .filter(author -> author.get("id").equals(authorId))
19 .findFirst()
20 .orElse(null);
21 };
22 }
23
24 public DataFetcher getAllBooksDataFetcher() {
25 return dataFetchingEnvironment -> {
26 return books;
27 };
28 }

到这里,我们API编辑的部分就算完成了。主要的流程就是按照上一篇博文中讲解的Graphql初始化流程来的。

大家可以发现,这种原生API的方式,非常的繁琐,我们必须手动地将查询方法(如:bookById)和对应的逻辑(graphQLDataFetchers.getBookByIdDataFetcher())绑定在一起。这就非常麻烦。为了简化流程,开发者会使用另外一种基于API,它基于原生API,在其基础上进行了包装,让开发者只需要关注于业务。

3.Helloworld(使用GraphQL Java Tools)

demo地址:

https://github.com/lihao5257/GraphqlDemo.git   选择tutorial-graphql-java-tools-hello分支

同样,先是schema.graphqls文件的创建

# This is a comment
type Book {
title: String!
isbn: String!
}

type Query {
getBook(isbn: String!): Book
getAllBooks : [Book]
}

type Mutation {
createBook(book:BookWrapper):Book
}

input BookWrapper{
title:String!
isbn:String!
}

我们接下来要创建Book的模型

1 public class Book {
2
3 private String title;
4 private String isbn;
5
6 public Book(String title, String isbn) {
7 this.title = title;
8 this.isbn = isbn;
9 }
10
11 public String getTitle() {
12 return title;
13 }
14
15 public void setTitle(String title) {
16 this.title = title;
17 }
18
19 public String getIsbn() {
20 return isbn;
21 }
22
23 public void setIsbn(String isbn) {
24 this.isbn = isbn;
25 }
26
27 }

然后,要创建一个Resolver,意思是调用API(如:调用getBook())时,处理请求的业务逻辑是什么样的。

// 处理查询的方法时,需要继承GraphQLQueryResolver 这个接口
public class BookResolver implements GraphQLQueryResolver {

static List<Book> books  = null;  
static {  
    books   =new ArrayList<Book>();  
    books.add(new Book("Harry Porter 1", "1111"));  
    books.add(new Book("Harry Porter 2", "2234"));  
    books.add(new Book("Harry Porter 3", "2434324"));  
    books.add(new Book("Harry Porter 4", "112343211"));  
    books.add(new Book("Harry Porter 5", "5646"));  
}

   // method名字跟API调用的名字一致,在方法里面写具体业务逻辑即可
public Book getBook(String isbn) {
return new Book("Learn GraphQL", "309234324");
}

public List<Book> getAllBooks() {  
    return books;  
}  

}

然后,就OK啦,非常的简便。省去了一切非业务的操作。这个处理方法有些像JPA,操作对象的的感觉。至此,我们的helloword完成了。希望大家亲自跑一跑,感受一下。

3.完整demo

这个完成的demo中,有增删改查的完整功能,以及异常处理等操作。大家感兴趣的话,可以看看。

https://github.com/lihao5257/GraphqlDemo.git     graphql-java-tools-full-demo分支

4.小结

Graphql入门基础,并不难。GraphQL Java Tools的这样类似JPA的,通过对象来操作事情的思想很好,这个月找机会研究一下JPA以及GraphQL Java Tools的源码,学习一下。

References:

https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/#graphql-in-3-minutes
https://www.graphql-java.com/documentation/v15/
https://graphql.org/
https://www.graphql-java-kickstart.com/