Build GraphQL APIs in Spring Boot 3 with GraphQL SPQR – A Step‑by‑Step Guide
This article walks you through creating a GraphQL API in Spring Boot 3 using the GraphQL SPQR library, covering environment setup, model and service definitions, resolver implementation, controller configuration, and optional starter usage with full code examples.
1. Introduction
Spring Boot 3.5.0 is used as the base platform for the tutorial. The goal is to demonstrate how to add a GraphQL API to a Spring Boot project with minimal configuration by leveraging the GraphQL SPQR library.
2. What is GraphQL?
GraphQL is a query language and runtime for APIs, originally developed by Facebook. It allows clients to request exactly the data they need via a single endpoint, reducing over‑fetching and under‑fetching and improving front‑back communication efficiency.
3. What is GraphQL SPQR?
GraphQL SPQR simplifies adding a GraphQL API to any Java project by dynamically generating the GraphQL schema from Java code. Its key benefits include:
Minimal configuration (about three lines of code)
Highly configurable and extensible without mandatory conventions
Supports rapid prototyping and iteration without boilerplate
Works with legacy codebases without source modification
Very few dependencies
4. Environment Preparation
Add the following Maven dependency to your project:
<dependency>
<groupId>io.leangen.graphql</groupId>
<artifactId>spqr</artifactId>
<version>0.12.4</version>
</dependency>5. Define Model Data
public record Book(Integer id, String author, String title) {}6. Define Service Interface
public interface IBookService {
Book getBookWithTitle(String title);
List<Book> getAllBooks();
Book addBook(Book book);
Book updateBook(Book book);
boolean deleteBook(Book book);
}7. Service Implementation (In‑Memory CRUD)
@Service
public class BookService implements IBookService {
private static final Set<Book> BOOKS = new HashSet<>();
@PostConstruct
public void init() {
Book book1 = new Book(1, "pack_xg", "Spring Boot 3实战案例200讲");
Book book2 = new Book(2, "pack_xg", "Spring Cloud底层源码剖析");
BOOKS.add(book1);
BOOKS.add(book2);
}
@Override
public Book getBookWithTitle(String title) {
return BOOKS.stream()
.filter(b -> b.title().equals(title))
.findFirst()
.orElse(null);
}
@Override
public List<Book> getAllBooks() {
return new ArrayList<>(BOOKS);
}
@Override
public Book addBook(Book book) {
BOOKS.add(book);
return book;
}
@Override
public Book updateBook(Book book) {
BOOKS.removeIf(b -> Objects.equals(b.id(), book.id()));
BOOKS.add(book);
return book;
}
@Override
public boolean deleteBook(Book book) {
return BOOKS.remove(book);
}
}8. Resolver (Expose GraphQL Operations)
@Service
public class BookResolver {
private final IBookService bookService;
public BookResolver(IBookService bookService) {
this.bookService = bookService;
}
@GraphQLQuery(name = "queryBookByTitle")
public Book queryBookByTitle(@GraphQLArgument(name = "title") String title) {
return bookService.getBookWithTitle(title);
}
@GraphQLQuery(name = "getAllBooks", description = "查询所有图书")
public List<Book> getAllBooks() {
return bookService.getAllBooks();
}
@GraphQLMutation(name = "addBook")
public Book addBook(@GraphQLArgument(name = "book") Book book) {
return bookService.addBook(book);
}
@GraphQLMutation(name = "updateBook")
public Book updateBook(@GraphQLArgument(name = "book") Book book) {
return bookService.updateBook(book);
}
@GraphQLMutation(name = "deleteBook")
public void deleteBook(@GraphQLArgument(name = "book") Book book) {
bookService.deleteBook(book);
}
}9. Controller (Manual Configuration)
@RestController
@RequestMapping("/books")
public class BookController {
private final GraphQL graphQL;
public BookController(BookResolver bookResolver) {
GraphQLSchema schema = new GraphQLSchemaGenerator()
.withBasePackages("com.pack")
.withOperationsFromSingleton(bookResolver)
.generate();
this.graphQL = new GraphQL.Builder(schema).build();
}
@PostMapping(value = "/graphql")
public Map<String, Object> execute(@RequestBody Map<String, String> body) throws GraphQLException {
ExecutionResult result = graphQL.execute(body.get("query"));
return result.getData();
}
}After starting the application, you can test queries and mutations using tools like Postman.
10. Using the GraphQL‑SPQR Spring Boot Starter
Instead of writing the controller manually, you can add the starter dependency:
<properties>
<graphql-java.version>21.4</graphql-java.version>
</properties>
<dependency>
<groupId>io.leangen.graphql</groupId>
<artifactId>graphql-spqr-spring-boot-starter</artifactId>
<version>1.0.1</version>
</dependency>Annotate your service class with @GraphQLApi (no need for a separate controller). The starter automatically exposes the GraphQL endpoint at /graphql and provides a default controller.
11. Additional Configuration
The starter allows further customization via application properties (e.g., package scanning, schema generation options). Refer to the library documentation for advanced settings.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
