- Access a File from the Classpath in a Spring Application
- Get started with Spring 5 and Spring Boot 2, through the reference Learn Spring course:
- 1. Introduction
- Further reading:
- A Guide to the ResourceBundle
- Load a Resource as a String in Spring
- 2. Using Resource
- 2.1. Manually
- 2.2. Using @Value
- 2.3. Using ResourceLoader
- 3. Using ResourceUtils
- 4. Reading Resource Data
- 4.1. Reading as a File
- 4.2. Reading as an InputStream
- 5. Conclusion
- Урок 3: Работа с ресурсами
- Что вам потребуется
- Настройка проекта
- Введение
- Встроенные реализации
- Получение ресурсов
- ResourceLoader
- ResourceLoaderAware
- Получение ресурса по его пути
- Итог
Access a File from the Classpath in a Spring Application
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
We rely on other people’s code in our own work. Every day.
It might be the language you’re writing in, the framework you’re building on, or some esoteric piece of software that does one thing so well you never found the need to implement it yourself.
The problem is, of course, when things fall apart in production — debugging the implementation of a 3rd party library you have no intimate knowledge of is, to say the least, tricky.
Lightrun is a new kind of debugger.
It’s one geared specifically towards real-life production environments. Using Lightrun, you can drill down into running applications, including 3rd party dependencies, with real-time logs, snapshots, and metrics.
Learn more in this quick, 5-minute Lightrun tutorial:
Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.
The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.
Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.
Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes:
DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema.
The way it does all of that is by using a design model, a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.
And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
Get started with Spring 5 and Spring Boot 2, through the reference Learn Spring course:
We’re looking for a new Java technical editor to help review new articles for the site.
1. Introduction
In this tutorial, we’ll demonstrate various ways to access and load the contents of a file that’s on the classpath using Spring.
Further reading:
A Guide to the ResourceBundle
It’s always challenging to maintain and extend multilingual applications. This article covers how to use the ResourceBundle to cope with the varieties that come up when you need to provide the same content to different cultures.
Load a Resource as a String in Spring
Learn how to inject the contents of a resource file into our beans as a String, with Spring’s Resource class making this very easy.
2. Using Resource
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.
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:
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.
However, we can also indicate the classloader to use either directly:
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.
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:
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:
@Value("classpath:data/resource-data.txt") Resource resourceFile;
@Value supports other prefixes too, like file: and url:.
2.3. Using ResourceLoader
If we want to lazily load our resource, we can use ResourceLoader:
@Autowired ResourceLoader resourceLoader;
Then we retrieve our resource with 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:
ApplicationContext context; public Resource loadEmployeesWithApplicationContext() < 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:
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:
Joe Employee,Jan Employee,James T. Employee
4.1. Reading as a File
Now we can read its contents by calling 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.
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:
@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 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.
As always, all of these examples are available over on GitHub.
Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.
The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.
Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.
Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes:
Урок 3: Работа с ресурсами
Этот урок освещает работу с ресурсами и основан на оригинальной документации §6. Resources.
Что вам потребуется
Настройка проекта
Прежде чем вы начнете изучать этот урок, вам необходимо создать класс lessons.starter.ResourceStarter .
Введение
Стандартный Java-класс java.net.URL и стандартные обработчки различных URL префиксов к сожалению не во всём достаточно пригодны для доступа к низкоуровневым ресурсам. К примеру, нет стандартизированных реализаций URL , которые могут быть использованы для доступа к ресурсам, которые необходимо получить из classpath, либо ServletContext . Можно зарегистрировать новые обработчики для конкретных URL префиксов, но это довольно сложная задача, а интерфейс URL все ещё недостаточно функционален.
Spring предоставляет интерфейс Resource , более совместимый для низкоуровнего доступа.
public interface Resource extends InputStreamSource < boolean exists(); boolean isOpen(); URL getURL() throws IOException; File getFile() throws IOException; Resource createRelative(String relativePath) throws IOException; String getFilename(); String getDescription(); //. >
public interface InputStreamSource
Интерфейс Resource используется и в самом Spring в качестве типа аргументов во многих методах, где необходимы ресурсы. Другие методы принимают в качестве аргументов строковые значения, которые в конечном счете используются для получения ресурсов. Важно понимать, что реализации интерфейса Resource не заменяют функциональность, а являются «оберткой». Например, URLResource является «оберткой» для URL .
Встроенные реализации
Из реализаций интерфейса Resource , которые входят в состав Spring, стоит выделить следующие:
- UrlResource — является оберткой для java.net.URL и может быть использован для доступа к любому объекту по его URL, например, файлы, HTTP или FTP ресурс и др., либо через строковое представление с соответветствующими префиксами classpath: , file: , http: , ftp: и др.
- ClassPathResource — представляет ресурс, который может быть получен из classpath и поддерживает ресурсы как java.io.File , если они расположены в файловой системе, а не в jar
- FileSystemResource — реализация для обработки java.io.File . Поддерживает как File , так и URL
- ServletContextResource — реализация для обработки ServletContext ресурсов относительно корневой директории web-приложения. Поддерживает потоковый и к URL доступ. Доступ к java.io.File возможен, когда web-приложение развернуто и ресурс физически находится в файловой системе
- InputStreamResource — реализация для обработки InputStream . Должен использоваться только тогда, когда нет доступных соответствующих реализаций интерфейса Resource или нет возможности использовать более предпочтительный вариант ByteArrayResource
- ByteArrayResource — реализация для обработки массива байтов. Полезен для загрузки контента из любого массива байтов, не прибегая к использованию InputStreamResource
Получение ресурсов
ResourceLoader
Интерфейс ResourceLoader предназначен для реализации возврата, т.е. загрузки, экземпляров Resource .
public interface ResourceLoader
Все контексты приложения реализуют данный интерфейс. Когда вы вызываете метод getResource() в определенном контексте приложения без указания префикса, то вы получите тот тип Resource , который соответствует контексту. В качестве демонстрации, можно запустить метод src/main/java/lessons/starter/ResourceStarter#printClassResourcesByContextNoPrefix() . В методе src/main/java/lessons/starter/ResourceStarter#printClassResourcesByContextWithPrefix() на консоль отбражаются подобные результаты, но ресурс передается уже с префиксом.
public class ResourceStarter < public static final Logger LOGGER = LogManager.getLogger(ResourceStarter.class); public static void main(String[] args) throws IOException < LOGGER.info("Starting resources. "); ResourceStarter starter = new ResourceStarter(); starter.printClassResourcesByContextNoPrefix(); starter.printClassResourcesByContextWithPrefix(); >public void printClassResourcesByContextNoPrefix() < LOGGER.info("*******printClassResourcesByContextNoPrefix**********"); ApplicationContext context = new AnnotationConfigApplicationContext(); Resource resource = context.getResource("resources/log4j.properties"); LOGGER.info("AnnotationConfigApplicationContext: " + resource.getClass().getSimpleName()); context = new ClassPathXmlApplicationContext(); resource = context.getResource("resources/log4j.properties"); LOGGER.info("ClassPathXmlApplicationContext: " + resource.getClass().getSimpleName()); context = new FileSystemXmlApplicationContext(); resource = context.getResource("resources/log4j.properties"); LOGGER.info("FileSystemXmlApplicationContext: " + resource.getClass().getSimpleName()); LOGGER.info("****************************************************"); >public void printClassResourcesByContextWithPrefix() < LOGGER.info("*******printClassResourcesByContextWithPrefix*******"); ApplicationContext context = new AnnotationConfigApplicationContext(); Resource resource = context.getResource("file:resources/log4j.properties"); LOGGER.info("file: " + resource.getClass().getSimpleName()); resource = context.getResource("http://spring.io/img/favicon.png"); LOGGER.info("http: " + resource.getClass().getSimpleName()); resource = context.getResource("classpath:resources/log4j.properties"); LOGGER.info("classpath: " + resource.getClass().getSimpleName()); LOGGER.info("****************************************************"); >>
ResourceLoaderAware
Интерфейс ResourceLoaderAware обеспечивает объект ссылкой на ResourceLoader .
public interface ResourceLoaderAware
Если класс реализует интерфейс ResourceLoaderAware и развернут в контексте приложения, например, как бин, то при его сборке контекст приложения будет вызывать метод setResourceLoader() и передавать соответствующий ResourceLoader , в зависимости от типа контекста.
Получение ресурса по его пути
Если ваш контекст ClassPathXmlApplicationContext , то вы можете получить ресурс по его пути с указанием префикса classpath: или без него с учетом его местоположения в classpath. Если же вам необходимо получить ресурс по его полному пути, то вам необходимо указать префикс file: , либо ваш контекст должен быть типа FileSystemXmlApplicationContext . В качестве демонстрации, можно запустить метод src/main/java/lessons/starter/ResourceStarter#resourcePath() .
public class ResourceStarter < public static final Logger LOGGER = LogManager.getLogger(ResourceStarter.class); public static void main(String[] args) throws IOException < //. starter.resourcePath(); >public void resourcePath() throws IOException < LOGGER.info("*****************resourcePath()*********************"); LOGGER.info("context = new ClassPathXmlApplicationContext()"); ApplicationContext context = new ClassPathXmlApplicationContext(); Resource resource = context.getResource("log4j.properties"); LOGGER.info("log4j.properties exist: " + resource.getFile().exists()); // resource = context.getResource("src/main/resources/log4j.properties"); // LOGGER.info("log4j.properties exist: " + resource.getFile().exists()); //IOException resource = context.getResource("file:src/main/resources/log4j.properties"); LOGGER.info("file:src/main/resources/log4j.properties exist: " + resource.getFile().exists()); resource = context.getResource("log/log.txt"); LOGGER.info("log/log.txt exist: " + resource.getFile().exists()); resource = context.getResource("classpath:log/log.txt"); LOGGER.info("classpath:log/log.txt exist: " + resource.getFile().exists()); resource = context.getResource("file:log.txt"); LOGGER.info("file:log.txt exist: " + resource.getFile().exists()); resource = context.getResource("file:log/log.txt"); LOGGER.info("file:log/log.txt exist: " + resource.getFile().exists()); resource = context.getResource("file:src/main/resources/log/log.txt"); LOGGER.info("file:src/main/resources/log/log.txt exist: " + resource.getFile().exists()); LOGGER.info("context = new FileSystemXmlApplicationContext()"); context = new FileSystemXmlApplicationContext(); resource = context.getResource("log4j.properties"); LOGGER.info("log4j.properties exist: " + resource.getFile().exists()); resource = context.getResource("src/main/resources/log4j.properties"); LOGGER.info("src/main/resources/log4j.properties exist: " + resource.getFile().exists()); resource = context.getResource("log/log.txt"); LOGGER.info("log/log.txt exist: " + resource.getFile().exists()); resource = context.getResource("classpath:log/log.txt"); LOGGER.info("classpath:log/log.txt exist: " + resource.getFile().exists()); resource = context.getResource("file:log.txt"); LOGGER.info("file:log.txt exist: " + resource.getFile().exists()); resource = context.getResource("file:log/log.txt"); LOGGER.info("file:log/log.txt exist: " + resource.getFile().exists()); LOGGER.info("****************************************************"); >>
Итог
Несмотря на небольшой объем урока, вы познакомились с основами доступа к ресурсам встроенными в Spring средствами. В соответствии с тем, что уроки не предусматривают работу с XML-конфигурациями, а только c Java-конфигурациями, не были рассмотрены варианты указания различных шаблонов в конструктор XML-конфигурациии, но вам ничто не мешает при необходимости ознакомиться с соответствующими разделами документации.