Введение: Почему GraphQL и Kotlin — идеальная пара для современного API
Современная веб-разработка требует гибких и производительных API. REST, долгое время бывший стандартом, часто приводит к проблеме over-fetching (когда сервер отдаёт больше данных, чем нужно) или under-fetching (когда для получения полной информации требуется несколько запросов). GraphQL решает эти проблемы, позволяя клиенту запрашивать только необходимые данные в одном запросе.
Kotlin, в свою очередь, — современный, лаконичный и типобезопасный язык, который отлично подходит для создания надёжных бэкенд-сервисов. Благодаря библиотеке graphql-kotlin от компании Expedia Group, создание GraphQL API на Kotlin становится простым и интуитивным. В этом туториале мы шаг за шагом создадим полноценный GraphQL API для управления списком книг.
Что вы узнаете:
- Как настроить проект на Spring Boot с поддержкой GraphQL.
- Как определить схему GraphQL с помощью классов Kotlin.
- Как реализовать запросы (Queries) и мутации (Mutations).
- Как тестировать API через встроенную GraphiQL IDE.
Шаг 1: Настройка проекта и зависимости
Для начала создадим новый проект Spring Boot. Мы будем использовать Gradle (Kotlin DSL) — это стандарт для современных Kotlin-проектов.
1.1. Создаём проект
Вы можете использовать Spring Initializr или создать структуру вручную. Нам понадобятся следующие зависимости:
- Spring Web — для запуска HTTP-сервера.
- Spring Boot Starter GraphQL — основная интеграция.
- Kotlin Reflection — для работы библиотеки graphql-kotlin.
1.2. Файл 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.20"
kotlin("plugin.spring") version "1.9.20"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-graphql")
implementation("com.expediagroup:graphql-kotlin-spring-server:7.0.1")
implementation("org.jetbrains.kotlin:kotlin-reflect")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
1.3. Конфигурация application.yml
spring:
graphql:
graphiql:
enabled: true # Включаем встроенную IDE для тестирования
schema:
locations: "classpath:graphql/**/"
server:
port: 8080
Шаг 2: Определение схемы и модели данных
В GraphQL схема — это контракт между клиентом и сервером. Библиотека graphql-kotlin позволяет определять схему автоматически на основе классов Kotlin (code-first подход). Это избавляет от необходимости писать файлы .graphqls вручную.
2.1. Создаём модель данных
Создадим простую модель Book и репозиторий для хранения данных в памяти.
package com.example.graphqlkotlin.model
data class Book(
val id: String,
val title: String,
val author: String,
val year: Int
)
2.2. Репозиторий (in-memory)
package com.example.graphqlkotlin.repository
import com.example.graphqlkotlin.model.Book
import org.springframework.stereotype.Repository
import java.util.concurrent.ConcurrentHashMap
@Repository
class BookRepository {
private val books = ConcurrentHashMap(
mapOf(
"1" to Book("1", "Война и мир", "Лев Толстой", 1869),
"2" to Book("2", "Преступление и наказание", "Фёдор Достоевский", 1866)
)
)
fun findAll(): List<Book> = books.values.toList()
fun findById(id: String): Book? = books[id]
fun save(book: Book): Book {
books[book.id] = book
return book
}
fun delete(id: String): Boolean = books.remove(id) != null
}
Шаг 3: Реализация Query и Mutation резолверов
Резолверы — это функции, которые обрабатывают запросы GraphQL. В graphql-kotlin они реализуются через интерфейсы Query и Mutation.
3.1. Резолвер для запросов (Query)
package com.example.graphqlkotlin.resolver
import com.example.graphqlkotlin.model.Book
import com.example.graphqlkotlin.repository.BookRepository
import org.springframework.stereotype.Component
@Component
class BookQueryResolver(private val repository: BookRepository) : Query {
fun books(): List<Book> = repository.findAll()
fun bookById(id: String): Book? = repository.findById(id)
}
3.2. Резолвер для мутаций (Mutation)
package com.example.graphqlkotlin.resolver
import com.example.graphqlkotlin.model.Book
import com.example.graphqlkotlin.repository.BookRepository
import org.springframework.stereotype.Component
import java.util.UUID
@Component
class BookMutationResolver(private val repository: BookRepository) : Mutation {
fun addBook(title: String, author: String, year: Int): Book {
val book = Book(
id = UUID.randomUUID().toString(),
title = title,
author = author,
year = year
)
return repository.save(book)
}
fun updateBook(id: String, title: String?, author: String?, year: Int?): Book? {
val existing = repository.findById(id) ?: return null
val updated = existing.copy(
title = title ?: existing.title,
author = author ?: existing.author,
year = year ?: existing.year
)
return repository.save(updated)
}
fun deleteBook(id: String): Boolean = repository.delete(id)
}
3.3. Главный класс приложения
package com.example.graphqlkotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class GraphqlKotlinApplication
fun main(args: Array<String>) {
runApplication<GraphqlKotlinApplication>(*args)
}
Шаг 4: Тестирование API через GraphiQL
После запуска приложения (./gradlew bootRun) откройте браузер и перейдите по адресу http://localhost:8080/graphiql
Блоги
Рекомендаций по книгам
Читайте также