Einleitung
Kotlin ist eine moderne Programmiersprache, die in der Backend-Entwicklung rasant an Popularität gewinnt. Dank der prägnanten Syntax, der vollständigen Kompatibilität mit Java und leistungsstarken Tools wie dem Ktor-Framework dauert das Schreiben einer REST API in Kotlin buchstäblich 30 Minuten. In diesem Artikel erstellen wir eine vollwertige REST API zur Verwaltung einer Aufgabenliste (Todo API). Sie lernen, wie Sie das Projekt einrichten, Endpunkte erstellen, eine Datenbank anbinden und die API testen. Keine überflüssige Theorie – nur Praxis.
Schritt 1: Projekteinrichtung und Abhängigkeiten
Für den schnellen Start verwenden wir IntelliJ IDEA (Community Edition) oder einen anderen Editor. Wir erstellen ein neues Gradle-Projekt mit Kotlin DSL.
Erstellung der Projektstruktur
Fügen Sie der Datei build.gradle.kts die folgenden Abhängigkeiten hinzu:
plugins { kotlin("jvm") version "1.9.22" application}
repositories { mavenCentral()}
dependencies { implementation("io.ktor:ktor-server-core:2.3.7") 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") implementation("org.jetbrains.exposed:exposed-core:0.44.1") implementation("org.jetbrains.exposed:exposed-dao:0.44.1") implementation("org.jetbrains.exposed:exposed-jdbc:0.44.1") implementation("com.h2database:h2:2.2.224") implementation("ch.qos.logback:logback-classic:1.4.14")}
application { mainClass.set("ApplicationKt")}Wir verwenden:
- Ktor — ein leichtgewichtiges asynchrones Framework für HTTP-Server.
- Exposed — ein ORM für die Arbeit mit Datenbanken.
- H2 — eine eingebettete Datenbank für die Entwicklung.
- Kotlinx.serialization — für die Arbeit mit JSON.
Schritt 2: Erstellung des Datenmodells und Datenbankverbindung
Wir definieren die Struktur der Aufgabentabelle. Erstellen Sie die Datei Database.kt:
import org.jetbrains.exposed.sql.Tableimport org.jetbrains.exposed.sql.insertimport org.jetbrains.exposed.sql.selectAllimport org.jetbrains.exposed.sql.transactions.transaction
object Tasks : Table() { val id = integer("id").autoIncrement() val title = varchar("title", 255) val completed = bool("completed").default(false)
override val primaryKey = PrimaryKey(id)}
data class Task(val id: Int, val title: String, val completed: Boolean)
fun initDatabase() { Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") transaction { SchemaUtils.create(Tasks) }}Dieser Code erstellt eine Tabelle Tasks mit drei Feldern: id, title und completed. Die Funktion initDatabase() initialisiert die Datenbank im Arbeitsspeicher.
Schritt 3: Schreiben der REST API-Controller
Jetzt erstellen wir die Hauptanwendungsdatei Application.kt. Hier definieren wir alle Endpunkte.
Grundlegende Serverkonfiguration
import io.ktor.server.application.*import io.ktor.server.engine.*import io.ktor.server.netty.*import io.ktor.server.routing.*import io.ktor.server.response.*import io.ktor.server.request.*import io.ktor.serialization.kotlinx.json.*import io.ktor.server.plugins.contentnegotiation.*
fun main() { embeddedServer(Netty, port = 8080) { install(ContentNegotiation) { json() } initDatabase() configureRouting() }.start(wait = true)}Implementierung der CRUD-Endpunkte
fun Application.configureRouting() { routing { // Alle Aufgaben abrufen get("/tasks") { val tasks = transaction { Tasks.selectAll().map { row -> Task( id = row[Tasks.id], title = row[Tasks.title], completed = row[Tasks.completed] ) } } call.respond(tasks) }
// Neue Aufgabe erstellen post("/tasks") { val task = call.receive() val id = transaction { Tasks.insert { it[title] = task.title it[completed] = task.completed } get Tasks.id } call.respond(Task(id, task.title, task.completed)) }
// Aufgabe nach ID abrufen get("/tasks/{id}") { val id = call.parameters["id"]?.toIntOrNull() if (id == null) { call.respondText(\"Ungültige ID\", status = io.ktor.http.HttpStatusCode.BadRequest) return@get } val task = transaction { Tasks.selectAll().where { Tasks.id eq id }.singleOrNull() } if (task == null) { call.respondText(\"Aufgabe nicht gefunden\", status = io.ktor.http.HttpStatusCode.NotFound) } else { call.respond(Task(task[Tasks.id], task[Tasks.title], task[Tasks.completed])) } }
// Aufgabe aktualisieren put("/tasks/{id}") { val id = call.parameters["id"]?.toIntOrNull() if (id == null) { call.respondText(\"Ungültige ID\", status = io.ktor.http.HttpStatusCode.BadRequest) return@put } val updatedTask = call.receive() transaction { Tasks.update({ Tasks.id eq id }) { it[title] = updatedTask.title it[completed] = updatedTask.completed } } call.respond(updatedTask.copy(id = id)) }
// Aufgabe löschen delete("/tasks/{id}") { val id = call.parameters["id"]?.toIntOrNull() if (id == null) { call.respondText(\"Ungültige ID\", status = io.ktor.http.HttpStatusCode.BadRequest) return@delete } transaction { Tasks.deleteWhere { Tasks.id eq id } } call.respondText(\"Aufgabe gelöscht\", status = io.ktor.http.HttpStatusCode.OK) } }} Schritt 4: Testen der API
Starten Sie die Anwendung, indem Sie die main()-Funktion ausführen. Der Server läuft auf http://localhost:8080. Sie können die API mit curl, Postman oder einem anderen Tool testen.
Beispielanfragen
Neue Aufgabe erstellen:
curl -X POST http://localhost:8080/tasks \ -H \"Content-Type: application/json\" \ -d '{\"title\": \"Kotlin lernen\", \"completed\": false}'Alle Aufgaben abrufen:
curl http://localhost:8080/tasksEine Aufgabe nach ID abrufen:
curl http://localhost:8080/tasks/1Eine Aufgabe aktualisieren:
curl -X PUT http://localhost:8080/tasks/1 \ -H \"Content-Type: application/json\" \ -d '{\"title\": \"Kotlin lernen\", \"completed\": true}'Eine Aufgabe löschen:
curl -X DELETE http://localhost:8080/tasks/1Fazit
Sie haben gerade eine voll funktionsfähige REST API in Kotlin mit Ktor und Exposed erstellt. In weniger als 30 Minuten haben Sie gelernt, wie Sie ein Projekt einrichten, eine Datenbank anbinden, CRUD-Endpunkte implementieren und die API testen. Dieses Setup kann leicht erweitert werden – fügen Sie Authentifizierung, Paginierung oder eine echte Datenbank wie PostgreSQL hinzu. Kotlin und Ktor bieten eine hervorragende Grundlage für moderne Backend-Entwicklung.