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, H2, Linux, Hibernate, Collections, Stream API, многопоточность, чат-боты, нейросети, файлы, devops, Docker, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.