天天看點

SpringBoot 實戰:加載和讀取資源檔案

SpringBoot 實戰:加載和讀取資源檔案

該圖檔由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 實戰:加載和讀取資源檔案内容