1. Introduction
1.介绍
In this tutorial, we’ll demonstrate various ways to access and load the contents of a file that’s on the classpath using Spring.
在本教程中,我们将演示使用Spring访问和加载classpath上的文件内容的各种方法。
2. Using Resource
2.使用资源
The Resource interface helps in abstracting access to low-level resources. In fact, it supports the handling of all kinds of file resources in a uniform manner.
Resource接口有助于抽象出对低层资源的访问。事实上,它支持以一种统一的方式处理所有类型的文件资源。
Let’s start by looking at various methods to obtain a Resource instance.
让我们先来看看获取Resource实例的各种方法。
2.1. Manually
2.1.手动操作
For accessing a resource from the classpath, we can simply use ClassPathResource:
对于从classpath访问资源,我们可以简单地使用ClassPathResource。
public Resource loadEmployeesWithClassPathResource() {
return new ClassPathResource("data/employees.dat");
}
By default, ClassPathResource removes some boilerplate by selecting between the thread’s context classloader and the default system classloader.
默认情况下,ClassPathResource通过在线程的上下文classloader和默认的系统classloader之间进行选择来移除一些模板。
However, we can also indicate the classloader to use either directly:
然而,我们也可以指示classloader直接使用其中之一。
return new ClassPathResource("data/employees.dat", this.getClass().getClassLoader());
Or indirectly through a specified class:
或者通过一个指定的类间接地进行。
return new ClassPathResource(
"data/employees.dat",
Employee.class.getClassLoader());
Note that from Resource, we can easily jump to Java standard representations like InputStream or File.
请注意,从Resource,我们可以很容易地跳到Java标准表示法,如InputStream或File。
Another thing to note here is that the above method works only for absolute paths. If we want to specify a relative path, we can pass a second class argument. The path will be relative to this class:
这里需要注意的另一件事是,上述方法只对绝对路径有效。如果我们想指定一个相对路径,我们可以传递第二个class参数。该路径将是相对于这个类的。
new ClassPathResource("../../../data/employees.dat", Example.class).getFile();
The file path above is relative to the Example class.
上面的文件路径是相对于Example class.的。
2.2. Using @Value
2.2.使用@Value
We can also inject a Resource with @Value:
我们也可以用@Value注入一个Resource。
@Value("classpath:data/resource-data.txt")
Resource resourceFile;
@Value supports other prefixes too, like file: and url:.
@Value也支持其他前缀,如file:和url:。
2.3. Using ResourceLoader
2.3.使用资源加载器
If we want to lazily load our resource, we can use ResourceLoader:
如果我们想懒散地加载我们的资源,我们可以使用ResourceLoader。
@Autowired
ResourceLoader resourceLoader;
Then we retrieve our resource with getResource:
然后我们用getResource来检索我们的资源。
public Resource loadEmployeesWithResourceLoader() {
return resourceLoader.getResource(
"classpath:data/employees.dat");
}
Note too that ResourceLoader is implemented by all concrete ApplicationContexts, which means that we can also simply depend on ApplicationContext if that suits our situation better:
也请注意,ResourceLoader由所有具体的ApplicationContexts实现,这意味着我们也可以简单地依赖ApplicationContext,如果这更适合我们的情况。
ApplicationContext context;
public Resource loadEmployeesWithApplicationContext() {
return context.getResource("classpath:data/employees.dat");
}
3. Using ResourceUtils
3.使用ResourceUtils
As a caveat, there is another way to retrieve resources in Spring, but the ResourceUtils Javadoc is clear that the class is mainly for internal use.
需要注意的是,在Spring中还有另一种检索资源的方法,但ResourceUtils Javadoc明确指出该类主要供内部使用。
If we see usages of ResourceUtils in our code:
如果我们在代码中看到ResourceUtils的使用。
public File loadEmployeesWithSpringInternalClass()
throws FileNotFoundException {
return ResourceUtils.getFile(
"classpath:data/employees.dat");
}
We should carefully consider the rationale, as it’s probably better to use one of the standard approaches above.
我们应该仔细考虑其中的道理,因为使用上述的标准方法之一可能更好。
4. Reading Resource Data
4.阅读资源数据
Once we have a Resource, it’s easy for us to read the contents. As we have already discussed, we can easily obtain a File or an InputStream reference from the Resource.
一旦我们有了一个Resource,我们就可以很容易地读取其内容。正如我们已经讨论过的,我们可以很容易地从Resource中获得一个File或一个InputStream引用。
Let’s imagine we have the following file, data/employees.dat, on the classpath:
让我们想象一下,我们有以下文件, data/employees.dat,在classpath上:。
Joe Employee,Jan Employee,James T. Employee
4.1. Reading as a File
4.1.作为一个文件阅读
Now we can read its contents by calling getFile:
现在我们可以通过调用getFile:来读取其内容。
@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);
}
Although, it should be noted that this approach expects the resource to be present in the filesystem and not within a jar file.
不过,应该注意的是,这种方法希望资源存在于文件系统中,而不是在jar文件中。
4.2. Reading as an InputStream
4.2.作为一个InputStream读
Let’s say though, that our resource is inside a jar.
让我们说,我们的资源是在一个罐子里。
Then we can instead read a Resource as an InputStream:
那么我们可以将Resource作为InputStream来读取。
@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);
}
}
5. Conclusion
5.结论
In this brief article, we’ve examined a few ways to access and read a resource from the classpath using Spring. This includes eager and lazy loading, and on the filesystem or in a jar.
在这篇简短的文章中,我们研究了使用Spring从classpath访问和读取资源的几种方法。这包括急迫加载和懒惰加载,以及在文件系统或jar中。
As always, all of these examples are available over on GitHub.
一如既往,所有这些例子都可以在GitHub上找到。