Jar下获取File对象问题

【需求:】 Java 获取配置文件File对象,且 jar 包方式运行无误

这里先给出错误代码,以及个人思路:

方式1 : new File(path)
目录结构:

img

    public static void main(String[] args) {
        File file = new File("src/main/resources/words.txt");
        System.out.println(file.getAbsolutePath());
        System.out.println(file.exists());
    }

开发环境下执行,但打包成jar 情况下,无法执行 ---> 找不到文件,且资源文件已经在jar中了,只不过位置变量如果使用 File file = new File("classes/words.txt"); Jar下可以执行,但Idea开发环境下不能执行。

方式2:ClassLoader

    public static void main(String[] args) {
        URL url = ClassLoader.getSystemClassLoader().getResource("words.txt");
        String filePath = url.getFile();
        File file = new File(filePath);
        System.out.println(file.exists());
    }

结果根上面的一样,Idea开发环境下可以获取文件 (file.exists() = > true ) , 而 jar 包下 找不到文件(file.exists() = > false),并且在jar下运行时,如果获取file的绝对路径为:F:\desktop\untitled2\target\file:\F:\desktop\untitled2\target\untitled2-1.0-SNAPSHOT.jar!\words.txt 很奇怪。

方式3:ClassLoader -> stream

    public static void main(String[] args) throws IOException {
        URL url = ClassLoader.getSystemClassLoader().getResource("words.txt");
        InputStream inputStream = url.openStream();
        System.out.println(inputStream.available());
        inputStream.close();
    }

这种方式 开发环境和jar环境下都可以,但不符合我的需求。我需要的配置文件的File对象。这里是文件流,估计有人会质疑我这个需求》。,其实我也是无赖之举,项目引用的第三方包的某个功能方法的参数入口就是个File类型的对象获取直接 string类型的url。

其他:我还尝试过 spring 的 ResourceUtils.getFile 工具方法,也是一样(开发IDEA环境下,可以获取到文件。但在Jar环境下就获取不到了)。有没有什么方式可以获取配置文件的File对象

我的思考想法
  1. 方式3中能够获取文件输入流比较令我深思,我们平常获取文件流之前想要先获取到该文件File对象才行吧。那么说明方式3中应该获取了File文件对象,然后才获取它的文件流并返回,但它是怎么成功获取File文件对象的呢?。
  2. 在设计api的时候是不是应该避免设计为File类型的参数哦,如果将File类型的参数换成 stream 的话好像也不好,因为这个想要close,不好把控close的时机,这里有什么别的建议码?。
  3. java 打包成Jar包后,项目的目录结构与Jar包中的目录结构是不同的,所以项目中获取文件不能像方式1那样写。如果要改,该怎么改呢?难道这里还要区分环境? 开发使用src/main/resources/words.txt,部署生产环境使用classes/words.txt ,感觉这不是一个聪明的方式,这里还是什么其他思路码?。

恕我直言,接口设计之初就不应该考虑使用file,优先inputStream和byte[],如果你这里的接口没有提供这两个参数的重载方法,固定死了只能走file对象,那就只能曲线救国了,PathMatchingResourcePatternResolver去classpath下扫描文件,扫描结果单个文件是Resouce,Resource可以直接获取URL,此时可以直接判断你这个资源是在jar包中还是在文件夹中(war包搭配外置tomcat的方式)

img


如果这个值是jar,自己把文件复制到服务器的指定位置,file对象就有了

看下打包出来的jar包结构,直接以压缩包的形式就能打开jar包。