Server Transports

Spring for GraphQL 支持 HTTP、WebSocket 和 RSocket 上的 GraphQL 请求的服务器处理。

HTTP

GraphQlHttpHandler 处理通过 HTTP 请求的 GraphQL,并委托给 Interception 链进行请求执行。有两种变体,一种适用于 Spring MVC,一种适用于 Spring WebFlux。两者都异步处理请求,并且具有同等功能,但分别依赖于阻塞式或非阻塞式 I/O 来编写 HTTP 响应。

请求必须使用 HTTP POST,其中 "application/json" 为内容类型,并将在请求正文中以 JSON 形式包含 GraphQL 请求详细信息,如此提议的 GraphQL over HTTP 规范中所定义。一旦成功解码 JSON 正文,HTTP 响应状态始终为 200(正常),并且 GraphQL 请求执行中的任何错误都会显示在 GraphQL 响应的“错误”部分。媒体类型的默认首选是 "application/graphql-response+json",但 "application/json" 也受支持,如此规范中所述。

通过声明 RouterFunction bean 以及使用 Spring MVC 或 WebFlux 中的 RouterFunctions 来创建路由,可以将 GraphQlHttpHandler 作为一个 HTTP 终结点公开。Boot Starter 这样做,请参阅 Web 终结点 部分以获取详细信息,或检查它包含的 GraphQlWebMvcAutoConfigurationGraphQlWebFluxAutoConfiguration 以获取实际配置。

此存储库的 1.0.x 分支包含一个 Spring MVC HTTP 样本 应用程序。

Server-Sent Events

GraphQlSseHandler 与上面列出的 HTTP 处理器非常相似,但这次是通过 Server-Sent Events 协议处理 HTTP 上的 GraphQL 请求。通过此传输,客户端必须向使用 “application/json” 作为内容类型并且在请求正文中包含 JSON 形式的 GraphQL 请求详细信息的端点发送 HTTP POST 请求;与传统的 HTTP 类型唯一不同的是,客户端必须向 “Accept” 请求头发送 “text/event-stream”。响应将作为一或多个 Server-Sent Events 发送。

这也在建议的 GraphQL over HTTP 规范中进行了定义。Spring for GraphQL 仅实现“明确连接模式”,因此应用程序必须考虑可扩展性问题,以及采用 HTTP/2 作为底层传输是否会有帮助。

GraphQlSseHandler 的主要用例是 WebSocket transport 的替代方案,接收的响应是一个订阅操作的项目流。其他类型的操作(如查询和突变)在此不受支持,并且应该使用普通 JSON 通过 HTTP 传输变体。

File Upload

作为一种协议,GraphQL 专注于文本数据的交换。这不包括二进制数据(如图像),但有一个单独的非正式 graphql-multipart-request-spec,它允许通过 HTTP 将文件上传到 GraphQL。

Spring for GraphQL 并不直接支持 graphql-multipart-request-spec。虽然规范确实提供了统一 GraphQL API 的好处,但实际经验引发了许多问题,最佳做法建议也在不断演进,请参见 Apollo Server File Upload Best Practices 进行更详细的探讨。

如果您想在应用程序中使用 graphql-multipart-request-spec,您可以通过库 multipart-spring-graphql 来实现。

WebSocket

GraphQlWebSocketHandler 根据 protocol 库中定义的 graphql-ws 处理通过 WebSocket 请求的 GraphQL。使用通过 WebSocket 进行 GraphQL 的主要原因是订阅,它允许发送一个 GraphQL 响应流,但也可以用于具有单个响应的常规查询。该处理程序将每个请求委托给 Interception 链,以进行进一步的请求执行。

GraphQL Over WebSocket Protocols

有两种这样的协议,一个在 subscriptions-transport-ws 库中,另一个在 graphql-ws 库中。前者处于非活动状态,后者取而代之。阅读本 blog post 以了解历史。

GraphQlWebSocketHandler 有两个变体,一个用于 Spring MVC,另一个用于 Spring WebFlux。它们都异步处理请求并具有等效的功能。WebFlux 处理程序还使用非阻塞 I/O 和反压来流式传输消息,这很好用,因为在 GraphQL Java 中订阅响应是 Reactive Streams Publisher

graphql-ws 项目列出了很多可供客户端使用的 recipes

通过声明 SimpleUrlHandlerMapping bean 并使用它将处理程序映射到 URL 路径,可以将 GraphQlWebSocketHandler 公开为 WebSocket 终结点。默认情况下,Boot Starter 不公开通过 WebSocket 的 GraphQL 终结点,但通过添加一个用于终结点路径的属性即可轻松启用它。请参阅 Web 终结点 部分以获取详细信息,或检查 GraphQlWebMvcAutoConfigurationGraphQlWebFluxAutoConfiguration 以获取实际 Boot starter 配置。

此存储库的 1.0.x 分支包含一个 WebFlux WebSocket 样本 应用程序。

RSocket

GraphQlRSocketHandler 处理 GraphQL over RSocket 请求。期待查询和突变,并将其作为 RSocket request-response 交互来处理,而订阅则作为 request-stream 来处理。

GraphQlRSocketHandler 可以作为映射到 GraphQL 请求路由的 @Controller 中的委托使用。例如:

import java.util.Map;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import org.springframework.graphql.server.GraphQlRSocketHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.stereotype.Controller;

@Controller
public class GraphQlRSocketController {

	private final GraphQlRSocketHandler handler;

	GraphQlRSocketController(GraphQlRSocketHandler handler) {
		this.handler = handler;
	}

	@MessageMapping("graphql")
	public Mono<Map<String, Object>> handle(Map<String, Object> payload) {
		return this.handler.handle(payload);
	}

	@MessageMapping("graphql")
	public Flux<Map<String, Object>> handleSubscription(Map<String, Object> payload) {
		return this.handler.handleSubscription(payload);
	}
}

Interception

服务器传输允许在调用 GraphQL Java 引擎处理请求之前和之后拦截请求。

WebGraphQlInterceptor

HTTPWebSocket 传输调用一个 0 或更多 WebGraphQlInterceptor 的链,然后调用 GraphQL Java 引擎的 ExecutionGraphQlServiceWebGraphQlInterceptor 允许应用程序拦截传入请求并执行以下操作之一:

  • Check HTTP request details

  • Customize the graphql.ExecutionInput

  • Add HTTP response headers

  • Customize the graphql.ExecutionResult

例如,拦截器可以将 HTTP 请求头传递给 DataFetcher

include-code::RequestHeaderInterceptor[]<1> 拦截器将 HTTP 请求标头值添加到 GraphQLContext<2> 数据控制器方法访问值

相反,拦截器可以访问控制器添加到 GraphQLContext 的值:

include-code::ResponseHeaderInterceptor[]<1> 控制器将值添加到 GraphQLContext<2> 拦截器使用该值添加 HTTP 响应标头

WebGraphQlHandler 可以修改 ExecutionResult,例如,检查和修改在执行开始之前触发的请求验证错误,这些错误无法使用 DataFetcherExceptionResolver 处理:

include-code::RequestErrorInterceptor[]<1> 如果 ExecutionResult 具有非空值的“数据”键,则返回相同<2> 检查并转换 GraphQL 错误<3> 使用已修改的错误更新 ExecutionResult

使用 WebGraphQlHandler 配置 WebGraphQlInterceptor 链。这受 Boot Starter 支持,请参阅 Web 终结点

RSocketQlInterceptor

类似于 WebGraphQlInterceptor,一个 RSocketQlInterceptor 允许在 GraphQL Java 引擎执行之前和之后拦截通过 RSocket 请求的 GraphQL。您可以使用此功能自定义 graphql.ExecutionInputgraphql.ExecutionResult