Access a File from the Classpath in a Spring Application
https://www.baeldung.com/spring-classpath-file-access
I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:
1. Introduction
In this tutorial, we’ll see various ways to access and load the contents of a file that’s on the classpath using Spring.
2. Using Resource
The Resource interface helps in abstracting access to low-level resources. In fact, it supports handling of all kinds of file resources in a uniform manner.
Let’s start by looking at various methods to obtain a Resource instance.
2.1. Manually
For accessing a resource from the classpath, we can simply use ClassPathResource:
1 2 3 |
public Resource loadEmployees() { return new ClassPathResource("data/employees.dat"); } |
By default, ClassPathResource removes some boilerplate for selecting between the thread’s context classloader and the default system classloader.
However, we can also indicate the classloader to use either directly:
1 |
return new ClassPathResource("data/employees.dat", this.getClass().getClassLoader()); |
Or indirectly through a specified class:
1 2 3 |
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.
Another thing to note here is that the above method works only for absolute paths. If you want to specify a relative path, you can pass a second class argument. The path will be relative to this class:
1 |
new ClassPathResource("../../../data/employees.dat", Example.class).getFile(); |
The file path above is relative to the Example class.
2.2. Using @Value
We can also inject a Resource with @Value:
1 2 |
@Value("classpath:data/resource-data.txt") Resource resourceFile; |
And @Value supports other prefixes, too, like file: and url:.
2.3. Using ResourceLoader
Or, if we want to lazily load our resource, we can use ResourceLoader:
1 2 |
@Autowired ResourceLoader resourceLoader; |
And then we retrieve our resource with getResource:
1 2 3 4 |
public Resource loadEmployees() { 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:
1 2 3 4 5 |
ApplicationContext context;
public Resource loadEmployees() { return context.getResource("classpath:data/employees.dat"); } |
3. Using 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.
If we see usages of ResourceUtils in our code:
1 2 3 4 5 |
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
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.
Let’s imagine we have the following file, data/employees.dat, on the classpath:
1 |
Joe Employee,Jan Employee,James T. Employee |
4.1. Reading as a File
Now, we can read its contents by calling getFile:
1 2 3 4 5 6 7 8 9 10 11 12 |
@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, note that this approach expects the resource to be present in the filesystem and not within a jar file.
4.2. Reading as an InputStream
Let’s say, though, that our resource is inside a jar.
Then, we can instead read a Resource as an InputStream:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@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
In this quick article, we’ve seen a few ways to access and read a resource from the classpath using Spring including eager and lazy loading and on the filesystem or in a jar.
And, as always, I’ve posted all these examples over on GitHub.
'Web > SpringBoot' 카테고리의 다른 글
Jersey: A message body writer for Java Class and MIME mediatype application/json was not found (0) | 2019.08.01 |
---|---|
Mybatis Java Configuration for springboot ( mapper 사용 안하고) (0) | 2019.04.10 |
Spring Boot - Apache Kafka 카프카 연동 (0) | 2019.03.29 |
[mybatis] 다중 Database Setting (0) | 2019.03.21 |
Spring @Qualifier isn't working without @Primary [duplicate] (0) | 2019.03.19 |
댓글