Введение в GraphQL API с Kotlin
GraphQL — это язык запросов для API, разработанный Facebook, который позволяет клиентам запрашивать только те данные, которые им действительно нужны. В отличие от REST, где каждый эндпоинт возвращает фиксированную структуру данных, GraphQL даёт гибкость и контроль. Kotlin, будучи современным статически типизированным языком для JVM, идеально подходит для создания таких API благодаря своей лаконичности и безопасности. В этом туториале мы шаг за шагом создадим простой GraphQL сервер на Kotlin с использованием библиотеки graphql-kotlin и Spring Boot.
К концу статьи вы научитесь:
- Настраивать проект Kotlin с Gradle
- Определять GraphQL-схему (типы, запросы, мутации)
- Реализовывать резолверы для обработки запросов
- Тестировать API через GraphQL Playground
Шаг 1: Настройка проекта и зависимости
Для начала создадим новый проект Kotlin с использованием Gradle. Мы будем использовать Spring Boot для упрощения конфигурации и graphql-kotlin-spring-server для интеграции GraphQL.
Создание базового проекта
Создайте директорию проекта и файл 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"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java {
sourceCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.expediagroup:graphql-kotlin-spring-server:7.0.1")
implementation("com.expediagroup:graphql-kotlin-schema-generator:7.0.1")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
}
Затем создайте основной класс приложения в src/main/kotlin/com/example/Application.kt:
package com.example
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
Шаг 2: Определение модели данных и схемы GraphQL
GraphQL использует строгую типизацию. Определим простую модель данных — книгу (Book) и автора (Author).
Создание классов данных
Создайте файл src/main/kotlin/com/example/model/Book.kt:
package com.example.model
data class Book(
val id: String,
val title: String,
val author: Author,
val year: Int
)
data class Author(
val id: String,
val name: String,
val nationality: String
)
Библиотека graphql-kotlin автоматически сгенерирует GraphQL-типы на основе этих data-классов. Каждое поле станет полем в схеме.
Резолверы для запросов
Теперь создадим сервис, который будет предоставлять данные. Создайте src/main/kotlin/com/example/service/BookService.kt:
package com.example.service
import com.example.model.Author
import com.example.model.Book
import org.springframework.stereotype.Service
@Service
class BookService {
private val books = mutableListOf(
Book("1", "Война и мир", Author("a1", "Лев Толстой", "Россия"), 1869),
Book("2", "Преступление и наказание", Author("a2", "Фёдор Достоевский", "Россия"), 1866),
Book("3", "1984", Author("a3", "Джордж Оруэлл", "Великобритания"), 1949)
)
fun getAllBooks(): List<Book> = books
fun getBookById(id: String): Book? = books.find { it.id == id }
fun addBook(title: String, authorName: String, year: Int): Book {
val newId = (books.size + 1).toString()
val author = Author("a${books.size + 1}", authorName, "Неизвестно")
val book = Book(newId, title, author, year)
books.add(book)
return book
}
}
Обратите внимание: мы используем простые списки в памяти. В реальном проекте здесь будет обращение к базе данных.
Шаг 3: Создание GraphQL-резолверов
В graphql-kotlin резолверы — это классы, помеченные аннотациями, которые определяют, как обрабатывать запросы и мутации.
Запросы (Query)
Создайте файл src/main/kotlin/com/example/graphql/BookQueryResolver.kt:
package com.example.graphql
import com.example.model.Book
import com.example.service.BookService
import org.springframework.stereotype.Component
@Component
class BookQueryResolver(private val bookService: BookService) {
fun allBooks(): List<Book> = bookService.getAllBooks()
fun bookById(id: String): Book? = bookService.getBookById(id)
}
Мутации (Mutation)
Мутации позволяют изменять данные. Создайте src/main/kotlin/com/example/graphql/BookMutationResolver.kt:
package com.example.graphql
import com.example.model.Book
import com.example.service.BookService
import org.springframework.stereotype.Component
@Component
class BookMutationResolver(private val bookService: BookService) {
fun addBook(title: String, authorName: String, year: Int): Book {
return bookService.addBook(title, authorName, year)
}
}
Библиотека автоматически свяжет эти классы с GraphQL-типами Query и Mutation.
Шаг 4: Запуск и тестирование API
Теперь всё готово к запуску. Выполните команду:
./gradlew bootRun
Сервер запустится на порту 8080. GraphQL Playground (встроенный инструмент для тестирования) будет доступен по адресу: http://localhost:8080/graphiql.
Примеры запросов
Попробуйте выполнить следующие запросы в Playground:
Запрос всех книг:
query {
allBooks {
id
title
author {
name
nationality