Kotlin и API: три кита современной разработки
Вы когда-нибудь задумывались, почему одни приложения летают, а другие тормозят даже на флагманах? Секрет часто кроется не в железе, а в том, как они общаются с сервером. Если вы пишете на Kotlin — будь то бэкенд на Ktor или Android-приложение — рано или поздно вы уткнётесь в выбор: REST, GraphQL или gRPC?
На PythonLib мы любим разбираться в технологиях до винтика. Сегодня разложим по полочкам три подхода к работе с API на Kotlin. Никакой воды: только код, сравнение и реальные кейсы. Поехали!
REST API на Kotlin: классика, которая не стареет
REST — это как чёрный костюм: уместен везде, прост и понятен. В Kotlin для REST есть два главных игрока: Ktor (для серверной части) и Retrofit (для клиентской).
Сервер на Ktor: пишем API за 5 минут
Ktor — это фреймворк от JetBrains, созданный специально для Kotlin. Он асинхронный, лёгкий и не навязывает лишних зависимостей.
// build.gradle.kts
implementation("io.ktor:ktor-server-netty:2.3.7")
implementation("io.ktor:ktor-server-content-negotiation:2.3.7")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")
А теперь сам сервер:
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.routing.*
import io.ktor.server.response.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.plugins.contentnegotiation.*
import kotlinx.serialization.Serializable
@Serializable
data class User(val id: Int, val name: String, val email: String)
fun main() {
embeddedServer(Netty, port = 8080) {
install(ContentNegotiation) {
json()
}
routing {
get("/api/users") {
val users = listOf(
User(1, "Анна", "anna@example.com"),
User(2, "Борис", "boris@example.com")
)
call.respond(users)
}
get("/api/users/{id}") {
val id = call.parameters["id"]?.toIntOrNull()
if (id != null) {
call.respond(User(id, "Тест", "test@example.com"))
} else {
call.respondText("Неверный ID", status = io.ktor.http.HttpStatusCode.BadRequest)
}
}
}
}.start(wait = true)
}
Этот код — полноценный REST API на Kotlin с двумя эндпоинтами. Ktor сам сериализует данные в JSON благодаря kotlinx.serialization.
Клиент на Retrofit: подключаемся к любому API
Retrofit — это стандарт де-факто для Android-разработки. С Kotlin он работает идеально благодаря корутинам.
// build.gradle.kts
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
Объявляем интерфейс:
interface ApiService {
@GET("users")
suspend fun getUsers(): List<User>
@GET("users/{id}")
suspend fun getUser(@Path("id") userId: Int): User
@POST("users")
suspend fun createUser(@Body user: User): User
}
Создаём клиент и делаем запрос:
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(ApiService::class.java)
// В корутине
GlobalScope.launch {
val users = service.getUsers()
println(users)
}
Плюсы REST: простота, кэширование через HTTP, огромное комьюнити.
Минусы: over-fetching и under-fetching данных — часто получаете больше или меньше, чем нужно.
GraphQL на Kotlin: запрашивай только то, что нужно
GraphQL решает главную боль REST — вы сами решаете, какие поля получить. На Kotlin для этого есть библиотеки graphql-kotlin (от Expedia) и KGraphQL.
Сервер с KGraphQL
KGraphQL — самый простой способ добавить GraphQL в ваш Kotlin-проект.
// build.gradle.kts
implementation("com.apurebase:kgraphql:0.18.0")
implementation("com.apurebase:kgraphql-ktor:0.18.0")
Определяем схему и запускаем:
import com.apurebase.kgraphql.GraphQL
import com.apurebase.kgraphql.schema.dsl.SchemaBuilder
data class Book(val id: Int, val title: String, val author: String, val year: Int)
val schema = GraphQL.schema {
query("books") {
resolver { ->
listOf(
Book(1, "Kotlin в действии", "Дмитрий Жемеров", 2017),
Book(2, "Чистый код", "Роберт Мартин", 2008)
)
}
}
query("book") {
resolver { id: Int ->
Book(id, "Kotlin в действии", "Дмитрий Жемеров", 2017)
}
}
}
// Подключаем к Ktor
fun Application.graphQLModule() {
install(KGraphQL) {
schema(schema)
}
}
Теперь клиент может запросить только нужные поля:
query {
books {
title
author
}
}
Это даёт гибкость, которой нет в REST. Представьте: мобильное приложение запрашивает только title и author, а веб-версия — ещё и year. Один эндпоинт, два разных ответа.
Клиент GraphQL на Kotlin
Для клиента используем Apollo GraphQL — самую популярную библиотеку:
// build.gradle.kts
implementation("com.apollographql.apollo3:apollo-runtime:3.8.2")
val apolloClient = ApolloClient.Builder()
.serverUrl("https://api.example.com/graphql")
.build()
// Запрос
val response = apolloClient.query(BooksQuery()).execute()
val books = response.data?.books
println(books)
Плюсы GraphQL: точные запросы, один эндпоинт, само-документирование (через Introspection).
Минусы: сложность кэширования, нет HTTP-кэша, сложнее мониторинг.
gRPC на Kotlin: скорость и строгость протокола
gRPC — это не просто API, это религия производительности. Он использует HTTP/2, Protobuf и строгую типизацию. Идеален для микросервисов и high-load систем.