Ktor shadow插件打包fat jar未包含resources文件夹问题
问题根因
执行gradle shadowJar --no-daemon构建出的Ktor fat jar缺失resources资源,通常由两个原因导致:
- Shadow插件未显式配置资源拷贝规则,构建时未将main源码集的资源输出纳入打包范围
- 本地开发时使用了依赖项目工作目录的资源读取写法,IDEA运行时工作目录为项目根目录可正常读取,但jar包内不存在
src目录结构,导致路径失效
解决步骤
- 配置Shadow插件打包规则
在你的build.gradle.kts中添加如下任务配置,强制将主源码集的编译输出(含class文件与处理后的资源文件)打入jar包,同时处理重复文件冲突:tasks { shadowJar { from(project.sourceSets.main.get().output) duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes["Main-Class"] = "com.cstcompany.ApplicationKt" } } } - 修正资源读取逻辑
禁止使用File("src/main/resources/xxx")这类相对路径读取资源,必须通过类加载器从classpath加载资源,兼容jar包运行环境:
你项目中使用了FreeMarker,安装插件时直接指定classpath下的模板路径即可,无需手动读取文件:错误写法(仅本地IDEA可运行)
val templateFile = File("src/main/resources/templates/index.ftl")正确写法(兼容jar部署)
// 读取资源为URL val templateUrl = ApplicationKt::class.java.classLoader.getResource("templates/index.ftl") // 读取资源为输入流 val templateStream = ApplicationKt::class.java.classLoader.getResourceAsStream("templates/index.ftl")install(FreeMarker) { templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates") } - 清理缓存重新构建
执行以下命令清理旧构建缓存后重新打包,避免历史产物干扰:gradle clean shadowJar --no-daemon - (可选)显式声明资源目录
如果上述配置后资源仍未打入,可在配置中显式指定Gradle识别的资源目录:sourceSets { main { resources { srcDirs("src/main/resources") } } }
打包结果验证
构建完成后,执行以下命令查看jar包内的文件列表,确认资源文件已被打入:
jar tf build/libs/[你的jar包文件名].jar
如果输出列表中能看到resources下存放的配置文件、模板文件(如logback.xml、templates/index.ftl),说明打包正常,直接运行jar即可。
内容的提问来源于stack exchange,提问作者Patrik Csikós
相关产品推荐
相关产品推荐

