
关于
Ktor 服务器模式,包括路由 DSL、插件、认证、Koin DI、kotlinx.serialization、WebSocket 和 testApplication 测试。
name: kotlin-ktor-patterns description: Ktor 服务器模式,包括路由 DSL、插件、认证、Koin 依赖注入、kotlinx.serialization、WebSocket 和 testApplication 测试。 origin: ECC
Ktor 服务器模式
用于构建健壮、可维护的 HTTP 服务器的全面 Ktor 模式,基于 Kotlin 协程。
何时激活
- 构建 Ktor HTTP 服务器
- 配置 Ktor 插件(Auth、CORS、ContentNegotiation、StatusPages)
- 使用 Ktor 实现 REST API
- 使用 Koin 设置依赖注入
- 使用 testApplication 编写 Ktor 集成测试
- 在 Ktor 中使用 WebSocket
应用结构
标准 Ktor 项目布局
src/main/kotlin/
├── com/example/
│ ├── Application.kt # Entry point, module configuration
│ ├── plugins/
│ │ ├── Routing.kt # Route definitions
│ │ ├── Serialization.kt # Content negotiation setup
│ │ ├── Authentication.kt # Auth configuration
│ │ ├── StatusPages.kt # Error handling
│ │ └── CORS.kt # CORS configuration
│ ├── routes/
│ │ ├── UserRoutes.kt # /users endpoints
│ │ ├── AuthRoutes.kt # /auth endpoints
│ │ └── HealthRoutes.kt # /health endpoints
│ ├── models/
│ │ ├── User.kt # Domain models
│ │ └── ApiResponse.kt # Response envelopes
│ ├── services/
│ │ ├── UserService.kt # Business logic
│ │ └── AuthService.kt # Auth logic
│ ├── repositories/
│ │ ├── UserRepository.kt # Data access interface
│ │ └── ExposedUserRepository.kt
│ └── di/
│ └── AppModule.kt # Koin modules
src/test/kotlin/
├── com/example/
│ ├── routes/
│ │ └── UserRoutesTest.kt
│ └── services/
│ └── UserServiceTest.kt
应用入口点
// Application.kt
fun main() {
embeddedServer(Netty, port = 8080, module = Application::module).start(wait = true)
}
fun Application.module() {
configureSerialization()
configureAuthentication()
configureStatusPages()
configureCORS()
configureDI()
configureRouting()
}
路由 DSL
基本路由
// plugins/Routing.kt
fun Application.configureRouting() {
routing {
userRoutes()
authRoutes()
healthRoutes()
}
}
// routes/UserRoutes.kt
fun Route.userRoutes() {
val userService by inject<UserService>()
route("/users") {
get {
val users = userService.getAll()
call.respond(users)
}
get("/{id}") {
val id = call.parameters["id"]
?: return@get call.respond(HttpStatusCode.BadRequest, "Missing id")
val user = userService.getById(id)
?: return@get call.respond(HttpStatusCode.NotFound)
call.respond(user)
}
post {
val request = call.receive<CreateUserRequest>()
val user = userService.create(request)
call.respond(HttpStatusCode.Created, user)
}
put("/{id}") {
val id = call.parameters["id"]
?: return@put call.respond(HttpStatusCode.BadRequest, "Missing id")
val request = call.receive<UpdateUserRequest>()
val user = userService.update(id, request)
?: return@put call.respond(HttpStatusCode.NotFound)
call.respond(user)
}
delete("/{id}") {
val id = call.parameters["id"]
?: return@delete call.respond(HttpStatusCode.BadRequest, "Missing id")
val deleted = userService.delete(id)
if (deleted) call.respond(HttpStatusCode.NoContent)
else call.respond(HttpStatusCode.NotFound)
}
}
}
带认证路由的路由组织
fun Route.userRoutes() {
route("/users") {
// Public routes
get { /* list users */ }
get("/{id}") { /* get user */ }
// Protected routes
authenticate("jwt") {
post { /* create user - requires auth */ }
put("/{id}") { /* update user - requires auth */ }
delete("/{id}") { /* delete user - requires auth */ }
}
}
}
内容协商与序列化
kotlinx.serialization 设置
// plugins/Serialization.kt
fun Application.configureSerialization() {
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = false
ignoreUnknownKeys = true
encodeDefaults = true
explicitNulls = false
})
}
}
可序列化模型
@Serializable
data class UserResponse(
val id: String,
val name: String,
val email: String,
val role: Role,
@Serializable(with = InstantSerializer::class)
val createdAt: Instant,
)
@Serializable
data class CreateUserRequest(
val name: String,
val email: String,
val role: Role = Role.USER,
)
兼容工具
Claude CodeCursor
标签
后端开发

