2025年DGS之联邦(Federation)

DGS之联邦(Federation)Federation DGS 开箱即与联盟兼容 具有引用和扩展联盟类型的能力 联盟实例 DGS 这是一个 DGS 的例子 演示了如何实现一个联盟类型 并测试联盟查询 本指南中的源代码来自于 Federation 的例子应用 我们强烈建议克隆该项目并在遵循本指南的同时使用 IDE 该示例项目有以下设置 1

大家好,我是讯享网,很高兴认识大家。

Federation

DGS开箱即与联盟兼容,具有引用和扩展联盟类型的能力。

联盟实例 DGS

这是一个DGS的例子,演示了如何实现一个联盟类型,并测试联盟查询。本指南中的源代码来自于Federation的例子应用。我们强烈建议克隆该项目并在遵循本指南的同时使用IDE。

该示例项目有以下设置。

1、使用Apollo的联盟网关库设置了一个联盟网关。
2、Shows DGS定义并拥有Show类型。
3、Review DGS在Show类型中添加了一个Review字段。

定义联合类型

Shows DGS定义了带有id、title和releaseYear字段的Show类型。请注意,id字段被标记为关键。这个例子有一个键,但你也可以有多个键 @key(fields: “fieldA fieldB” 这表明网关的id字段将被用于识别Shows DGS中的相应的Show,并且必须指定联合类型。

type Query { 
    shows(titleFilter: String): [Show] } type Show @key(fields: "id") { 
    id: ID title: String releaseYear: Int } 

讯享网

扩展联合类型

要扩展一个类型,你要在你自己的模式中重新定义该类型,使用指令@extends来指示它是一个类型扩展。@key是必需的,用于指示网关将用来识别查询的原始Show的字段。在这种情况下,键是id字段。

讯享网type Show @key(fields: "id") @extends { 
    id: ID @external reviews: [Review] } type Review { 
    starRating: Int } 

当重新定义一个类型时,只有id字段和你要添加的字段需要被列出。其他字段,如Show类型的标题,是由Shows DGS提供的,不需要指定,除非你在模式中使用它。联邦确保由所有DGS提供的字段被合并成一个单一的类型,用于返回查询结果。

如果您定义的字段不属于您的 DGS,但您需要引用它,请不要忘记使用 @external 指令。


讯享网

实现联合类型

开始的第一步是生成代表模式的Java类型。这在build.gradle中进行了配置,如手册中所述。当运行./gradlew build时,Java类型被生成到build/generated文件夹中,然后被自动添加到classpath中。

提供实体提取器

让我们看一下发送到网关的以下查询的示例;

query { 
    shows { 
    title reviews { 
    starRating } } } 

Review DGS需要实现一个实体取回器来处理这个查询。实体获取器负责根据上述_entities查询中的表示创建一个Show的实例。DGS框架完成了大部分繁重的工作,而我们所要做的就是提供以下内容。

讯享网@DgsEntityFetcher(name = "Show") public Show movie(Map<String, Object> values) { 
    return new Show((String) values.get("id"), null); } 

请记住,此处的 Show Java 类型是由 codegen 生成的。它是从模式生成的,所以它只有我们的模式指定的字段。

使用 @DgsEntityFetcher 注解的方法应返回具体类型(在本例中为:Show)、CompletionStage< T>(例如 CompletableFuture< T>)或 Reactor Mono< T> 实例。

使用数据提取器提供数据

现在,DGS知道在收到_entities查询时如何创建一个Show实例,我们可以指定如何为review字段提供数据。

@DgsData(parentType = "Show", field = "reviews") public List<Review> reviews(DgsDataFetchingEnvironment dataFetchingEnvironment) { 
    Show show = dataFetchingEnvironment.getSource(); return reviews.get(show.getId()); } 

测试一个联合查询

对于自动化测试,QueryExecutor提供了一种从单元测试中运行查询的方法,启动开销很小(在500ms左右)。我们可以捕获(或手动编写)网关发送给DGS的_entities查询。当通过(本地运行的)网关运行查询时,DGS将记录它收到的查询。只需在QueryExecutor测试中复制这个查询,就可以隔离验证DGS了。

讯享网@SpringBootTest(classes = { 
   DgsAutoConfiguration.class, ReviewsDatafetcher.class}) class ReviewsDatafetcherTest { 
    @Autowired DgsQueryExecutor dgsQueryExecutor; @Test void shows() { 
    Map<String,Object> representation = new HashMap<>(); representation.put("__typename", "Show"); representation.put("id", "1"); List<Map<String, Object>> representationsList = new ArrayList<>(); representationsList.add(representation); Map<String, Object> variables = new HashMap<>(); variables.put("representations", representationsList); List<Review> reviewsList = dgsQueryExecutor.executeAndExtractJsonPathAsObject( "query ($representations:[_Any!]!) {" + "_entities(representations:$representations) {" + "... on Show {" + " reviews {" + " starRating" + "}}}}", "data['_entities'][0].reviews", variables, new TypeRef<>() { 
   }); assertThat(reviewsList) .isNotNull() .hasSize(3); } } 

为了帮助构建联合 _entities 查询,您还可以使用 graphql-dgs-client 包中提供的 EntitiesGraphQLQuery 以及代码生成。以下是使用构建器 API 的同一测试的示例:

@SpringBootTest(classes = { 
   DgsAutoConfiguration.class, ReviewsDatafetcher.class}) class ReviewssDatafetcherTest { 
    @Autowired DgsQueryExecutor dgsQueryExecutor; @Test void showsWithEntitiesQueryBuilder() { 
    EntitiesGraphQLQuery entitiesQuery = new EntitiesGraphQLQuery.Builder().addRepresentationAsVariable(ShowRepresentation.newBuilder().id("1").build()).build(); GraphQLQueryRequest request = new GraphQLQueryRequest(entitiesQuery, new EntitiesProjectionRoot().onShow().reviews().starRating()); List<Review> reviewsList = dgsQueryExecutor.executeAndExtractJsonPathAsObject( request.serialize(), "data['_entities'][0].reviews", entitiesQuery.getVariables(), new TypeRef<>() { 
    }); assertThat(reviewsList).isNotNull(); assertThat(reviewsList.size()).isEqualTo(3); } } 

定制默认的联盟解析器

在上面的例子中,GraphQL Show类型名称映射到Java Show类型。也有GraphQL和Java类型名称不匹配的情况,特别是在使用现有代码时。如果你的任何一个类的名称与你的模式类型名称不匹配,你需要为这个类提供一种方法来映射它们。要做到这一点,在你自己实现的DefaultDgsFederationResolver中,从typeMapping()方法返回一个映射。在下面的例子中,我们将GraphQL Show类型映射到一个ShowId Java类型。

讯享网@DgsComponent public class FederationResolver extends DefaultDgsFederationResolver { 
    private final Map<Class<?>, String> types = new HashMap<>(); @PostConstruct public void init() { 
    //The Show type is represented by the ShowId class. types.put(ShowId.class, "Show"); } @Override public Map<Class<?>, String> typeMapping() { 
    return types; } } 
小讯
上一篇 2025-02-23 20:24
下一篇 2025-02-22 13:23

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/37546.html