該圖檔由Marna Buys在Pixabay上釋出
你好,我是看山。
本文聊一聊在 SpringBoot 應用中,通路加載類路徑(classpath)中的檔案内容的多種方法。
通過Resource接口
Resource接口抽象出一種更底層的方式管理資源,可以實作通過統一的方式處理各類檔案資源。下面是幾種擷取資源執行個體的方法。
手動加載
通路類路徑中的檔案,我們可以直接使用ClassPathResource加載内容,比如:
new ClassPathResource("data/resource-data.txt");
預設情況下,ClassPathResource會線上程的上下文類加載器和預設系統類加載器之間進行選擇,以删除樣闆檔案。我們也可以直接指定類加載器,比如:
new ClassPathResource("data/resource-data.txt", this.getClass().getClassLoader());
1
或者是通過指定類的類加載器:
new ClassPathResource("data/resource-data.txt", Employee.class.getClassLoader());
從Resource對象,我們可以很容易的将其轉換為InputStream或File對象。
上面說的方式都是相對于類路徑的位址。如果想要指定某個類的相對路徑,我們和可以通過指定具體類來定義,比如:
new ClassPathResource("../../../data/resource-data.txt", Example.class).getFile();
這樣就是相對于Example的相對路徑了。在實際使用中,不太建議通過類擷取其相對路徑的檔案。這樣會将類與檔案的相對坐标綁定,如果修改了類的包路徑,但是忘記修改檔案位置,就會出現錯誤。而且,大家現在一般是使用 Maven 之類的包管理器管理,可以直接在resources目錄中定義配置檔案,使用類路徑的相對位址加載檔案即可。
通過@Value自動轉換
我們還可以使用@Value直接注入Resource對象,比如:
@Value("classpath:data/resource-data.txt")
Resource resourceFile;
@Value還能支援其他的加載協定,比如file:或url:。
通過ResourceLoader加載
我們還能使用注入ResourceLoader來實作資源的懶加載,比如,先注入ResourceLoader執行個體:
@Autowired
ResourceLoader resourceLoader;
然後在我們需要的地方,通過ResourceLoader執行個體加載資源:
resourceLoader.getResource("classpath:data/resource-data.txt");
在 Spring 中,ApplicationContext實作了ResourceLoader,是以,我們也可以直接通過ApplicationContext執行個體加載資源,比如:
ApplicationContext context;
public Resource loadEmployeesWithApplicationContext() {
return context.getResource("classpath:data/resource-data.txt");
}
使用ResourceUtils加載資源
在 Spring 内部,還提供了一個工具類ResourceUtils,可以很友善的擷取類路徑中額資源。但是通過這個類的 Javadoc 可以看到,這個類主要是在 Spring 内部使用,也就是說,不太推薦這種用法。不過我們可以了解一下:
public File loadEmployeesWithSpringInternalClass()
throws FileNotFoundException {
return ResourceUtils.getFile(
"classpath:data/resource-data.txt");
}
我們可以了解其内部實作,但是還是建議使用其他更加标準的做法。
讀取資源中的内容
上面都是通過各種方式擷取了Resource資源,接下來我們就聊聊如果擷取資源對象的資料。
比如,我們的資源檔案内容如下:
站點:https://www.howardliu.cn
作者:看山
公号:看山的小屋 (kanshanshuo)
關注公号得福利:不知道多少 G 的資料(電子書、視訊等等)
通過File對象讀取
我們可以使用getFile方法得到File執行個體,就可以用讀取File對象的方式讀取檔案了,比如:
@Test
File resource = new ClassPathResource("data/resource-data.txt").getFile();
String content = new String(Files.readAllBytes(resource.toPath()));
但是這種方式不适用與讀取 jar 包中的檔案,鑒于現在很多應用都是通過 FatJar 方式部署,我們還需要找找其他方式。
通過InputStream對象讀取
File對象不适合 jar 包中資源讀取的原因在于檔案路徑格式不一樣,是以我們可以直接将資源内容讀取為流的形式,這樣就沒有檔案路徑的問題了。比如:
InputStream resource = new ClassPathResource("data/resource-data.txt").getInputStream();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource))) {
String content = reader.lines().collect(Collectors.joining("\n"));
}
讀取完畢。
文末總結
本文從加載資源、讀取内容兩個方法講解,給出了多種讀取方式。
《SpringBoot 實戰》是一個系列,我會通過實戰+原理的方式完整整個專欄,可以關注公衆号「看山的小屋」回複 spring 擷取源碼。
推薦閱讀
SpringBoot 實戰:一招實作結果的優雅響應
SpringBoot 實戰:如何優雅的處理異常
SpringBoot 實戰:通過 BeanPostProcessor 動态注入 ID 生成器
SpringBoot 實戰:自定義 Filter 優雅擷取請求參數和響應結果
SpringBoot 實戰:優雅的使用枚舉參數
SpringBoot 實戰:優雅的使用枚舉參數(原理篇)
SpringBoot 實戰:在 RequestBody 中優雅的使用枚舉參數
SpringBoot 實戰:在 RequestBody 中優雅的使用枚舉參數(原理篇)
SpringBoot 實戰:JUnit5+MockMvc+Mockito 做好單元測試
SpringBoot 實戰:加載和讀取資源檔案内容