实现数据解析器
在 Spring Boot 中编写解析器函数,从各种来源获取已定义 GraphQL 字段的数据。
实现数据解析器 是 CoddyKit 上的免费 GraphQL APIs with Spring Boot 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 GraphQL APIs with Spring Boot 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 GraphQL APIs with Spring Boot 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
What are Data Resolvers?
Welcome! In GraphQL, clients ask for specific data. But how does your server know where to get that data?
That's where Data Resolvers come in! A resolver is a function or method that knows how to fetch the data for a specific field in your GraphQL schema.
- They act as the bridge between your schema and your data sources (like databases, APIs, or even simple in-memory lists).
- Each field in your schema needs a resolver, implicitly or explicitly.
Resolvers in Spring for GraphQL
Spring for GraphQL makes implementing resolvers straightforward. It uses annotations to map Java methods directly to fields in your GraphQL schema.
You'll typically write these resolver methods inside Spring @Controller classes. Spring automatically scans these controllers and connects their methods to the GraphQL schema fields based on naming conventions or explicit annotations.
Your First Root Query Resolver
Let's create a simple resolver for a root query. We'll define a basic hello field that returns a greeting string.
First, imagine our schema has:
type Query {
hello: String
}Now, let's write the Java resolver:
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
@Controller
public class GreetingController {
@QueryMapping
public String hello() {
return "Hello from CoddyKit!";
}
}Resolving Custom Objects
Resolvers aren't just for simple strings. They can return custom Java objects too! Let's define a simple Book class and a resolver to return it.
Assume our schema has:
type Book {
id: ID
title: String
author: String
}
type Query {
firstBook: Book
}Here's the Book class and a resolver:
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
// A simple data class for our Book
record Book(String id, String title, String author) {}
@Controller
public class BookController {
@QueryMapping
public Book firstBook() {
return new Book("book-1", "The Great Journey", "Alice Wonderland");
}
}Mocking Data Sources
For our examples, we won't connect to a real database. Instead, we'll use an in-memory list to simulate a data source. This keeps our code simple and focused on resolvers.
In a real application, your resolvers would interact with:
- Databases (SQL, NoSQL)
- Other REST or GraphQL APIs
- Message queues
- File systems
The resolver's job is just to get the data, no matter the source!
Implementing a List Resolver
Often, you'll want to return a list of objects. Our BookController can be updated to provide a list of books from a mock source.
If our schema has:
type Query {
allBooks: [Book]
}Here's how we'd implement the resolver:
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
import java.util.List;
import java.util.ArrayList;
record Book(String id, String title, String author) {}
@Controller
public class BookListController {
private final List<Book> books = new ArrayList<>(List.of(
new Book("b-1", "The Moonstone", "Wilkie Collins"),
new Book("b-2", "Pride and Prejudice", "Jane Austen"),
new Book("b-3", "1984", "George Orwell")
));
@QueryMapping
public List<Book> allBooks() {
return books;
}
}Resolving by ID with Arguments
Queries often need arguments, like searching for a book by its ID. Resolvers can easily accept these arguments.
If our schema has:
type Query {
bookById(id: ID!): Book
}We use the @Argument annotation in Spring for GraphQL:
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
import java.util.List;
import java.util.ArrayList;
record Book(String id, String title, String author) {}
@Controller
public class BookByIdController {
private final List<Book> books = new ArrayList<>(List.of(
new Book("b-1", "The Moonstone", "Wilkie Collins"),
new Book("b-2", "Pride and Prejudice", "Jane Austen")
));
@QueryMapping
public Book bookById(@Argument String id) {
return books.stream()
.filter(book -> book.id().equals(id))
.findFirst()
.orElse(null);
}
}Field-Level Resolvers
Sometimes, a field on an object itself needs a separate resolver. For example, if the author of a Book was a complex object needing its own lookup.
Let's say Book has an authorId, and we need to fetch the full Author object. We use @SchemaMapping for these non-root fields.
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;
record Book(String id, String title, String authorId) {}
record Author(String id, String name) {}
@Controller
public class AuthorResolver {
// This resolver is for the 'author' field on a 'Book' object
@SchemaMapping
public Author author(Book book) {
// In a real app, you'd fetch from a data source using book.authorId()
if ("auth-1".equals(book.authorId())) {
return new Author(book.authorId(), "Wilkie Collins");
}
return new Author(book.authorId(), "Unknown Author");
}
}Complete Resolver Application
Let's put everything together into a runnable Spring Boot application! This example includes resolvers for listing books, finding a book by ID, and resolving an author for a book.
Try running this and querying it with a GraphQL client!
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;
import java.util.List;
import java.util.ArrayList;
// Data classes
record Book(String id, String title, String authorId) {}
record Author(String id, String name) {}
@SpringBootApplication
public class GraphQLResolversApp {
public static void main(String[] args) {
SpringApplication.run(GraphQLResolversApp.class, args);
}
}
@Controller
class BookDataController {
private final List<Book> books = new ArrayList<>(List.of(
new Book("b-1", "The Moonstone", "auth-1"),
new Book("b-2", "Pride and Prejudice", "auth-2"),
new Book("b-3", "1984", "auth-3")
));
@QueryMapping
public List<Book> allBooks() {
return books;
}
@QueryMapping
public Book bookById(@Argument String id) {
return books.stream()
.filter(book -> book.id().equals(id))
.findFirst()
.orElse(null);
}
// Field-level resolver for 'author' on 'Book'
@SchemaMapping
public Author author(Book book) {
// Mocking author data lookup
return switch (book.authorId()) {
case "auth-1" -> new Author("auth-1", "Wilkie Collins");
case "auth-2" -> new Author("auth-2", "Jane Austen");
case "auth-3" -> new Author("auth-3", "George Orwell");
default -> new Author(book.authorId(), "Unknown Author");
};
}
}Understanding Resolver Mapping
Which of the following statements about GraphQL resolvers in Spring Boot are TRUE?
Recap: Your Resolver Journey
You've taken a big step in building GraphQL APIs!
- We learned that resolvers are the core logic for fetching data.
- Spring for GraphQL uses
@Controllerwith@QueryMappingfor root queries and@SchemaMappingfor nested fields. - Resolvers can return simple types, custom objects, and lists.
- You can pass arguments to resolvers using the
@Argumentannotation.
Next, you'll learn how to execute these queries using tools like GraphiQL!
常见问题解答
「实现数据解析器」课时是免费的吗?
是的 — 「实现数据解析器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 GraphQL APIs with Spring Boot 课程的其余内容,请升级到 CoddyKit PRO。 GraphQL APIs with Spring Boot 课程共包含 4 节课。
「实现数据解析器」这节课中我会学到什么?
在 Spring Boot 中编写解析器函数,从各种来源获取已定义 GraphQL 字段的数据。 你通过在浏览器中直接运行的动手代码来练习 GraphQL APIs with Spring Boot,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 GraphQL APIs with Spring Boot 需要有经验吗?
无需任何先前经验。CoddyKit 上的 GraphQL APIs with Spring Boot 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「实现数据解析器」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 GraphQL APIs with Spring Boot 课中编写并运行代码吗?
能。每节 GraphQL APIs with Spring Boot 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。