28 декабря 2023
Тэги: Java, rest, Spring Boot, yaml, файлы.
Значения параметров системы удобно отделять от программного кода, чтобы можно было их менять без перекомпиляции всего приложения. Spring Boot предоставляет нам удобный способ работы с конфигурационными файлами. Ниже мы рассмотрим несколько случаев, начиная с самого простого.
Отдельное свойство можно внедрить в любой компонент Spring при помощи аннотации @Value.
Предположим, у нас есть простейшее Spring Boot приложение, в котором есть rest-контроллер с методами.
Добавим метод, который в ответ возвращает приветственный текст для пользователя, а имя пользователя будем брать из конфига.
Здесь аннотация @Value подставляет значение для поля name из конфигурационного файла application.yml. Сам файл может выглядеть следующим образом (в формате yaml):
Формат yaml является наиболее современным и компактным, однако вы можете использовать и другие форматы (текст, xml).
Чтобы увидеть результат работы метода, запустите приложение и откройте в браузере http://127.0.0.1:8080/value/hello.
Вы можете подставлять не только текстовые, но и числовые значения. Добавим в наш контроллер ещё одно поле с параметром и ещё один GET-метод.
Расширим наш конфигурационный файл:
Обратите внимание, что оба свойства имеют общий префикс «very.important», что наглядно отображает иерархичная структура yaml.
Мы также можем указывать значения параметров по умолчанию. Сделать это можно всё в той же аннотации @Value:
Здесь значение по умолчанию отделено от имени параметра двоеточием. Значение по умолчанию будет использоваться только тогда, когда этого параметра нет в application.yml.
Когда в приложении появляется несколько параметров, связанных между собой, внедрять их через @Value уже становится неудобно. Для группировки параметров лучше создать отдельный компонент. Spring предоставляет удобную возможность группировки для параметров, имеющих общий префикс – это как раз наш случай. Воспользуемся аннотацией @ConfigurationProperties.
Создадим ещё один rest-контроллер, который по функционалу будет аналогичен первому, но при этом будет использовать наш VeryImportantConfig.
Обратите внимание, что для внедрения нашего бина в данный контроллер мы не пишем явно аннотацию @Autowired. Это возможно благодаря тому, что у нас имеется конструктор, принимающий этот бин и при этом конструктор единственный.
До сих пор мы работали с одиночными значениями. А что, если нам нужно подгрузить параметр, который является списком? Например, список рабочих дней недели. В yaml список значений записывается следующим образом:
Каждый элемент списка начинается с тире и записывается в отдельной строке. Весь список в данном случае доступен по имени very.important.days. Добавить его в наш конфигурационный бин не менее проще, чем предыдущие значения:
В rest-контроллер добавим такой метод:
Выполнив get-запрос по адресу http://127.0.0.1:8080/grouped/days мы увидим список рабочих дней недели в формате json.
Со строками и списками разобрались, а что, если мы хотим хранить в конфигурационном файле и другие типы? Предположим, мы хотим хранить список праздничных дней 2019 года. Сначала добавим их в конфиг:
Пропишем этот список в нашем конфигурационном бине:
Затем добавим метод в контроллер:
Если после этого запустим приложение, то при старте увидим ошибку «Failed to bind properties under 'very.important.holidays[0]' to java.time.LocalDate». Эта ошибка связана с тем, что Spring не умеет преобразовывать дату из строки в LocalDate. Для решения этой проблемы мы можем создать собственный конвертер.
Мы реализовали стандартный интерфейс Converter, типизировав его исходным типом (String) и типом, в который мы преобразуем (LocalDate). Реализация единственного метода convert() довольно проста. Конвертер также должен быть снабжён аннотациями @Component и @ConfigurationPropertiesBinding, чтобы он использовался при инициализации нашего конфигурационного бина.
После этого мы можем выполнить запрос GET http://127.0.0.1:8080/grouped/holidays и увидеть список праздничных дат 2019 года.
Конфигурационные файлы в Spring Boot обладают довольно хорошей гибкостью при работе со стандартными типами (числа и строки). А если этой гибкости не хватает, мы всегда можем написать собственный конвертер, который будет преобразовывать значения из строки в любой другой тип данных.
При этом важно отметить, что совершенно не обязательно использовать формат yaml. В любой момент вы можете изменить формат конфигурационных файлов и при этом вам не нужно будет править код вашего приложения.
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.