1.5使用GraphQL组合API 原创
传统Rest API是由后端决定请求接口时输出的数据结构。GraphQL是一种用于API的查询语言,使得客户端能根据自己的需要获取数据,没有任何冗余,从而减少不必要的网络传输浪费。本节介绍使用Quarkus来实现GraphQL基本功能。
1.5.1 添加GraphQL功能扩展
在pom.xml文件中添加smallrye-graphql扩展来启用GraphQL支持:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-graphql</artifactId>
</dependency>
1.5.2 创建领域类
创建两个领域类Book(书籍)和Catalog(目录),代码如下:
package manon.wang.domain;
import java.util.List;
/**
* 书籍
*/
public class Book {
public String bookName;// 书名
public String language;//语言
public String author;//作者
public List<Catalog> catalogs;// 目录
}
package manon.wang.domain;
import java.util.List;
/**
目录
*/
public class Catalog {
public Integer id;// ID
public String chapter;// 章节
public List<String> content;//内容
}
1.5.3 创建服务层代码
创建一个书籍服务类BookService。本专栏第5章讲解通过数据库增、删、改、查数据的方法,本节为方便演示,使用在构造函数中初始化演示数据的方式。同时,实现三个方法,分别是获得所有书籍、根据书名查询书籍和新增书籍,代码如下:
package manon.wang.service;
import manon.wang.domain.Book;
import manon.wang.domain.Catalog;
import javax.enterprise.context.ApplicationScoped;
import java.util.ArrayList;
import java.util.List;
/**
* 书籍服务层
*/
@ApplicationScoped
public class BookService {
private List<Book> books = new ArrayList<>();
/**
* 构造函数
*/
public BookService() {
/**
* 第一本书
*/
Book book = new Book();
book.bookName = "拥抱云原生——Quarkus快速开发指南";
book.language = "Quarkus";
book.author = "李程华";
List<Catalog> catalogs = new ArrayList<>();
Catalog catalog = new Catalog();
catalog.id = 1;
catalog.chapter = "第1章 Hello Quarkus";
List<String> content = new ArrayList<>();
content.add("1.1 云原生时代的宠儿Quarkus");
content.add("1.2 搭建开发环境");
content.add("1.3 Hello Quarkus");
content.add("1.4 生成OpenAPI规范文档");
content.add("1.5 使用GraphQL组合API");
content.add("1.6 应用打包方式");
content.add("1.7 总结与回顾");
catalog.content = content;
catalogs.add(catalog);
catalog = new Catalog();
catalog.id = 2;
catalog.chapter = "第2章 从SpringCloud到Quarkus";
content = new ArrayList<>();
content.add("2.1 Quarkus微服务生命周期");
content.add("2.2 开发REST API");
content.add("2.3 Quarkus的依赖注入");
content.add("2.4 Quarkus的微服务配置");
content.add("2.5 常用数据校验注解");
content.add("2.6 异常与日志处理");
content.add("2.7 总结与回顾");
catalog.content = content;
catalogs.add(catalog);
book.catalogs = catalogs;
books.add(book);
/**
* 第二本书
*/
book = new Book();
book.bookName = "HarmonyOS 3.0 ArkUI eTS 开发实战";
book.language = "鸿蒙eTS";
book.author = "李程华";
catalogs = new ArrayList<>();
catalog = new Catalog();
catalog.id = 1;
catalog.chapter = "第1章 鸿蒙3.0真的来了";
content = new ArrayList<>();
content.add("1.1 鸿蒙3.0 App开发技术选型");
content.add("1.2 DevEco Studio 3.0 Beta2 for HarmonyOS下载与安装");
content.add("1.3 完成开发者认证");
content.add("1.4 调试代码、本地预览和远程模拟器");
content.add("1.5 真机调试与应用发布");
content.add("1.6 总结与回顾");
catalog.content = content;
catalogs.add(catalog);
catalog = new Catalog();
catalog.id = 2;
catalog.chapter = "第2章 揭开方舟开发框架ArkUI(eTS)的神秘面纱";
content = new ArrayList<>();
content.add("2.1 eTS物种起源");
content.add("2.2 基于eTS的ArkUI有什么优势");
content.add("2.3 ArkUI App设计规范");
content.add("2.4 实现沉浸式体验的状态栏");
content.add("2.5 全场景开发的优点和痛点");
content.add("2.6 ArkUI实现一次开发多端部署");
content.add("2.7 总结与回顾");
catalog.content = content;
catalogs.add(catalog);
book.catalogs = catalogs;
books.add(book);
}
/**
* 获得所有书籍
* @return
*/
public List<Book> getAllBooks() {
return books;
}
/**
* 根据书名查询书籍
* @param bookName
* @return
*/
public Book getBook(String bookName) {
for (Book book:
books) {
if(bookName.equals(book.bookName)){
return book;
}
}
return null;
}
/**
* 新增书籍
* @param book
*/
public void addBook(Book book) {
books.add(book);
}
}
1.5.4 创建资源类
创建一个资源类GraphQLResource.java,在类上面加上“@GraphQLApi”注解。代码如下:
提示下一章讲解@ApplicationScoped和@Inject注解,这里可以不用关注。
package manon.wang;
import org.eclipse.microprofile.graphql.*;
import manon.wang.domain.Book;
import manon.wang.service.BookService;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.util.List;
@ApplicationScoped
@GraphQLApi
public class GraphQLResource {
@Inject
BookService bookService;
@Query("allBooks")// 查询路径,类似于REST的GET方法
@Description("查询所有书籍")
public List<Book> getAllBooks() {
return bookService.getAllBooks();
}
@Query
@Description("根据书名查询书籍")
public Book getBook(@Name("bookName") String bookName) {
return bookService.getBook(bookName);
}
@Mutation
public Book createBook(Book book) {
bookService.addBook(book);
return book;
}
}
1.5.5 体验GraphQL查询
运行项目,可以访问3个不同的GraphQL服务,如表所示:
表1-1三种GraphQL服务
路径 | 作用 |
/q/graphql-ui | GraphQL开发界面 |
/graphql/schema.graphql | 获取GraphQL模式 |
/graphql | GraphQL的API终端 |
首先,我们可以通过/graphql/schema.graphql获取GraphQL模式,看一下GraphQL API的相关接口及数据结构,如图1-22 所示:
图1-22 获取GraphQL模式
然后,访问路径/q/graphql-ui,在GraphQL开发界面中请求数据,如图1-23 所示:
图1-23 在GraphQL开发界面请求数据
改变一下请求的数据模型,发现返回的数据结构也做了相应的剪裁,如图1-24 所示:
图1-24 改变请求的数据模型
根据书名查询某本书籍的示例如图1-25 所示:
图1-25 根据书名查询某本书籍
在GraphQL中也可以通过“@Mutation”注解构建新增、修改和删除的方法。这里示范一个新增书籍的例子,如图1-26 所示:
图1-26 新增书籍
再次查询书籍列表,发现列表也已更新。如图1-27 所示:
图1-27 新增书籍