Spring for GraphQL
如果您想構建 GraphQL 應用程式,可以利用 Spring Boot 為 Spring for GraphQL 提供的自動配置。Spring for GraphQL 專案基於 GraphQL Java。您至少需要 spring-boot-starter-graphql 啟動器。由於 GraphQL 獨立於傳輸協議,您還需要在應用程式中有一個或多個額外的啟動器,以透過 Web 暴露您的 GraphQL API。
| 啟動器 | 傳輸 | 實現 |
|---|---|---|
|
HTTP |
Spring MVC |
|
WebSocket |
用於 Servlet 應用程式的 WebSocket |
|
HTTP, WebSocket |
Spring WebFlux |
|
TCP, WebSocket |
基於 Reactor Netty 的 Spring WebFlux |
GraphQL Schema
Spring GraphQL 應用程式在啟動時需要定義一個 schema。預設情況下,您可以在 src/main/resources/graphql/** 下編寫 ".graphqls" 或 ".gqls" schema 檔案,Spring Boot 會自動識別它們。您可以透過 spring.graphql.schema.locations 自定義位置,並透過 spring.graphql.schema.file-extensions 自定義副檔名。
如果您希望 Spring Boot 檢測該位置下所有應用程式模組和依賴項中的 schema 檔案,您可以將 spring.graphql.schema.locations 設定為 "classpath*:graphql/**/"(注意 classpath*: 字首)。 |
在以下章節中,我們將考慮這個示例 GraphQL schema,它定義了兩種型別和兩個查詢。
type Query {
greeting(name: String! = "Spring"): String!
project(slug: ID!): Project
}
""" A Project in the Spring portfolio """
type Project {
""" Unique string id used in URLs """
slug: ID!
""" Project name """
name: String!
""" URL of the git repository """
repositoryUrl: String!
""" Current support status """
status: ProjectStatus!
}
enum ProjectStatus {
""" Actively supported by the Spring team """
ACTIVE
""" Supported by the community """
COMMUNITY
""" Prototype, not officially supported yet """
INCUBATING
""" Project being retired, in maintenance mode """
ATTIC
""" End-Of-Lifed """
EOL
}
預設情況下,schema 上允許進行欄位自檢,因為 GraphiQL 等工具需要它。如果您不希望暴露關於 schema 的資訊,可以透過將 spring.graphql.schema.introspection.enabled 設定為 false 來停用自檢。 |
GraphQL RuntimeWiring
GraphQL Java 的 RuntimeWiring.Builder 可用於註冊自定義標量型別、指令、型別解析器、DataFetcher 等。您可以在 Spring 配置中宣告 RuntimeWiringConfigurer bean,以訪問 RuntimeWiring.Builder。Spring Boot 會檢測此類 bean 並將其新增到 GraphQlSource 構建器中。
然而,通常應用程式不會直接實現 DataFetcher,而是會建立帶註解的控制器。Spring Boot 將自動檢測帶有註解處理方法的 @Controller 類,並將它們註冊為 DataFetcher。以下是我們使用 @Controller 類實現問候查詢的示例:
-
Java
-
Kotlin
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
@Controller
public class GreetingController {
@QueryMapping
public String greeting(@Argument String name) {
return "Hello, " + name + "!";
}
}
import org.springframework.graphql.data.method.annotation.Argument
import org.springframework.graphql.data.method.annotation.QueryMapping
import org.springframework.stereotype.Controller
@Controller
class GreetingController {
@QueryMapping
fun greeting(@Argument name: String): String {
return "Hello, $name!"
}
}
Querydsl 和 QueryByExample 倉庫支援
Spring Data 支援 Querydsl 和 QueryByExample 倉庫。Spring GraphQL 可以將 Querydsl 和 QueryByExample 倉庫配置為DataFetcher。
使用 @GraphQlRepository 註解並擴充套件以下介面之一的 Spring Data 倉庫:
將被 Spring Boot 檢測到,並被視為匹配頂級查詢的 DataFetcher 候選。
傳輸
HTTP 和 WebSocket
GraphQL HTTP 端點預設位於 HTTP POST /graphql。它還支援透過 Server Sent Events 僅用於訂閱的 "text/event-stream" 媒體型別。路徑可以透過 spring.graphql.http.path 進行自定義。
Spring MVC 和 Spring WebFlux 的 HTTP 端點由一個帶有 @Order 值為 0 的 RouterFunction bean 提供。如果您定義自己的 RouterFunction bean,您可能需要新增適當的 @Order 註解,以確保它們正確排序。 |
GraphQL WebSocket 端點預設關閉。要啟用它:
-
對於 Servlet 應用程式,新增 WebSocket 啟動器
spring-boot-starter-websocket -
對於 WebFlux 應用程式,無需額外依賴
-
對於兩者,必須設定
spring.graphql.websocket.path應用程式屬性
Spring GraphQL 提供了一個Web 攔截模型。這對於從 HTTP 請求頭中檢索資訊並將其設定在 GraphQL 上下文中,或者從同一上下文中獲取資訊並將其寫入響應頭非常有用。使用 Spring Boot,您可以宣告一個 WebGraphQlInterceptor bean,以便將其註冊到 Web 傳輸中。
Spring MVC 和 Spring WebFlux 支援 CORS(跨域資源共享)請求。CORS 是 GraphQL 應用程式 Web 配置的關鍵部分,這些應用程式透過不同域的瀏覽器訪問。
Spring Boot 在 spring.graphql.cors.* 名稱空間下支援許多配置屬性;這是一個簡短的配置示例:
-
屬性
-
YAML
spring.graphql.cors.allowed-origins=https://example.org
spring.graphql.cors.allowed-methods=GET,POST
spring.graphql.cors.max-age=1800s
spring:
graphql:
cors:
allowed-origins: "https://example.org"
allowed-methods: GET,POST
max-age: 1800s
RSocket
RSocket 也作為傳輸協議受支援,它構建在 WebSocket 或 TCP 之上。一旦RSocket 伺服器配置完成,我們就可以使用 spring.graphql.rsocket.mapping 在特定路由上配置我們的 GraphQL 處理程式。例如,將該對映配置為 "graphql" 意味著我們可以在使用 RSocketGraphQlClient 傳送請求時將其用作路由。
Spring Boot 自動配置一個 RSocketGraphQlClient.Builder<?> bean,您可以將其注入到您的元件中。
-
Java
-
Kotlin
@Component
public class RSocketGraphQlClientExample {
private final RSocketGraphQlClient graphQlClient;
public RSocketGraphQlClientExample(RSocketGraphQlClient.Builder<?> builder) {
this.graphQlClient = builder.tcp("example.spring.io", 8181).route("graphql").build();
}
@Component
class RSocketGraphQlClientExample(private val builder: RSocketGraphQlClient.Builder<*>) {
然後傳送請求:include-code::RSocketGraphQlClientExample[tag=request]
異常處理
Spring GraphQL 允許應用程式註冊一個或多個 Spring DataFetcherExceptionResolver 元件,這些元件會按順序呼叫。異常必須解析為 GraphQLError 物件的列表,詳情請參閱 Spring GraphQL 異常處理文件。Spring Boot 將自動檢測 DataFetcherExceptionResolver bean 並將其註冊到 GraphQlSource.Builder。
GraphiQL 和 Schema Printer
Spring GraphQL 提供了基礎設施,以幫助開發人員在使用或開發 GraphQL API 時進行工作。
Spring GraphQL 附帶一個預設的 GraphiQL 頁面,預設暴露在 "/graphiql"。此頁面預設停用,可以透過 spring.graphql.graphiql.enabled 屬性開啟。許多暴露此頁面的應用程式更喜歡自定義構建。在開發過程中,預設實現非常有用,這就是為什麼它在開發期間透過 spring-boot-devtools 自動暴露。
當 spring.graphql.schema.printer.enabled 屬性啟用時,您還可以選擇在 /graphql/schema 處以文字格式暴露 GraphQL schema。