在过去几年中,开发人员使用 HTTP(s) 上的 RESTful Web 服务,通过 API 公开业务功能。 REST API 使用服务器驱动的固定数据响应,这意味着开发人员(客户端)无法确定响应的结果。相反,服务器将所有数据发送回客户端,这称为过度获取。开发人员(客户端)需要调用第一个调用后的多个 REST API,直到客户端获得所需的数据,这会导致获取不足。
为了创建新的微服务,使用这些 REST API 的开发人员一直在寻找方法来最大限度地减少检索数据以及业务逻辑时的过度获取和获取不足的情况。
GraphQL 提供了一种客户端驱动的查询语言和运行时,以防止客户端的这种开销,而是检索 REST API 所需的精确数据。当 GraphQL 出现时,许多开发人员认为它可以取代现有的 REST API 规范。但是,它不是替代品,而是一种替代方案。
本文介绍如何使用 Quarkus 应用程序使用 GraphQL 服务。 Quarkus 是一个基于 Kubernetes 的 Java 应用程序编写框架。如果您以前没有创建过 Quarkus 应用程序,请在继续之前阅读在 VS Code 中使用 Quarkus 编写 Java。
将 GraphQL 扩展添加到您的 Quarkus 项目
首先,通过在终端中输入以下内容(或者您可以使用 Visual Studio Code 中的 Quarkus 工具),将 Quarkus 扩展 smallrye-graphql 添加到现有的 Quarkus Maven 项目中
$ mvn quarkus:add-extension -Dextensions="graphql"您应该在终端中看到以下内容
✅ Extension io.quarkus:quarkus-smallrye-graphql has been installed
[INFO] ---------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ---------------------------------------------------------------------
[INFO] Total time:  9.833 s
[INFO] Finished at: 2020-07-29T22:00:28-04:00
[INFO] ---------------------------------------------------------------------为 GraphQL 的 API 添加一个实体和一个服务
创建两个实体 Java 类——对于这个例子,查询关于电影的数据。将它们命名为 Film 和 Hero——来表示 GraphQL 模式,它们是一组最终用户可以检索的可能的数据(例如,对象、字段、关系)
public class Film {
    private String title;
    private Integer episodeID;
    private String director;
    private LocalDate releaseDate;
   // Getter & Setter methods here
   ...
}
public class Hero {
    private String name;
    private String surname;
    private Double height;
    private Integer mass;
    private Boolean darkSide;
    private LightSaber lightSaber;
    private List<Integer> episodeIds = new ArrayList<>();
   // Getter & Setter methods here
   ...
}
enum LightSaber {
    RED, BLUE, GREEN
}使用 CDI bean 创建 GraphQL API
在 CDI(上下文和依赖注入)bean 类(例如,GalaxyService.java)中实现一些方法来检索带有参数的 Film 和 Hero 数据。生成一些示例数据
public GalaxyService() {
   Film aNewHope = new Film();
   aNewHope.setTitle("A New Hope");
   aNewHope.setReleaseDate(LocalDate.of(1977, Month.MAY, 25));
   aNewHope.setEpisodeID(4);
   aNewHope.setDirector("George Lucas");
   films.add(aNewHope);
   ...
   Hero luke = new Hero();
   luke.setName("Luke");
   luke.setSurname("Skywalker");
   luke.setHeight(1.7);
   luke.setMass(73);
   luke.setLightSaber(LightSaber.GREEN);
   luke.setDarkSide(false);
   luke.getEpisodeIds().addAll(Arrays.asList(4, 5, 6));
   heroes.add(luke);
   ...
public List<Film> getAllFilms() {
   return films;
}现在,创建一个 GraphQL API 类(例如,FilmResource.java)来注入 CDI bean
@GraphQLApi 
public class FilmResource {
    @Inject
    GalaxyService service;
    @Query("allFilms") 
    @Description("Get all Films from a galaxy far far away") 
    public List<Film> getAllFilms() {
        return service.getAllFilms();
    }
}@GraphQLApi 注解使您能够使用 CDI bean(例如,GalaxyService)来创建一个 GraphQL 端点。@Query 注解允许您使用特定名称(例如,allFilms)使方法(例如,getAllFilms)可查询。
访问 GraphiQL 的 UI,一个 GraphQL 界面
Quarkus smallrye-graphql 扩展使您可以在运行 Quarkus 应用程序时使用 GraphiQL 工具轻松地与您的 GraphQL API 进行交互。在使用 Quarkus 的开发模式 (mvn quarkus:dev) 启动应用程序后,使用以下端点访问 GraphiQL 用户界面 (UI)
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2020-07-29 22:25:18,324 WARN  [io.sma.graphql] (Quarkus Main Thread) SRGQL010000: Schema is null, or it has no operations. Not bootstrapping SmallRye GraphQL
2020-07-29 22:25:18,552 INFO  [io.quarkus] (Quarkus Main Thread) quarkus-getting-started 1.0.0-SNAPSHOT on JVM (powered by Quarkus x.xx.x.) started in 1.246s. Listening on: http://0.0.0.0:8080
2020-07-29 22:25:18,553 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2020-07-29 22:25:18,553 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, smallrye-graphql]一旦 Quarkus 运行时启动,使用 https://:8080/graphql-ui/ 在本地访问 GraphiQL 的 UI。
您将看到
 
(Daniel Oh, CC BY-SA 4.0)
查询 GraphQL API
尝试使用以下内容查询 GraphiQL
query allFilms {
  allFilms {
    title
    director
    releaseDate
    episodeID
  }
}单击播放按钮,您将看到
 
(Daniel Oh, CC BY-SA 4.0)
假设一个新的客户端应用程序需要 title 和 episodeID 数据,但不需要调用之前的 API(即,过度获取),其中包括不必要的数据(例如,Director、releaseDate)。 尝试再次使用以下内容查询 GraphiQL
query allFilms {
  allFilms {
    title
    episodeID
  }
}您将看到
 
(Daniel Oh, CC BY-SA 4.0)
下一步
GraphQL 的受欢迎程度正在持续增长,并且它与 Java 很好地集成。如果您正在寻找更多学习方法,请尝试更改查询数据以满足您通过 GraphQL API 的业务需求。请记住,本操作方法的完整 Java 代码可在 GitHub 仓库中找到。
 
 
 
 
 
 
 
 

1 条评论