Котлин с Ктор

Котлин с Ктор

1. обзор

Ktor - это платформа для построения асинхронных серверов и клиентов в связанных системах с использованием мощного языка программирования Kotlin. Это облегчает разработку отдельного приложения со встроенными серверами.

В этом руководстве мы собираемся изучить, как создать автономное серверное приложение с помощью Ktor.

2. Настройка приложения Ktor

Начнем с настройки проекта Ktor. Мы будем использоватьGradle, это рекомендуемый и простой в использовании подход. Gradle можно установить, следуя инструкциям наGradle site.

Создайте файлbuild.gradle:

group 'com.example.kotlin'
version '1.0-SNAPSHOT'

buildscript {
    ext.kotlin_version = '1.2.40'
    ext.ktor_version = '0.9.2'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'application'

mainClassName = 'APIServer.kt'

sourceCompatibility = 1.8
compileKotlin { kotlinOptions.jvmTarget = "1.8" }
compileTestKotlin { kotlinOptions.jvmTarget = "1.8" }

kotlin { experimental { coroutines "enable" } }

repositories {
    mavenCentral()
    jcenter()
    maven { url "https://dl.bintray.com/kotlin/ktor" }
}

dependencies {
    compile "io.ktor:ktor-server-netty:$ktor_version"
    compile "ch.qos.logback:logback-classic:1.2.1"
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

Мы импортировали Ktor и пакет сервера Ktor netty. Netty - это встроенный сервер, который мы будем использовать в этом примере.

3. Сборка сервера

Мы создаем наше приложение, добавляя код в исходную папкуsrc/main/kotlin.

Здесь мы создаем файлAPIServer.kt с помощью основного метода:

fun main(args: Array) {

}

Далее мы создаем и запускаем встроенный сервер Netty:

embeddedServer(Netty, 8080) {

}.start(wait = true)

Он создаст и запустит сервер на порту8080. Мы установилиwait=true в методеstart() для прослушивания соединений.

4. Создание API

Давайте добавим API. Для обработки HTTP-запросов Ktor предоставляет функциюRouting.

Мы активируемRouting feature с помощью блокаinstall, в котором мы можем определять маршруты для определенных путей и методов HTTP:

val jsonResponse = """{
    "id": 1,
    "task": "Pay waterbill",
    "description": "Pay water bill today",
}"""

embeddedServer(Netty, 8080) {
  install(Routing) {
      get("/todo") {
          call.respondText(jsonResponse, ContentType.Application.Json)
      }
  }
}.start(wait = true)

В этом примере сервер обработает запросGET для пути/todo и ответит объектомtodo JSON. Подробнее об установке функций мы узнаем в разделеInstalling Features.с

5. Запуск сервера

Чтобы запустить сервер, нам нужна задача запуска в Gradle:

task runServer(type: JavaExec) {
    main = 'APIServer'
    classpath = sourceSets.main.runtimeClasspath
}

Чтобы запустить сервер, мы называем эту задачу:

./gradlew runServer

Затем доступ к API можно получить черезhttp://localhost:8080/todo.

6. Установка функций

Приложение Ktor обычно состоит из ряда функций. Мы могли бы думать о функциях как о функциональности, которая внедряется в конвейер запросов и ответов.

Используя функциюDefaultHeaders, мы можем добавлять заголовки к каждому исходящему ответу. Routing - еще одна функция, которая позволяет нам определять маршруты для обработки запросов и т. д.

Мы также можем разработать наши функции и установить их.

Давайте посмотрим, добавив настраиваемый заголовок к каждому запросу, установив функциюDefaultHeaders:

install(DefaultHeaders) {
    header("X-Developer", "example")
}

Точно так же мы можем переопределить заголовки по умолчанию, установленные самой структурой Ktor:

install(DefaultHeaders) {
    header(HttpHeaders.Server, "My Server")
}

Список доступных заголовков по умолчанию можно найти в классеio.ktor.features.DefaultHeaders. 

7. Обслуживание JSON

Создать строковый JSON вручную непросто. Ktor предоставляет возможность обслуживать объекты данных как JSON с использованием Gson.

Давайте добавим зависимость Gson в нашbuild.gradle:

compile "io.ktor:ktor-gson:$ktor_version"

Например, мы используем объект данных с именемAuthor:

data class Author(val name: String, val website: String)

Далее мы устанавливаем функциюgson:

install(ContentNegotiation) {
   gson {
       setPrettyPrinting()
   }
}

Наконец, давайте добавим маршрут к серверу, который обслуживает объект-автор как JSON:

get("/author") {
    val author = Author("example", "example.com")
    call.respond(author)
}

API автора будет обслуживать объект данных автора какJSON.

8. Добавление контроллеров

Чтобы понять, как обрабатывать несколько запросов HTTP-действий, давайте создадим приложение TODO, которое позволяет пользователю добавлять, удалять, просматривать и перечислять элементы TODO.

Начнем с добавления класса данныхTodo:

data class ToDo(var id: Int, val name: String, val description: String, val completed: Boolean)

Затем мы создаемArrayList для хранения нескольких элементовTodo:

val toDoList = ArrayList();

Далее мы добавляем контроллеры для обработки запросов POST, DELETE и GET:

routing() {
    route("/todo") {
        post {
            var toDo = call.receive();
            toDo.id = toDoList.size;
            toDoList.add(toDo);
            call.respond("Added")

        }
        delete("/{id}") {
            call.respond(toDoList.removeAt(call.parameters["id"]!!.toInt()));
        }
        get("/{id}") {
            call.respond(toDoList[call.parameters["id"]!!.toInt()]);
        }
        get {
            call.respond(toDoList);
        }
    }
}

Мы добавилиtodoroute, а затем сопоставили запрос различных HTTP-глаголов с этой конечной точкой.

9. Заключение

В этой статье мы узнали, как создать серверное приложение Kotlin с фреймворком Ktor.

Мы создали небольшое серверное приложение за несколько минут без использования стандартного кода.

Как всегда, образцы кода можно найтиover on GitHub.