这篇主要会讲一下 Ktor
的项目结构,以及怎么样更好的使用相应的资源,那么直接进入正题了。
一个正常的 Ktor
项目的结构是这样的:
project
| -- src
| | -- Application.kt
| -- resources
| | -- application.conf
| | -- web
| | -- index.html
| | -- templates
| -- web
| | -- WEB-INF
| | -- web.xml
| -- build.gradle
| -- gradle.properties
| -- settings.gradle
gradle 相关的文件自不必说,project 下的文件其含义如下表所示:
文件(夹) | 作用 |
---|---|
Application.kt | 程序 / Router 的入口 |
application.conf | ktor 的配置 |
index.html | 首页,注意 Ktor 的页面必须放在 resources 内 |
web.xml | servlet 配置,固定文件 |
src/ | 源码放在这 |
resources/ | 资源文件放在这 |
resources/web/ | 页面文件,js, css 等放在这 |
resources/templates/ | 模板文件放在这 |
Ktor 提供了多种文件访问的方式,可以从 resources
里获得文件。在上一篇中,讲述的 Demo 程序,其本质是自己 response 一个文本,这种做法并没有太大的适用场景,更多的情况是直接返回一个写好的页面。这个时候我们可以把代码改成这样:
fun Application.main() {
routing {
static {
defaultResource("index.html", "web")
resources("web")
}
}
}
static { }
用于对静态资源进行配置,比如说在 get("/")
时,返回 index.html
的内容,而此时并不需要明确的写出 get("/")
,只需要写 defaultResource()
即可。
如果觉得不直观,也可以写成这样:
fun Application.main() {
routing {
get("/") {
call.respond(call.resolveResource("index.html", "web"))
}
}
}
通过以上方法,我们可以访问到任意的文件,抽一个函数出来即可:
@UseExperimental(io.ktor.util.KtorExperimentalAPI::class)
fun ApplicationCall.resolveFile(path: String, resourcePackage: String? = null, classLoader: ClassLoader = application.environment.classLoader): String? {
val packagePath = (resourcePackage?.replace('.', '/') ?: "").appendPathPart(path)
val normalizedPath = Paths.get(packagePath).normalizeAndRelativize()
val normalizedResource = normalizedPath.toString().replace(File.separatorChar, '/')
for (url in classLoader.getResources(normalizedResource).asSequence()) {
when (url.protocol) {
"file" -> {
val file = File(url.path.decodeURLPart())
return if (file.isFile) file.readText() else null
}
else -> {
}
}
}
return null
}
这个函数可以到处使用,需要注意的一点是,在 Ktor
里,有非常多的被标为 Experimental
的内容,如果要使用它们,就必须带上 @UseExperimental(io.ktor.util.KtorExperimentalAPI::class)
注解,否则在编译时,这些函数不会被编译到目标文件,从而引发异常。
同时,需要在 gradle 内增加以下内容,以确保 Experimental
内容被成功编译:
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlin.Experimental"]
}
现在,你可以顺利的访问到 Ktor
项目内的静态文件了,本篇到此结束。
下一篇预告:《Ktor 从入门到放弃(三) 接受请求与页面组装》