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 终结点 部分以获取详细信息,或检查它包含的 GraphQlWebMvcAutoConfiguration
或 GraphQlWebFluxAutoConfiguration
以获取实际配置。
此存储库的 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 终结点 部分以获取详细信息,或检查 GraphQlWebMvcAutoConfiguration
或 GraphQlWebFluxAutoConfiguration
以获取实际 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
HTTP 和 WebSocket 传输调用一个 0 或更多 WebGraphQlInterceptor
的链,然后调用 GraphQL Java 引擎的 ExecutionGraphQlService
。WebGraphQlInterceptor
允许应用程序拦截传入请求并执行以下操作之一:
-
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.ExecutionInput
和 graphql.ExecutionResult
。