Spring 应用访问Classpath路径下的文件

本文我们了解下spring多种方式访问classpath路径下文件。

1. 使用Resource

Resource接口是对底层资源的抽象。提供以统一的方式操作各种文件资源。首先我们看获得Resource实例的不同方法。

1.1. 手工获取

可以简单使用ClassPathResource类访问classpath路径下文件:

public Resource loadEmployees() {
    return new ClassPathResource("data/employees.dat");
}

缺省情况下,ClassPathResource无需指定固定代码,用于选择线程上下文或缺省系统类加载器。实际也可以直接明确指定:

return new ClassPathResource("data/employees.dat", this.getClass().getClassLoader());

或通过特定的类进行指定:

return new ClassPathResource("data/employees.dat", Employee.class.getClassLoader());

注意,我们可以很容易地从Resource获得InputStream或File等Java标准表示形式。这里需要提醒的另一件事是,上面的方法只适用于绝对路径。如果希望取得相对路径,需传入第二个类参数。路径将相对于这个类:

new ClassPathResource("../../../data/employees.dat", Example.class).getFile();

上面的文件路径是相对于Example类。

1.2. 使用@Value

可以使用@Value注入Resource:

@Value("classpath:data/resource-data.txt")
Resource resourceFile;

@Value也支持其他前缀,如:file和url:

1.3. 使用ResourceLoader

如果想懒价值资源,可以使用ResourceLoader:

@Autowired
ResourceLoader resourceLoader;

然后使用getResource方法获得资源:

public Resource loadEmployees() {
    return resourceLoader.getResource("classpath:data/employees.dat");
}

这里也说明下,ResourceLoader是由所有具体的ApplicationContext实现的,这意味着在更适合的场景,也可以简单地通过ApplicationContext获取资源:

ApplicationContext context;
 
public Resource loadEmployees() {
    return context.getResource("classpath:data/employees.dat");
}

2. 使用ResourceUtils

需要注意的是,在Spring中还有另一种检索资源的方法,但是ResourceUtils Javadoc很清楚说明该类主要是内部使用。使用示例代码:

public File loadEmployeesWithSpringInternalClass() throws FileNotFoundException {
    return ResourceUtils.getFile("classpath:data/employees.dat");
}

我们应该仔细考虑其实现机理,因为使用上面提及的标准方法可能更好。

3. 读取资源数据

获得Resource之后,读取内容也就比较容易了。之前也提及了,通过Resource可以很方便获得File或InputStream。假设classpath有data/employee.data文件,内容如下:

Joe Employee,Jan Employee,James T. Employee

3.1. 获得File

通过getFile方法或的File:

@Test
public void whenResourceAsFile_thenReadSuccessful() throws IOException {
  
    File resource = new ClassPathResource("data/employees.dat").getFile();
    String employees = new String(Files.readAllBytes(resource.toPath()));
    assertEquals("Joe Employee,Jan Employee,James T. Employee", employees);
}

注意,上面方面期望资源是在文件系统中,而不是在jar文件中。

3.2. 获取InputStream

如果资源是在jar中,那么需要使用Resource的getInputStream方法:

@Test
public void whenResourceAsStream_thenReadSuccessful() throws IOException {

    InputStream resource = new ClassPathResource("data/employees.dat").getInputStream();
    try ( BufferedReader reader = new BufferedReader( new InputStreamReader(resource)) ) {
        String employees = reader.lines() .collect(Collectors.joining("\n"));
  
        assertEquals("Joe Employee,Jan Employee,James T. Employee", employees);
    }
}

4. 总结

本文我们介绍了Spring提供的几种方法访问和读取classpath路径下的文件,可以是立刻加载和懒价值,包括文件系统文件或jar中的文件。