历史文章(文章累计460+)
《国内最全的Spring Boot系列之一》
《国内最全的Spring Boot系列之二》
《国内最全的Spring Boot系列之三》
《国内最全的Spring Boot系列之四》
《国内最全的Spring Boot系列之五》
《国内最全的Spring Boot系列之六》
SpringBoot版的低代码开发平台,关联无 SQL - 第462篇
SpringBoot项目打成jar后加载外部配置文件 - 第463篇
线上环境无法读取classpath下的txt文件?- 第464篇
修炼技术的九阳神功,让你从模式小白轻松进阶为模式大神
66个ChatGPT副业赚钱技巧 - 第3篇
ChatGPT+剪映·副业赚钱技巧实战教程·《制作阿凡达解说视频》- 第4篇
悟纤:师傅,你在前面说到《线上环境无法读取classpath下的txt文件?》你没有讲清楚为什么使用ClassPathResource就可以了呢?
师傅:这个么,就有点说,牵涉到了java底层的ClassLoader的机制。
悟纤:那你也和我简单说说吗?
师傅:那师傅就和你说说。但是确实有点难懂,要认真听哦。
悟纤:师傅万岁。
0
导读
在之前有篇文章中《线上环境无法读取classpath下的txt文件?》中说到了解决这个问题的方式就是使用ClassPathResource和class.getResourceAsStream,那为什么这样的方式可以呢?又是什么原理呢?本文带你进行解密。
1
一、ClassPathResource
ClassPathResource是 Spring Framework 中的一个类,用于访问类路径下的资源文件。它可以读取到流,是因为它内部使用了ClassLoader来加载资源文件,而 ClassLoader可以将资源文件转换成 InputStream 流。具体的实现方式是,ClassPathResource内部使用了当前线程的上下文 ClassLoader 来获取资源文件的 URL,然后使用该 URL 打开一个InputStream 流,最终返回给调用者。因此,ClassPathResource 可以方便地读取到类路径下的资源文件,并返回一个 InputStream 流供调用者使用。
使用ClassPathResource 的方法如下:
ClassPathResource resource = new ClassPathResource("path/to/resource");
InputStream inputStream = resource.getInputStream();
其中,path/to/resource是资源文件的相对路径。使用 ClassPathResource 时,需要注意以下几点:
(1)ClassPathResource 只能读取类路径下的资源文件,无法读取其他路径下的文件。
(2)要确保资源文件存在于类路径下,并且在编译后被打包到 jar 或 war 文件中。
(3)资源文件的路径应该使用正斜杠(/)分隔符,而不是反斜杠(\)分隔符。
1
二、class.getResourceAsStream
二、class.getResourceAsStream
class.getResourceAsStream 是 Java 中的一个方法,用于获取类路径下的资源文件的 InputStream 流。它可以读取到流,是因为它内部使用了ClassLoader来加载资源文件,并将其转换为InputStream流。具体的实现方式是,class.getResourceAsStream 方法会根据传入的相对路径,先将其转换为绝对路径,然后使用当前线程的上下文 ClassLoader 来获取资源文件的 URL,最后使用该 URL 打开一个 InputStream 流,并返回给调用者。因此,class.getResourceAsStream 可以方便地读取到类路径下的资源文件,并返回一个 InputStream 流供调用者使用。
在使用class.getResourceAsStream()方法读取类路径下的资源文件时,需要注意以下几点:
(1)路径问题
getResourceAsStream()方法需要传入资源文件的路径,路径的写法有一定的规则。如果资源文件和当前类在同一个包下,可以直接使用文件名作为路径;如果资源文件在当前类的父包或更高级的包中,需要使用相对路径或绝对路径;如果资源文件在classpath下的根目录,需要在路径前加上“/”。
(2)返回值问题
getResourceAsStream()方法返回一个InputStream对象,可以通过该对象读取资源文件的内容。需要注意的是,如果资源文件不存在,该方法返回null。因此,在使用该方法时,需要判断返回值是否为null,避免空指针异常。
(3)编码问题
getResourceAsStream()方法返回的InputStream对象读取的是二进制数据,如果资源文件是文本文件,需要根据文件的编码格式将二进制数据转换成字符串。可以使用Java中的InputStreamReader和BufferedReader类来实现。
(4)路径分隔符
在Windows操作系统中,路径分隔符是“\”,而在Java中,路径分隔符是“/”。因此,在使用getResourceAsStream()方法读取资源文件时,需要使用“/”作为路径分隔符,而不能使用“\”。
总之,在使用class.getResourceAsStream()方法读取类路径下的资源文件时,需要注意路径问题、返回值问题、编码问题和路径分隔符等细节,才能正确地读取文件内容。
2
一、准备工作
三、ClassLoader为什么可以读取到流?
上面两个最终都是ClassLoader加载了,那么为什么ClassLoaer可以加载进来流呐?
ClassLoader是Java中的一个重要机制,用于动态加载类和资源文件。ClassLoader可以从指定的路径中查找并加载资源文件,然后返回一个InputStream对象,以便读取文件内容。ClassLoader可以读取到流的原因如下:
(1)ClassLoader的结构
ClassLoader是Java中的一个类,它可以被看作是类加载器的抽象类。在Java中,ClassLoader是一个层次结构,每个ClassLoader都有一个父ClassLoader,形成了一个树形结构。当需要加载类或资源文件时,ClassLoader会先查询自身的类路径或资源路径,如果找不到,则会委托给父ClassLoader进行查找。这种委托机制保证了ClassLoader可以查找到所有的资源文件。
(2)加载资源文件
当ClassLoader需要加载资源文件时,会通过getResourceAsStream()方法查找资源文件,并返回一个InputStream对象。该方法查找资源文件的顺序是先在ClassLoader自身的类路径或资源路径中查找,如果找不到,则委托给父ClassLoader进行查找。如果父ClassLoader也找不到,则继续委托上级ClassLoader进行查找,直到找到为止。这种查找机制保证了ClassLoader可以查找到所有的资源文件。
(3)读取流
当ClassLoader找到资源文件后,会返回一个InputStream对象,以便读取文件内容。InputStream对象可以读取任意类型的文件,包括文本文件、二进制文件等。因此,ClassLoader可以通过InputStream对象读取任意类型的资源文件,并进行相应的处理。
综上所述,ClassLoader可以读取到流的原因是由于它具有一个层次结构,可以查找到所有的资源文件,并返回一个InputStream对象,以便读取文件内容。这种机制能够满足Java程序动态加载类和资源文件的需求,为Java开发提供了很大的灵活性和扩展性。
4
最近累坏了
最近真的是忙累坏了,主要搞了两个大的时期:
其一:设计模式的书的物资准备和宣传
用“恋爱脑”的角度去解读设计模式,脑洞大开,一阅既懂,核心原理剖析+应用场景实例+前沿技术解读,让你从模式小白轻松进阶为模式大神。
①打造全网最易理解最有趣的设计模式课程体系;
②寓教于乐,学习进阶不再枯燥;
③提升内功,更好的理解框架源码设计思想,封装中间件;
💪值得每位IT人把玩的一本书:https://item.jd.com/13860042.html(长按链接“复制”到浏览器购买,内附详细信息)
如果您更青睐视频学习方式,不妨来此:https://dwz.cn/wqO0MAy7 (长按链接“复制”到浏览器购买,内附详细信息)
一顿饭钱就拿走大神十年心血💔,哈哈,苦BB的IT人(互联网行业形式严峻,希望各位仔都成为金字塔尖的人物)
其二:ChatGPT星球的创建和运营
我也入局了!ChatGPT带来了技术变革之风向,跟随时代步伐和圈内好友,创建了一个ChatGPT知识星球。
持续针对ChatGPT基础操作、最新风向、应用案例、变现方式、商业价值等多维度输出干货内容!
正式运营价格定在299,目前地板价78!加入就送独立的 ChatGPT 账号,目前全网断货,我们也不多,送完为止!
并赠送ChatGPT中文站(https://csdn.wuqian.fun)永久授权key。
目前已授权ChatGPT中文站试用key:sk-lhtjtestkey24hour0808,左下角点击设置填入后体验试用,24小时后失效。