此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring GraphQL 1.3.1! |
此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring GraphQL 1.3.1! |
Spring for GraphQL 支持服务器通过 HTTP、WebSocket 和 RSocket。
HTTP的
GraphQlHttpHandler
处理 GraphQL over HTTP 请求,并委托给 Interception 链执行请求。有两种变体,一种用于
Spring MVC 和一个用于 Spring WebFlux 的 MVC。两者都异步处理请求,并且具有
等效功能,但分别依赖于阻塞和非阻塞 I/O
编写 HTTP 响应。
请求必须使用 HTTP POST 作为内容类型和 GraphQL 请求详细信息
作为 JSON 包含在请求正文中,如建议的 GraphQL over HTTP 规范中所定义。
成功解码 JSON 正文后,HTTP 响应状态始终为 200 (OK),
GraphQL 请求执行的任何错误都显示在 GraphQL 响应的“错误”部分。
媒体类型的默认和首选选择是 ,但也受支持,如规范中所述。"application/json"
"application/graphql-response+json"
"application/json"
GraphQlHttpHandler
可以通过声明 bean 并使用 from Spring MVC 或 WebFlux 创建路由来公开为 HTTP 端点。Boot Starter 执行此操作,请参阅 Web 终结点部分
详细信息,或检查或它包含实际配置。RouterFunction
RouterFunctions
GraphQlWebMvcAutoConfiguration
GraphQlWebFluxAutoConfiguration
此存储库的 1.0.x 分支包含一个 Spring MVC HTTP 示例应用程序。
文件上传
作为一种协议,GraphQL 专注于文本数据的交换。这不包括二进制文件 数据,例如图像,但有一个单独的、非正式的 graphql-multipart-request-spec,允许使用 GraphQL over HTTP 上传文件。
Spring for GraphQL 不支持直接。
虽然该规范确实提供了统一的 GraphQL API 的好处,但实际经验具有
导致了许多问题,并且最佳实践建议已经发展,有关更详细的讨论,请参阅 Apollo Server 文件上传最佳实践。graphql-multipart-request-spec
如果您想在应用程序中使用,您可以
通过库 multipart-spring-graphql 执行此操作。graphql-multipart-request-spec
网络套接字
GraphQlWebSocketHandler
根据 graphql-ws 库中定义的协议处理 GraphQL over WebSocket 请求。使用的主要原因
GraphQL over WebSocket 是允许发送 GraphQL 流的订阅
响应,但它也可用于具有单个响应的常规查询。
处理程序将每个请求委托给 Interception 链,以便进一步
请求执行。
基于 WebSocket 协议的 GraphQL
有两个这样的协议,一个在 subscriptions-transport-ws 库中,另一个在 graphql-ws 库中。前者不活跃且 继任者是后者。阅读这篇博文了解历史。 |
有两种变体,一种用于 Spring MVC,另一种用于
Spring WebFlux 中。两者都异步处理请求,并具有等效的功能。
WebFlux 处理程序还使用非阻塞 I/O 和背压来流式传输消息,
这很好用,因为在 GraphQL Java 中,订阅响应是 反应式流 .GraphQlWebSocketHandler
Publisher
该项目列出了许多供客户使用的配方。graphql-ws
GraphQlWebSocketHandler
可以通过声明 Bean 并使用它来将处理程序映射到 URL 路径来公开为 WebSocket 端点。默认情况下,
Boot Starter 不会公开 GraphQL over WebSocket 端点,但很容易
通过为终结点路径添加属性来启用它。有关详细信息,请参阅 Web 终结点部分,或查看 或 以获取实际的启动启动器配置。SimpleUrlHandlerMapping
GraphQlWebMvcAutoConfiguration
GraphQlWebFluxAutoConfiguration
此存储库的 1.0.x 分支包含一个 WebFlux WebSocket 示例应用程序。
基于 WebSocket 协议的 GraphQL
有两个这样的协议,一个在 subscriptions-transport-ws 库中,另一个在 graphql-ws 库中。前者不活跃且 继任者是后者。阅读这篇博文了解历史。 |
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);
}
}
拦截
服务器传输允许在 GraphQL Java 引擎之前和之后拦截请求 调用以处理请求。
WebGraphQlInterceptor
HTTP 和 WebSocket 传输调用
0 或更多,后跟一个调用
GraphQL Java 引擎。 允许应用程序拦截
传入请求,然后执行下列操作之一:WebGraphQlInterceptor
ExecutionGraphQlService
WebGraphQlInterceptor
-
检查 HTTP 请求详细信息
-
自定义
graphql.ExecutionInput
-
添加 HTTP 响应标头
-
自定义
graphql.ExecutionResult
例如,拦截器可以将 HTTP 请求标头传递给:DataFetcher
import java.util.Collections;
import reactor.core.publisher.Mono;
import org.springframework.graphql.data.method.annotation.ContextValue;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.WebGraphQlRequest;
import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.stereotype.Controller;
class RequestHeaderInterceptor implements WebGraphQlInterceptor { (1)
@Override
public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
String value = request.getHeaders().getFirst("myHeader");
request.configureExecutionInput((executionInput, builder) ->
builder.graphQLContext(Collections.singletonMap("myHeader", value)).build());
return chain.next(request);
}
}
@Controller
class MyContextValueController { (2)
@QueryMapping
Person person(@ContextValue String myHeader) {
...
}
}
1 | Interceptor 将 HTTP 请求标头值添加到 GraphQLContext 中 |
2 | 数据控制器方法访问值 |
相反,拦截器可以访问控制器添加到 的值:GraphQLContext
import graphql.GraphQLContext;
import reactor.core.publisher.Mono;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.WebGraphQlRequest;
import org.springframework.graphql.server.WebGraphQlResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Controller;
// Subsequent access from a WebGraphQlInterceptor
class ResponseHeaderInterceptor implements WebGraphQlInterceptor {
@Override
public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) { (2)
return chain.next(request).doOnNext((response) -> {
String value = response.getExecutionInput().getGraphQLContext().get("cookieName");
ResponseCookie cookie = ResponseCookie.from("cookieName", value).build();
response.getResponseHeaders().add(HttpHeaders.SET_COOKIE, cookie.toString());
});
}
}
@Controller
class MyCookieController {
@QueryMapping
Person person(GraphQLContext context) { (1)
context.put("cookieName", "123");
...
}
}
1 | 控制器为GraphQLContext |
2 | Interceptor 使用该值添加 HTTP 响应标头 |
WebGraphQlHandler
可以修改,例如检查和修改
在执行开始之前引发的请求验证错误,并且不能
处理方式为:ExecutionResult
DataFetcherExceptionResolver
import java.util.List;
import graphql.GraphQLError;
import graphql.GraphqlErrorBuilder;
import reactor.core.publisher.Mono;
import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.WebGraphQlRequest;
import org.springframework.graphql.server.WebGraphQlResponse;
class RequestErrorInterceptor implements WebGraphQlInterceptor {
@Override
public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
return chain.next(request).map((response) -> {
if (response.isValid()) {
return response; (1)
}
List<GraphQLError> errors = response.getErrors().stream() (2)
.map((error) -> {
GraphqlErrorBuilder<?> builder = GraphqlErrorBuilder.newError();
// ...
return builder.build();
})
.toList();
return response.transform((builder) -> builder.errors(errors).build()); (3)
});
}
}
1 | 如果具有非 null 值的“data”键,则返回相同的值ExecutionResult |
2 | 检查并转换 GraphQL 错误 |
3 | 使用修改后的错误更新ExecutionResult |
RSocketQlInterceptor
与 WebGraphQlInterceptor
类似,允许拦截
GraphQL over RSocket 请求在 GraphQL Java 引擎执行之前和之后。您可以使用
这将自定义 和 .RSocketQlInterceptor
graphql.ExecutionInput
graphql.ExecutionResult
1 | Interceptor 将 HTTP 请求标头值添加到 GraphQLContext 中 |
2 | 数据控制器方法访问值 |
1 | 控制器为GraphQLContext |
2 | Interceptor 使用该值添加 HTTP 响应标头 |
1 | 如果具有非 null 值的“data”键,则返回相同的值ExecutionResult |
2 | 检查并转换 GraphQL 错误 |
3 | 使用修改后的错误更新ExecutionResult |