“This is the fifth day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Hello, I’m looking at the mountains.

This article discusses various ways to access the contents of a file in the load classpath in a SpringBoot application.

throughResourceinterface

The Resource interface abstracts a lower-level way to manage resources, which can handle all kinds of file resources in a unified way. Here are several ways to get resource instances.

Manual loading

To access files in the classpath, we can load content directly using the ClassPathResource, for example:

new ClassPathResource("data/resource-data.txt");
Copy the code

By default, the ClassPathResource chooses between the thread’s context classloader and the default system classloader to remove the boilerplate. We can also specify class loaders directly, for example:

new ClassPathResource("data/resource-data.txt".this.getClass().getClassLoader());
Copy the code

Or by specifying the class loader for the class:

new ClassPathResource("data/resource-data.txt", Employee.class.getClassLoader());
Copy the code

From Resource objects, we can easily convert them to InputStream or File objects.

All the above methods are relative to the classpath address. If we want to specify the relative path of a class, we can specify it by specifying the concrete class, for example:

new ClassPathResource(".. /.. /.. /data/resource-data.txt", Example.class).getFile();
Copy the code

This is the relative path to Example. In practice, it is not recommended to get files with relative paths from a class. This binds the relative coordinates of the class to the file, and an error occurs if you change the package path of the class but forget to change the file location. Furthermore, you can now use a package manager such as Maven to define configuration files directly in the Resources directory and load the files using the relative address of the classpath.

through@ValueAutomatic conversion

We can also inject Resource objects directly using @Value, such as:

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

@value can also support other loading protocols, such as File: or URL:.

throughResourceLoaderloading

We can also inject ResourceLoader to implement lazy loading of resources. For example, inject ResourceLoader instances first:

@Autowired
ResourceLoader resourceLoader;
Copy the code

Then load the resources where we need them through the ResourceLoader instance:

resourceLoader.getResource("classpath:data/resource-data.txt");
Copy the code

In Spring, ApplicationContext implements ResourceLoader, so we can also load resources directly from ApplicationContext instances, such as:

ApplicationContext context;

public Resource loadEmployeesWithApplicationContext(a) {
    return context.getResource("classpath:data/resource-data.txt");
}
Copy the code

useResourceUtilsLoad resources

Within Spring, a utility class ResourceUtils is provided to easily access resources in the classpath. But as you can see from the Javadoc of this class, this class is primarily used within Spring, which means it is not recommended. But here’s what we can learn:

public File loadEmployeesWithSpringInternalClass(a) 
  throws FileNotFoundException {
    return ResourceUtils.getFile(
      "classpath:data/resource-data.txt");
}
Copy the code

We can look at the internal implementation, but recommend other, more standard practices.

Read the contents of the resource

Resource objects are obtained in various ways. Let’s talk about how to obtain the data of Resource objects.

For example, our resource file would look like this:

Site: https://www.howardliu.cn author: see the mountain public number: see the mountain hut (Kanshanshuo) concern public number welfare: do not know how many G of information (e-books, videos and so on)Copy the code

throughFileObject to read

We can use the getFile method to get the File instance, and then we can read the File in the same way as the File object, for example:

@Test
File resource = new ClassPathResource("data/resource-data.txt").getFile();
String content = new String(Files.readAllBytes(resource.toPath()));
Copy the code

However, this approach does not work for reading files in jar packages, and given how many applications are deployed using FatJars, we need to find other ways.

throughInputStreamObject to read

The reason File objects are not suitable for reading resources in JAR packages is that the File path format is different, so we can read the resource content as a stream directly, and there is no File path problem. Such as:

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"));
}
Copy the code

Read complete.

At the end of the article to summarize

This paper explains two methods of loading resources and reading content, and gives a variety of reading methods.

“SpringBoot actual combat” is a series, I will complete the whole column through actual combat + principle, you can pay attention to the public number “to see the mountain hut” reply spring source code.

Recommended reading

  • SpringBoot: elegant response to achieve results in one move
  • SpringBoot: How to handle exceptions gracefully
  • SpringBoot: Dynamically injects the ID generator through the BeanPostProcessor
  • SpringBoot: Customizes Filter to gracefully obtain request parameters and response results
  • SpringBoot: Elegant use of enumeration parameters
  • SpringBoot: Elegant use of enumeration parameters (Principles)
  • SpringBoot: Gracefully use enumeration parameters in the RequestBody
  • SpringBoot: Gracefully using enumeration parameters in the RequestBody
  • Do unit tests with JUnit5+MockMvc+Mockito

Hello, I’m looking at the mountains. Swim in the code, play to enjoy life. If this article is helpful to you, please like, bookmark, follow.