Gradle+IntelliJ环境下ClassLoader加载resources仅获取build目录文件问题
问题根因
resources是项目的静态只读资源源目录,Gradle在构建/IDEA在运行项目时,会自动将src/main/resources下的所有文件复制到build目录的对应输出位置,ClassLoader加载的是该目录下的临时副本。每次重新构建、启动项目时,build目录都会被重新生成覆盖,因此写入build目录的修改自然不会保留,也不会同步到src目录的源文件。
适配不同场景的解决方案
场景1:仅本地开发阶段需要修改resources源文件
该方案仅适用于本地调试,不可用于生产环境:
- 打开IDEA的运行配置,确认「工作目录(Working directory)」设置为项目根目录
- 直接通过相对路径定位源resources文件,不要用ClassLoader获取,示例路径:
./src/main/resources/你的配置文件路径.json,直接对该路径的文件做读写即可修改源文件,重启不会丢失。
场景2:应用运行时需要持久化存储可修改的JSON数据
不要把可写的动态数据放在resources目录下,resources设计上仅用于存放静态只读资源,推荐方案如下:
- 自定义可写存储目录,可选择系统用户目录下的应用专属文件夹、启动参数指定的外部目录等位置
- 首次启动时如果找不到自定义目录下的配置文件,就从resources读取默认配置,复制到自定义目录下,后续所有读写操作都作用于自定义目录下的文件即可。
示例代码逻辑参考:
// 定义用户侧可写的配置文件路径 File writableConfig = new File(System.getProperty("user.home") + "/.my_app/config.json"); if (!writableConfig.exists()) { // 首次启动无配置时,从resources拷贝默认配置到可写目录 try (InputStream defaultConfigIn = getClass().getClassLoader().getResourceAsStream("default_config.json")) { Files.copy(defaultConfigIn, writableConfig.toPath()); } catch (IOException e) { // 异常处理逻辑 e.printStackTrace(); } } // 后续所有读写操作都针对writableConfig即可
注意:打包为jar包运行时,jar包内部的resources文件是只读的,没有任何办法直接修改jar包内的文件内容,所有需要动态修改的配置必须放在jar包外部的可写目录。
内容的提问来源于stack exchange,提问作者GRETA
相关产品推荐
相关产品推荐

