Введение: Почему GraphQL и Java — это мощное сочетание
Современная разработка API требует гибкости и эффективности. REST API, несмотря на свою популярность, часто сталкивается с проблемой over-fetching (избыточная загрузка данных) или under-fetching (недостаток данных). GraphQL решает эти проблемы, позволяя клиенту запрашивать только те данные, которые ему нужны.
Java, в свою очередь, остаётся одним из самых надёжных языков для enterprise-разработки. Сочетание GraphQL и Java через фреймворк Spring Boot даёт мощный инструмент для создания масштабируемых и производительных API. В этом пошаговом туториале мы создадим простой GraphQL API с нуля.
Этот материал будет полезен Java-разработчикам, которые хотят освоить современный подход к построению API. Мы разберём ключевые концепции, напишем код и протестируем нашу реализацию.
1. Настройка проекта и зависимости
Первым шагом создадим базовый проект Spring Boot. Мы будем использовать Maven для управления зависимостями. Убедитесь, что у вас установлены JDK 17+ и Maven 3.8+.
Создайте файл pom.xml со следующим содержимым:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<groupId>com.example</groupId>
<artifactId>graphql-java-tutorial</artifactId>
<version>1.0.0</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
</dependency>
</dependencies>
</project>
После настройки pom.xml создайте главный класс приложения:
package com.example.graphqldemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GraphqlDemoApplication {
public static void main(String[] args) {
SpringApplication.run(GraphqlDemoApplication.class, args);
}
}
Теперь структура проекта готова. Переходим к определению данных.
2. Определение модели данных и GraphQL Schema
GraphQL Schema — это контракт между клиентом и сервером. Мы начнём с создания простой модели Book (книга).
2.1 Java-класс модели
package com.example.graphqldemo.model;
public class Book {
private String id;
private String title;
private String author;
private int pages;
public Book(String id, String title, String author, int pages) {
this.id = id;
this.title = title;
this.author = author;
this.pages = pages;
}
// Геттеры и сеттеры
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getAuthor() { return author; }
public void setAuthor(String author) { this.author = author; }
public int getPages() { return pages; }
public void setPages(int pages) { this.pages = pages; }
}
2.2 Файл schema.graphqls
Создайте файл src/main/resources/schema.graphqls:
type Book {
id: ID!
title: String!
author: String!
pages: Int!
}
type Query {
books: [Book!]!
bookById(id: ID!): Book
}
input BookInput {
title: String!
author: String!
pages: Int!
}
type Mutation {
addBook(input: BookInput!): Book
}
В этой схеме мы определили:
- Book — тип объекта с полями id, title, author, pages.
- Query — точки входа для получения данных (все книги и книга по ID).
- Mutation — точка входа для изменения данных (добавление книги).
- BookInput — входной тип для мутации.
3. Реализация DataFetcher и Resolver
Теперь нужно связать схему с Java-кодом. Для этого используются GraphQL Resolver (или DataFetcher).
3.1 Репозиторий (имитация БД)
Создадим простой репозиторий для хранения данных в памяти:
package com.example.graphqldemo.repository;
import com.example.graphqldemo.model.Book;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Repository
public class BookRepository {
private final List<Book> books = new ArrayList<>();
public BookRepository() {
// Добавим начальные данные
books.add(new Book("1", "1984", "George Orwell", 328));
books.add(new Book("2", "To Kill a Mockingbird", "Harper Lee", 281));
}
public List<Book> findAll() {
return books;
}
public Optional<Book> findById(String id) {
return books.stream().filter(b -> b.getId().equals(id)).findFirst();
}
public Book save(Book book) {
if (book.getId() == null) {
book.setId(UUID.randomUUID().toString());
}
books.add(book);
return book;
}
}
3.2 Resolver для Query
package com.example.graphqldemo.resolver;
import com.example.graphqldemo.model.Book;
import com