GraphQL API с Kotlin: пошаговый туториал на практике

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

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

Начать курс

Введение: Почему GraphQL и Kotlin?

В мире современной веб-разработки выбор правильного подхода к созданию API может определить успех всего проекта. GraphQL, разработанный Facebook, предлагает гибкую альтернативу REST, позволяя клиентам запрашивать только те данные, которые им действительно нужны. А Kotlin, современный язык программирования для JVM, добавляет к этому лаконичность, null-безопасность и мощную поддержку корутин.

В этом туториале мы на практике создадим полноценный GraphQL API с использованием Kotlin и фреймворка graphql-kotlin-spring-server. Вы узнаете, как настроить сервер, определить схему данных, написать резолверы и протестировать API. К концу статьи вы сможете самостоятельно внедрить GraphQL в свои проекты на Kotlin.

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

Для начала создадим новый проект на Spring Boot с поддержкой GraphQL. Мы будем использовать Gradle как систему сборки.

1.1. Создание базовой структуры

Создайте новый проект в IntelliJ IDEA или через Spring Initializr. Добавьте следующие зависимости в build.gradle.kts:

plugins {
    id("org.springframework.boot") version "3.2.0"
    id("io.spring.dependency-management") version "1.1.4"
    kotlin("jvm") version "1.9.21"
    kotlin("plugin.spring") version "1.9.21"
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.expediagroup:graphql-kotlin-spring-server:7.0.1")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

1.2. Конфигурация приложения

Создайте файл application.yml в src/main/resources:

server:
  port: 8080

graphql:
  packages:
    - "com.example.graphqldemo"
  schema:
    introspection-enabled: true
    exception-handlers-enabled: true

Это базовая конфигурация. Параметр introspection-enabled: true позволяет использовать GraphiQL для тестирования.

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

В graphql-kotlin схема строится автоматически на основе ваших классов данных (data classes). Это одно из главных преимуществ — не нужно писать отдельный SDL-файл.

2.1. Создание модели данных

Предположим, мы создаем API для библиотеки книг. Определим модели:

package com.example.graphqldemo.model

data class Book(
    val id: String,
    val title: String,
    val author: Author,
    val year: Int,
    val genre: String
)

data class Author(
    val id: String,
    val name: String,
    val books: List<Book> = emptyList()
)

// Input-типы для мутаций
data class BookInput(
    val title: String,
    val authorId: String,
    val year: Int,
    val genre: String
)

2.2. Сервис для работы с данными

Создадим простой in-memory сервис, который будет хранить данные:

package com.example.graphqldemo.service

import com.example.graphqldemo.model.Author
import com.example.graphqldemo.model.Book
import com.example.graphqldemo.model.BookInput
import org.springframework.stereotype.Service
import java.util.UUID

@Service
class LibraryService {
    private val authors = mutableListOf(
        Author("1", "Джоан Роулинг"),
        Author("2", "Джордж Оруэлл")
    )
    private val books = mutableListOf(
        Book("1", "Гарри Поттер и философский камень", authors[0], 1997, "Фэнтези"),
        Book("2", "1984", authors[1], 1949, "Антиутопия")
    )

    fun getBooks(): List<Book> = books
    fun getBookById(id: String): Book? = books.find { it.id == id }
    fun getAuthors(): List<Author> = authors
    fun addBook(input: BookInput): Book {
        val author = authors.find { it.id == input.authorId }
            ?: throw IllegalArgumentException("Автор не найден")
        val newBook = Book(
            id = UUID.randomUUID().toString(),
            title = input.title,
            author = author,
            year = input.year,
            genre = input.genre
        )
        books.add(newBook)
        return newBook
    }
}

3. Написание резолверов

Резолверы — это классы, которые определяют, как GraphQL обрабатывает запросы. В graphql-kotlin резолверы делятся на Query и Mutation.

3.1. Query-резолвер

Создадим класс для обработки запросов на получение данных:

package com.example.graphqldemo.resolver

import com.example.graphqldemo.model.Book
import com.example.graphqldemo.service.LibraryService
import org.springframework.stereotype.Component

@Component
class BookQueryResolver(private val libraryService: LibraryService) {

    fun books(): List<Book> = libraryService.getBooks()

    fun bookById(id: String): Book? = libraryService.getBookById(id)
}

Обратите внимание: graphql-kotlin автоматически сканирует компоненты Spring и регистрирует их как резолверы. Имена методов становятся полями в схеме.

3.2. Mutation-резолвер

Для изменения данных используем мутации:

package com.example.graphqldemo.resolver

import com.example.graphqldemo.model.Book
import com.example.graphqldemo.model.BookInput
import com.example.graphqldemo.service.LibraryService
import org.springframework.stereotype.Component

@Component
class BookMutationResolver(private val libraryService: LibraryService) {

    fun addBook(input: BookInput): Book = libraryService.addBook(input)
}

3.3. Data-резолвер для связей

Если нужно кастомно обработать связанные данные (например, книги автора), создайте отдельный резолвер:

package com.example.graphqldemo.resolver

import com.example.graphqldemo.model.Author
import com.example.graphqldemo.model.Book
import com.example.graphqldemo.service.LibraryService
import org.springframework.stereotype.Component

@Component
class AuthorResolver(private val libraryService: LibraryService) {

    fun books(author: Author): List<Book> =
        libraryService.getBooks().filter { it.author.id == author.id }
}

4. Запуск и тестирование API

4.1. Запуск приложения

Создайте главный класс приложения:

package com.example.graphqldemo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class GraphqlDemoApplication

fun main(args: Array                

Блоги

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