GraphQL API с Java: пошаговый туториал для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в GraphQL API с Java

GraphQL — это язык запросов для API, который позволяет клиентам запрашивать только те данные, которые им действительно нужны. В отличие от REST, где каждый эндпоинт возвращает фиксированную структуру данных, GraphQL даёт гибкость и уменьшает количество запросов. В этом туториале мы создадим полноценное GraphQL API на Java с использованием Spring Boot и библиотеки graphql-java. Вы узнаете, как настроить проект, определить схему, написать резолверы и обрабатывать запросы и мутации. Все примеры кода готовы к запуску.

1. Настройка проекта и зависимости

Для начала создадим новый проект Spring Boot. Мы будем использовать Maven, но вы можете адаптировать пример под Gradle. Добавьте следующие зависимости в pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java</artifactId>
    <version>21.0</version>
</dependency>
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java-spring-boot-starter-webmvc</artifactId>
    <version>2021-06-28T00-00-00-6e3b7b2</version>
</dependency>

После добавления зависимостей создайте основной класс приложения:

@SpringBootApplication
public class GraphqlApplication {
    public static void main(String[] args) {
        SpringApplication.run(GraphqlApplication.class, args);
    }
}

Теперь настроим точку входа GraphQL. Создайте файл application.yml в папке resources:

graphql:
  servlet:
    mapping: /graphql
    enabled: true
    cors-enabled: true

Готово! Базовая структура проекта запускается. Далее переходим к определению схемы.

2. Определение схемы GraphQL

Схема — это ядро GraphQL API. Она описывает типы данных, запросы и мутации. Создадим файл schema.graphqls в папке src/main/resources:

type Book {
    id: ID!
    title: String!
    author: String!
    year: Int
}

type Query {
    books: [Book]
    bookById(id: ID!): Book
}

type Mutation {
    addBook(title: String!, author: String!, year: Int): Book
    deleteBook(id: ID!): Boolean
}

Здесь мы определили:

  • Book — объект с полями id, title, author и year.
  • Query — точки входа для чтения данных (список книг и поиск по ID).
  • Mutation — операции изменения данных (добавление и удаление книги).

Теперь нам нужно загрузить эту схему в приложение. Создадим конфигурационный класс:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;

import java.io.File;
import java.io.IOException;

@Configuration
public class GraphqlConfig {

    @Bean
    public GraphQL graphQL() throws IOException {
        File schemaFile = new File("src/main/resources/schema.graphqls");
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(schemaFile);
        RuntimeWiring wiring = buildWiring();
        GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring);
        return GraphQL.newGraphQL(schema).build();
    }

    private RuntimeWiring buildWiring() {
        return RuntimeWiring.newRuntimeWiring()
                .type("Query", builder -> builder
                        .dataFetcher("books", new BooksDataFetcher())
                        .dataFetcher("bookById", new BookByIdDataFetcher()))
                .type("Mutation", builder -> builder
                        .dataFetcher("addBook", new AddBookDataFetcher())
                        .dataFetcher("deleteBook", new DeleteBookDataFetcher()))
                .build();
    }
}

3. Создание резолверов (DataFetcher)

Резолверы — это Java-классы, которые реализуют логику получения данных для каждого поля схемы. Сначала создадим простую имитацию базы данных — сервис с HashMap:

import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.*;

@Service
public class BookService {
    private Map<String, Book> books = new HashMap<>();

    @PostConstruct
    public void init() {
        books.put("1", new Book("1", "Война и мир", "Лев Толстой", 1869));
        books.put("2", new Book("2", "Преступление и наказание", "Фёдор Достоевский", 1866));
    }

    public List<Book> getAllBooks() {
        return new ArrayList<>(books.values());
    }

    public Book getBookById(String id) {
        return books.get(id);
    }

    public Book addBook(String title, String author, int year) {
        String id = String.valueOf(books.size() + 1);
        Book book = new Book(id, title, author, year);
        books.put(id, book);
        return book;
    }

    public boolean deleteBook(String id) {
        return books.remove(id) != null;
    }
}

Теперь создадим класс модели Book:

public class Book {
    private String id;
    private String title;
    private String author;
    private int year;

    public Book(String id, String title, String author, int year) {
        this.id = id;
        this.title = title;
        this.author = author;
        this.year = year;
    }

    // геттеры и сеттеры
    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 getYear() { return year; }
    public void setYear(int year) { this.year = year; }
}

Теперь напишем резолверы. Каждый из них реализует интерфейс DataFetcher:

import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BooksDataFetcher implements DataFetcher<List<Book>> {
    @Autowired
    private BookService bookService;

    @Override
    public List<Book> get(DataFetchingEnvironment env) {
        return bookService                

Блоги

Рекомендаций по книгам