联邦dlc_联邦和帝国两个阵营

联邦dlc_联邦和帝国两个阵营ShowsDGS定义了带有id、title和releaseYear字段的Show类型

联邦dlc_联邦和帝国两个阵营"

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;
    }
}

今天的文章联邦dlc_联邦和帝国两个阵营分享到此就结束了,感谢您的阅读。

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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注