Scala读取resources目录文件失败,Docker运行测试报空指针异常
问题根源
getResource()、scala.io.Source.fromResource()这类资源读取方法的寻址基准是编译后的类路径(classpath)根目录,和本地开发的项目源码目录结构无关- Maven构建项目时,
src/test/resources目录下的所有文件会直接拷贝到测试类路径的根目录,不会保留/src/test/resources这层路径前缀。你写的路径包含了源码目录层级,运行时自然找不到对应资源,返回null后调用getPath方法就会触发空指针 - Docker中运行的是编译后的打包产物,完全不存在本地的源码目录结构,所以必然会复现该问题
修复方案
修正资源路径写法
删除路径中的/src/test/resources前缀,直接写资源在resources目录下的相对路径即可,三类正确写法参考:
- 基于类读取资源
// 开头的/代表从类路径根目录寻址 val filename = getClass.getResource("/data/my_data.txt").getPath
- 用Scala原生工具读取
// fromResource默认从类路径根寻址,无需加开头的/ val ss = scala.io.Source.fromResource("data/my_data.txt") // 读取完成后注意关闭资源 ss.close()
- 基于类加载器读取
// 无需加开头的/ val filename = ClassLoader.getSystemResource("data/my_data.txt").getPath
注意:
getClass.getResource如果路径开头不带/,会基于当前类的包路径寻址;Source.fromResource和ClassLoader.getSystemResource默认都是从类路径根目录寻址,不要额外加开头的/避免寻址失败。
确认POM配置(可选)
不需要单独将src/test/resources/data配置为资源目录,默认src/test/resources下的所有文件都会被处理,正确的testResources配置参考:
<build> <testResources> <testResource> <directory>src/test/resources</directory> <includes> <include>**/*.txt</include> <!-- 可添加其他需要处理的资源后缀 --> </includes> </testResource> </testResources> </build>
Docker镜像校验
如果修正路径后仍有问题,可在Docker测试启动逻辑中添加类路径内容打印,确认my_data.txt确实被打包到了类路径下的/data目录中,避免构建镜像时遗漏资源文件。
内容的提问来源于stack exchange,提问作者Rahman
相关产品推荐
相关产品推荐

