前言

我于2020年7月起跟随郭霖老师的《第一行代码(第三版)》进入了Kotlin与安卓的开发世界,在不断的学习之中更加深入地体会到Jetbrains所打造的Kotlin相比于古老的Java所存在的巨大创新与优势。Kotlin在完整保留与Java相兼容的同时继承了所有来自Java过去所打造的巨大财富,并且在语言现代化、语法简洁性、空安全等方面作出了大量改进和创新,于Java始终如一的老套古板语法相比更加使人为之着迷。从此我便一发不可收拾地喜爱并推荐使用Kotlin来完成以前使用Java编程的相关工作。一个月前,我在网上偶然间发现了Ktor框架,发现这是一个完全以Kotlin打造的轻量级后端框架,能够只专注于后端程序要实现的功能去搭建程序而不需过多考虑api的具体实现细节,极大提升了后端程序的开发效率。

简单介绍

Ktor是完成基于Kotlin打造的轻量级后端框架,它附带了如路径跳转、Header和Cookie控制、安全性验证、数据库连接、HTTP转发、HTML和CSS DSL等多种实用功能。这些功能都通过Plugin的形式能够自由选择是否添加到项目中,极大增强了框架本身的功能扩展性。除了用于后端开发外,它还能于类似React这种JavaScript框架相整合以便在获取后端数据的同时实时地将数据反映在用户界面上。在部署时,可以导出为War格式文件轻松地部署到Tomcat等服务器应用中。

基础功能

Routing

Routing是用来控制当前要访问的资源链接以及资源访问方式的Plugin。

fun Application.configureRouting() {
routing {
get("/") {
// 使用GET方法访问根路径的处理函数
}
route("articles") {
get {
// 使用GET方法访问/articles的处理函数
}
get("{id}/edit") {
// 使用GET方法访问/{id}/edit的处理函数
call.parameters["id"] // 获得链接中参数id
call.request.queryParameters["title"] // 获得链接?后的参数
}
post {
// 使用POST方法访问/articles的处理函数
}
}
}
}

HTML DSL & CSS DSL

HTML DSL & CSS DSL是将HTML与CSS转为由Kotlin语言编写的Plugin,通过它们可以在Kotlin中直接生成HTML与CSS。

dependencies {
implementation("io.ktor:ktor-server-html-builder:$ktor_version")
implementation("org.jetbrains.kotlin-wrappers:kotlin-css:$kotlin_css_version")
}
suspend inline fun ApplicationCall.respondCss(builder: CssBuilder.() -> Unit) {
this.respondText(CssBuilder().apply(builder).toString(), ContentType.Text.CSS)
}
fun Application.module() {
routing {
get("/") {
call.respondHtml {
head {
link(rel = "stylesheet", href = "/styles.css", type = "text/css")
}
body {
h1(classes = "page-title") {
+"Hello Ktor!"
}
}
}
}
get("/styles.css") {
call.respondCss {
body {
backgroundColor = Color.darkBlue
margin(0.px)
}
rule("h1.page-title") {
color = Color.white
}
}
}
}
}

Content Negotiation & Serialization

Content negotiation & Serialization是实现对象以格式化文本(JSON/XML)输出的Plugin。

implementation("io.ktor:ktor-server-content-negotiation:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-xml:$ktor_version")
val client = HttpClient(CIO) {
install(ContentNegotiation) {
json()
}
}
@Serializable
data class Customer(val id: Int, val firstName: String, val lastName: String)
val response: HttpResponse = client.post("http://localhost:8080/customer") {
contentType(ContentType.Application.Json)
setBody(Customer(3, "Jet", "Brains"))
}
val customer: Customer = client.get("http://localhost:8080/customer/3").body()

Exposed

Exposed是Ktor提供的轻量化数据库集成Plugin,能够方便快捷地连接并使用数据库。

dependencies {
implementation("org.jetbrains.exposed:exposed-core:$exposed_version")
implementation("org.jetbrains.exposed:exposed-dao:$exposed_version")
implementation("org.jetbrains.exposed:exposed-jdbc:$exposed_version")
implementation("com.h2database:h2:$h2_version")
}

Table对象

object Articles : Table() {
val id = integer("id").autoIncrement()
val title = varchar("title", 128)
val body = varchar("body", 1024)
override val primaryKey = PrimaryKey(id)
}

连接数据库

object DatabaseFactory {
fun init() {
val driverClassName = "org.h2.Driver"
val jdbcURL = "jdbc:h2:file:./build/db"
val database = Database.connect(jdbcURL, driverClassName)
}
}

增删改查

由于相关内容过多,有关增删改查等数据库操控知识请参考Exposed官方文档

测试

测试Ktor程序只需在Test模块内新建xxx.http文件并在其输入HTTP访问请求,并在IDEA中检查返回数据是否正确即可。

GET http://127.0.0.1:8080/articles
Accept: application/json

小结

Ktor框架基于Kotlin搭建,通过Plugin设计将许多框架提供的功能进行拆分,按需添加使用。它提供了HTML、CSS的Kotlin内嵌支持,轻量化的数据库连接与操作功能,使得搭建后端程序只需关注业务本身需要实现的功能而不用过多关注实际代码细节,减少了很多不需要考虑的后端开发繁杂工作。配合Kotlin和Java的其他框架,甚至能够实现全栈应用的开发,功能扩展性很强。