使用 freemarker 自托管的 ktor 网站不起作用

Posted

技术标签:

【中文标题】使用 freemarker 自托管的 ktor 网站不起作用【英文标题】:ktor website self hosted with freemarker doesn't work 【发布时间】:2021-03-10 09:41:20 【问题描述】:

我正在与 kotlin handson 一起练习“Ktor 的交互式网站”, 我没有正确的话来解释我的代码发生了什么,但我可以说: 当我导航到 http://localhost:8080/ IDE 时显示此错误有时会起作用

    2020-11-27 16:01:59.144 [main] INFO  Application - No ktor.deployment.watch patterns specified, automatic reload is not active
2020-11-27 16:02:00.677 [main] INFO  Application - Responding at http://0.0.0.0:8080
Exception in thread "eventLoopGroupProxy-3-1 @response-pipeline#3" kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[UnsafeBlockingTrampoline@76907f9f, Continuation at io.ktor.utils.io.jvm.javaio.OutputAdapter$loop$1.loop(Blocking.kt:311)@aa7a293]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
    at kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx_coroutines_core(DispatchedTask.kt:93)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:64)
    at io.ktor.utils.io.jvm.javaio.UnsafeBlockingTrampoline.dispatch(Blocking.kt:296)
    at kotlinx.coroutines.DispatchedContinuation.resumeWith(DispatchedContinuation.kt:184)
    at io.ktor.utils.io.jvm.javaio.BlockingAdapter$end$1.resumeWith(Blocking.kt:163)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
    at io.ktor.utils.io.jvm.javaio.UnsafeBlockingTrampoline.dispatch(Blocking.kt:296)
    at kotlinx.coroutines.DispatchedContinuation.resumeWith(DispatchedContinuation.kt:184)
    at io.ktor.utils.io.internal.CancellableReusableContinuation.resumeWith(CancellableReusableContinuation.kt:93)
    at io.ktor.utils.io.ByteBufferChannel.resumeWriteOp(ByteBufferChannel.kt:2258)
    at io.ktor.utils.io.ByteBufferChannel.bytesRead(ByteBufferChannel.kt:929)
    at io.ktor.utils.io.ByteBufferChannel.consumed(ByteBufferChannel.kt:1953)
    at io.ktor.server.netty.cio.NettyResponsePipeline$processBodyFlusher$2.invokeSuspend(NettyResponsePipeline.kt:305)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.ktor.server.netty.EventLoopGroupProxy$Companion$create$factory$1$1.run(NettyApplicationEngine.kt:215)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.ClassCastException: class kotlin.coroutines.jvm.internal.CompletedContinuation cannot be cast to class kotlinx.coroutines.DispatchedContinuation (kotlin.coroutines.jvm.internal.CompletedContinuation and kotlinx.coroutines.DispatchedContinuation are in unnamed module of loader 'app')
    at kotlinx.coroutines.CoroutineDispatcher.releaseInterceptedContinuation(CoroutineDispatcher.kt:103)
    at kotlin.coroutines.jvm.internal.ContinuationImpl.releaseIntercepted(ContinuationImpl.kt:118)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:39)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:55)
    ... 22 more

Application.kt

    package com.server

import freemarker.cache.ClassTemplateLoader
import io.ktor.application.*
import io.ktor.freemarker.*
import io.ktor.http.content.*
import io.ktor.response.*
import io.ktor.routing.*

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
//fun main(args: Array<String>)  embeddedServer(Netty, port = 8080, module = Application::module).apply  start(wait = true)  

@Suppress("unused") // Referenced in application.conf
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) 
    install(FreeMarker) 
        templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates")
    

    routing 
        get("/") 
            call.respond(FreeMarkerContent("index.ftl",
                mapOf("data" to IndexData(listOf(1, 2, 3))), ""))
        

        static("/files") 
            resources("files")
        
    


data class IndexData(val items: List<Int>)

build.gradle.kts

    import org.jetbrains.kotlin.gradle.dsl.Coroutines
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

val ktor_version: String by project
val kotlin_version: String by project
val logback_version: String by project

plugins 
    application
    kotlin("jvm") version "1.4.10"


group = "com.server"
version = "0.0.1"

application 
    mainClassName = "io.ktor.server.netty.EngineMain"


repositories 
    mavenLocal()
    jcenter()
    maven  url = uri("https://kotlin.bintray.com/ktor") 


dependencies 
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version")
    implementation("io.ktor:ktor-server-netty:$ktor_version")
    implementation("ch.qos.logback:logback-classic:$logback_version")
    implementation("io.ktor:ktor-server-core:$ktor_version")
    implementation("io.ktor:ktor-freemarker:$ktor_version")
    testImplementation("io.ktor:ktor-server-tests:$ktor_version")


kotlin.sourceSets["main"].kotlin.srcDirs("src")
kotlin.sourceSets["test"].kotlin.srcDirs("test")

sourceSets["main"].resources.srcDirs("resources")
sourceSets["test"].resources.srcDirs("testresources")

应用程序.conf

ktor 
deployment 
    port = 8080
    port = $?PORT

application 
    modules = [ com.server.ApplicationKt.module ]

项目结构

服务器/主服务器-

resources
     files
     templates
     Application.conf
     logback.xml
src
     Application.kt 

【问题讨论】:

【参考方案1】:

这很可能是this issue。使用 Ktor 1.5.2,您的代码可以按预期工作。

【讨论】:

以上是关于使用 freemarker 自托管的 ktor 网站不起作用的主要内容,如果未能解决你的问题,请参考以下文章

java官网门户源码 SSM框架 自适应-响应式 freemarker 静态模版引擎

Ktor 后端的 CORS 问题

“未找到转换:类 io.ktor.utils.io.ByteChannelNative”错误使用 Ktor

Ktor 客户端 IOS 和自签名证书

带有自签名证书的 ktor 客户端 https 请求

您可以自定义 Ktor 401 - 未经授权的响应吗?