KMP项目中如何在服务端与客户端共享Ktor Resources?
解决Ktor多平台中共享@Resource类实现类型安全路由的问题
完全可以将@Resource类放在shared/commonMain模块中,无需在客户端和服务端重复定义——这才是Kotlin多平台类型安全路由的正确用法,文档未明确提及是默认开发者会利用多平台共享模块的特性。
依赖配置要点
- 共享模块(commonMain):仅引入核心的
ktor-resources依赖,它包含@Resource注解及基础类型,是客户端、服务端依赖的共同基础// 共享模块build.gradle.kts配置 sourceSets["commonMain"].dependencies { implementation("io.ktor:ktor-resources:$ktorVersion") } - 服务端模块:引入
ktor-server-resources,它依赖核心包,同时提供服务端路由绑定的扩展方法// 服务端模块build.gradle.kts配置 sourceSets["jvmMain"].dependencies { implementation("io.ktor:ktor-server-resources:$ktorVersion") } - 客户端模块:引入
ktor-client-resources,依赖核心包,提供客户端类型安全请求的扩展// 客户端模块build.gradle.kts配置(以commonMain为例,也可对应androidMain/iosMain) sourceSets["commonMain"].dependencies { implementation("io.ktor:ktor-client-resources:$ktorVersion") }
共享资源类示例
在shared/commonMain中定义资源类:
import io.ktor.resources.* @Resource("/articles") class Articles // 带参数的嵌套资源类示例 @Resource("/articles/{id}") class Article(val parent: Articles = Articles(), val id: Int)
服务端使用方式
在服务端路由中绑定共享的资源类:
import io.ktor.server.application.* import io.ktor.server.resources.* import io.ktor.server.routing.* fun Application.configureRouting() { install(Resources) routing { get<Articles> { // 处理/articles请求逻辑 } get<Article> { article -> // 直接通过article.id获取路径参数,处理/articles/{id}请求 } } }
客户端使用方式
在客户端请求中调用共享的资源类:
import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.plugins.resources.* suspend fun fetchArticles(client: HttpClient): List<ArticleDto> { return client.get(Articles()).body() } suspend fun fetchArticle(client: HttpClient, articleId: Int): ArticleDto { return client.get(Article(id = articleId)).body() }
常见误区说明
- 不要在客户端、服务端分别定义资源类,这会破坏类型安全的核心价值,也违背多平台共享的初衷
- 共享模块只需核心依赖,客户端/服务端的特定依赖会自动关联核心包,不会出现依赖冲突
内容的提问来源于stack exchange,提问作者Papooch
相关产品推荐
相关产品推荐

