Federation
Spring for GraphQL 提供了对 federation-jvm 库的集成,该库使用 GraphQL Java 在联邦服务图中初始化子图的模式。详情请参阅 Apollo Federation 和 子图规范。
配置
要启用集成,请在配置中声明一个 FederationSchemaFactory bean,并将其插入到 GraphQlSource.Builder 中。例如,在 Spring Boot 中:
@Configuration
public class FederationConfig {
@Bean
public GraphQlSourceBuilderCustomizer customizer(FederationSchemaFactory factory) {
return builder -> builder.schemaFactory(factory::createGraphQLSchema);
}
@Bean
public FederationSchemaFactory schemaFactory() {
return new FederationSchemaFactory();
}
}
现在子图服务的模式可以扩展联邦类型:
type Book @key(fields: "id") @extends {
id: ID! @external
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
@EntityMapping
@EntityMapping 方法可以加载联邦类型实例,以响应来自联邦网关的 _entities 查询。例如:
@Controller
private static class BookController {
@EntityMapping
public Book book(@Argument int id) { 1
// ...
}
@SchemaMapping
public Author author(Book book) { 2
// ...
}
}
@Argument方法参数从实体的"表示"输入映射中解析。完整的"表示"输入Map也可以被解析。有关支持的方法参数和返回值类型,请参阅方法签名。@SchemaMapping方法可用于图的其余部分。
你可以通过接受一个 List 类型的 ID 列表,并返回一个 List 或 Flux 类型的实体列表,来批量加载同一类型的联邦实体:
@Controller
private static class BookController {
@EntityMapping
public List<Book> book(@Argument List<Integer> idList) { 1
// ... return books in the same order
}
@BatchMapping
public Map<Book, Author> author(List<Book> books) { 2
// ...
}
}
idList命名约定有助于对参数名进行单数化处理,以便在 "representation" 输入映射中查找正确的值。你也可以通过注解来设置参数名。@BatchMapping方法可用于图的其余部分。
你可以使用 DataLoader 加载联邦实体:
@Controller
private static class BookController {
@Autowired
public DataLoaderBookController(BatchLoaderRegistry registry) { 1
registry.forTypePair(Integer.class, Book.class).registerBatchLoader((bookIds, environment) -> {
// load entities...
});
}
@EntityMapping
public Future<Book> book(@Argument int id, DataLoader<Integer, Book> dataLoader) { 2
return dataLoader.load(id);
}
@BatchMapping
public Map<Book, Author> author(List<Book> books) { 3
// ...
}
}
为联邦实体类型注册批量加载器。
在
@EntityMapping方法中声明一个DataLoader参数。@BatchMapping方法可用于图的其余部分。
方法签名
实体映射方法支持以下参数:
| 方法参数 | 描述 |
|---|---|
@Argument | 用于从"表示"输入映射中访问命名值,并转换为类型化对象。 |
Map<String, Object> | 实体的完整"表示"输入映射。 |
List<Map<String, Object>> | 当使用单个控制器方法加载给定类型的所有实体时,表示"表示"输入映射的列表。 |
@ContextValue | 用于从 DataFetchingEnvironment 中的主 GraphQLContext 访问属性。 |
@LocalContextValue | 用于从 DataFetchingEnvironment 中的本地 GraphQLContext 访问属性。 |
GraphQLContext | 用于从 DataFetchingEnvironment 访问上下文。 |
java.security.Principal | 从 Spring Security 上下文获取(如果可用)。 |
@AuthenticationPrincipal | 用于从 Spring Security 上下文访问 Authentication#getPrincipal()。 |
DataFetchingFieldSelectionSet | 用于通过 DataFetchingEnvironment 访问查询的选择集。 |
Locale, Optional<Locale> | 用于从 DataFetchingEnvironment 访问 Locale。 |
DataFetchingEnvironment | 用于直接访问底层的 DataFetchingEnvironment。 |
DataLoader<I, E> | 用于通过 DataLoader 加载联邦实体,其中 I 是 ID 类型,E 是实体类型。 |
@EntityMapping 方法可以返回 Mono、CompletableFuture、Callable 或实际的实体。
异常处理
你可以使用 @GraphQlExceptionHandler 方法来将 @EntityMapping 方法抛出的异常映射为 GraphQLError。这些错误将包含在 "_entities" 查询的响应中。异常处理方法可以位于同一个控制器中,也可以位于 @ControllerAdvice 类中。