Вступление
В этой статье мы погрузимся в настройку свойств загрузки Spring .
Spring позволяет разработчикам настраивать огромное количество свойств для своих проектов. Spring Boot, помимо того, что позволяет разработчикам начать работу над проектом с нуля, намного проще и удобнее, чем Spring, также значительно упрощает настройку свойств для ваших приложений.
Есть несколько способов настроить проект Spring:
- На основе Java
- На основе XML
- На основе свойств
Конфигурация свойств на основе Java и XML была классическим способом
настройки приложений Spring до того, как Spring Boot представил нам файл
application.properties
Это дополнение позволяет нам настраивать приложение извне и легко получать доступ к свойствам, определенным в файле.
По умолчанию application.properties
можно использовать для хранения
пар свойств, хотя вы также можете определить любое количество
дополнительных файлов свойств.
Чтобы зарегистрировать файл свойств, вы можете аннотировать
@Configuration
с помощью дополнительной аннотации @PropertySource
@Configuration
@PropertySource("classpath:custom.properties")
public class ConfigClass {
// Configuration
}
Используя этот метод, вы можете зарегистрировать любое количество
дополнительных файлов .properties
@Configuration
@PropertySource("classpath:custom.properties")
@PropertySource("classpath:another.properties")
public class ConfigClass {
// Configuration
}
Внедрение свойств загрузки Spring
Настройка приложения
Самый простой способ начать работу со скелетным проектом - использовать
Spring Initializr . Выберите предпочитаемую
версию Spring Boot, добавьте Web
зависимость и сгенерируйте ее как
проект Maven:
{.ezlazyload}
Если вы откроете проект, вы заметите, что файл application.properties
хранится по пути src/main/resources
.
Это файл по умолчанию, который Spring использует для загрузки свойств. Здесь мы можем записать наши пользовательские или специфичные для Spring свойства в виде пар ключ-значение:
message.default.welcome=Welcome...
message.default.goodbye=Goodbye...
Вместо properties
мы также можем использовать .yml
и определить те
же свойства, что и:
message:
default:
welcome: Welcome...
goodbye: Goodbye...
Это работает из-за jar-файла SnakeYaml, присутствующего в пути к классам. Файлы YAML более краткие и поддерживают карты, списки и т. Д.
Какой тип использовать - решать вам и вашей команде. В этом руководстве
мы будем использовать .properties
Внедрение свойств с использованием @Value
Давайте посмотрим, как мы можем использовать эти свойства в простом REST API:
@RestController
public class GreetController {
@Value("${message.default.welcome}")
private String welcomeMessage;
@Value("${message.default.goodbye}")
private String goodBye;
@RequestMapping("/welcome")
public String welcome() {
return welcomeMessage;
}
@RequestMapping("/bye")
public String bye() {
return goodBye;
}
}
Это довольно просто. Используя @Value
, мы можем
application.properties
в поля класса в управляемом Spring
bean-компоненте GreetController
.
Затем у нас есть пара конечных точек REST, которые просто возвращают эти значения:
{.ezlazyload}
Использование @Value
позволяет вам установить значение по умолчанию,
если запрошенное по какой-либо причине недоступно:
@Value("${message.default.welcome:SomeDefaultValue}")
private String welcomeMessage;
Если message.default.welcome
отсутствует, будет установлено значение
SomeDefaultValue
.
Если вы хотите узнать больше об аннотации
@Value
, у
нас есть подробная статья об этом!
Внедрение свойств с помощью @ConfigurationProperties
Если у наших свойств есть какой-то общий контекст, такой как один и тот
же префикс, мы можем использовать @ConfigurationProperties
которая
сопоставит эти свойства с объектами Java:
@Configuration
@ConfigurationProperties(prefix = "message.default")
public class MessageProperties {
private String welcome;
private String goodbye;
// Getters and Setters
}
@Configuration
скажет Spring создать bean-компонент этого класса.@ConfigurationProperties
инициализирует поля соответствующими именами свойств.
Теперь мы можем использовать этот bean-компонент в других bean-компонентах, управляемых Spring:
@Autowired
MessageProperties messageProperties;
Переопределение свойств
Естественно, что по мере расширения и изменения среды нашего приложения (разработка, контроль качества, производство и т. Д.) Некоторые из наших свойств также изменятся. Они могут мешать друг другу, если мы не разделяем их каким-либо образом.
Мы достигаем этого, поддерживая разные файлы или получая значения свойств через переменные среды.
Использование профилей Spring
Самый распространенный способ записать «изменяющиеся» свойства - сохранить их в разных файлах. Эти файлы зависят от среды, и наше приложение может загружать их на основе переменных среды.
Spring Boot предоставляет очень элегантный способ справиться с этим.
Все, что нам нужно сделать, это следовать соглашению об именах -
application-<environment>.properties
для наших файлов свойств:
- application-dev.properties
- application-qa.properties
- application-production.properties и т. д.
Чтобы сообщить Spring, какие файлы использовать, мы должны установить
переменную среды - spring.profiles.active
.
При этом, если значение spring.profiles.active
равно dev
, например,
загрузка Spring загрузит application-dev.properties
и тому подобное.
Примечание . application.properties
загружается всегда, независимо
от значения spring.profiles.active
Если один и тот же ключ-значение
присутствует как в application.properties
и в
application-<environment>.properties
, последнее переопределит первое.
Обычно мы записываем все общие свойства каждой среды в
application.properties
и переопределяем специфичные для среды свойства
с помощью зависящего от профиля application-<environment>.properties
.
Давайте посмотрим на это, создав application-dev.properties
:
message.default.welcome = Welcome to DEV environment...
Есть несколько способов настроить переменную spring.profiles.active
Если мы запускаем приложение через Eclipse, мы можем установить это в аргументах виртуальной машины:
{.ezlazyload}
Мы можем установить его в переменных окружения ОС, как в Windows:
{.ezlazyload}
Давайте запустим наше приложение и в журналах вы увидите загружаемый
профиль dev
{.ezlazyload}
Давайте проверим обе наши предыдущие конечные точки REST:
{.ezlazyload}
Как мы видим, значение message.default.welcome
из файла
application-dev.properties
а свойство message.default.goodbye
application.properties
.
У нас может быть несколько значений в spring.profiles.active
например
dev,qa
:
{.ezlazyload}
Любой повторяющийся ключ будет переопределен последним профилем, в
приведенном выше случае qa
.
Мы также можем передать spring.profiles.active
в качестве аргумента
командной строки, например:
java -jar -Dspring.profiles.active=dev greeting-service-0.0.1-SNAPSHOT.jar
Создание application.properties из местоположения сборки
Мы также можем переопределить внутренние свойства, создав
application.properties
на том же уровне, на котором выполняется .jar
. Контекст Spring переопределит свойства, используя этот только что
созданный файл.
Это отличный способ распространения вашего приложения среди других, которые могут переопределить определенные свойства в зависимости от своей среды, например, конфигурации базы данных.
Есть и другие способы экстернализации ваших свойств, таких как переменные среды ОС, аргументы командной строки и т. Д. Порядок, в котором Spring считает это, можно найти здесь .
Внешний перенос свойств с помощью сервера облачной конфигурации
Многие из создаваемых в настоящее время приложений полагаются на микросервисную архитектуру. Эти приложения не только развертываются отдельно, но и могут иметь несколько экземпляров самих себя (в зависимости от нагрузки), а общее количество может легко превысить 100.
Управление недвижимостью в этом архитектурном стиле обычными методами требует слишком больших усилий. Кроме того, чтобы изменить свойство, мы должны заново собрать приложение и развернуть его или, в лучшем случае, перезапустить приложение. Это требует простоя, который сводит на нет всю цель микросервисов.
Еще одна проблема с традиционным подходом, особенно если свойства были вынесены во внешний вид через переменные файла или среды, заключается в отсутствии возможности отслеживания. Всегда берутся самые свежие, и мы не знаем, какие свойства были раньше или кто их изменил.
Spring Cloud Config предоставляет централизованный, внешний, безопасный и простой способ хранения и обслуживания конфигураций приложений для различных сред:
{.ezlazyload}
Короче говоря, у нас есть сервер конфигурации, работающий как отдельное приложение, которое подключается к репозиторию Git.
Когда мы запускаем новое приложение (клиент конфигурации), оно получает все необходимые свойства с сервера конфигурации. Когда мы настраивали сервер, не имеет значения, существовало приложение или нет.
Создание сервера конфигурации
Как всегда, мы начинаем с использования Spring Initializr .
Выберите предпочитаемую версию Spring Boot, добавьте зависимость Config Server и сгенерируйте ее как проект Maven:
{.ezlazyload}
@EnableConfigServer
наш основной класс с помощью @EnableConfigServer,
мы отмечаем его как конфигурационный сервер:
@SpringBootApplication
@EnableConfigServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
А теперь нам нужно настроить несколько вещей в файле
application.properties
server.port = 8888
spring.cloud.config.server.git.uri = https://github.com/dhananjay12/spring-cloud-config
spring.cloud.config.server.git.searchPaths = app-properties
Здесь мы определили порт, на котором будет работать сервер конфигурации. Затем мы указали URL-адрес Git, который нужно перехватить для свойств.
Примечание . По умолчанию Spring ищет файлы свойств в корне. Если
нам нужно указать конкретную папку, мы можем указать ее местоположение
через searchPaths
.
Вот как выглядит репозиторий Git:
{.ezlazyload}
Теперь мы можем запустить сервер конфигурации. Если вы хотите проверить
конфигурацию Spring Config Server, следуя соглашению,
http://localhost:8888/<application-name>/<spring-profiles>
покажет нам
всю необходимую информацию.
В нашем случае это будет - http: // localhost: 8888 / welcome-service-cloud / default :
{.ezlazyload}
Создание клиента конфигурации
Давайте создадим ту же службу приветствия, но с парой дополнительных зависимостей:
{.ezlazyload}
Здесь мы создали greeting-service-cloud
сервис приветствия с
зависимостями Web
, Config Client
и Actuator
Он имеет те же сопоставления REST, что и раньше, с добавлением аннотации
@RefreshScope
Эта аннотация позволяет компоненту динамически
обновляться во время выполнения:
@RestController
@RefreshScope
public class GreetController {
@Value("${message.default.welcome}")
private String welcomeMessage;
@Value("${message.default.goodbye}")
private String goodBye;
@RequestMapping("/welcome")
public String welcome() {
return welcomeMessage;
}
@RequestMapping("/bye")
public String bye() {
return goodBye;
}
}
Теперь помимо application.properties
нам нужно создать
bootstrap.properties
, который загружается перед
application.properties
.
Обычно он используется Spring Config Client для получения свойств с Spring Config Server :
spring.application.name = greeting-service-cloud
spring.cloud.config.uri = http://localhost:8888
Здесь мы сначала устанавливаем имя приложения. Сервер Spring Config будет искать это имя файла в репозитории Git и обслуживать его содержимое.
Мы также должны указать, где работает Config Server, указав его в
spring.cloud.config.uri
.
Запустим этот сервис и посмотрим логи:
{.ezlazyload}
Обратите внимание, что он сначала получил свойства от Spring Config Server.
Примечание . Если сервер конфигурации недоступен, приложение не запустится.
Теперь давайте проверим наши конечные точки REST:
{.ezlazyload}
Таким образом, мы реализовали наши свойства во внешнем виде и получили возможность отслеживать их в нашем репозитории Git. Стоит отметить несколько важных моментов:
- Здесь мы также можем использовать
spring-profiles-active
. Если эта переменная установлена в среде Config Client, например.dev
, он будет передан на сервер конфигурации при запросе свойств. Затем сервер конфигурации будет искатьgreeting-service-cloud-dev.properties
-service-cloud-dev.properties в репозитории Git и передавать его клиенту. - Если
application.properties
, он будет обслуживаться всем клиентам в дополнение к другим файлам. - Если клиент конфигурации запрашивает свойства, например, например,
dev
, сервер конфигурации вернетapplication.properties
,application-dev.properties
иgreeting-service-cloud-dev.properties
. Общие свойства будут отменены последним.
Обновление свойств без перезапуска
По умолчанию значения конфигурации из файлов свойств готовы или извлекаются при запуске приложения, а не повторно. Если необходимо внести какие-то изменения, нам все равно придется перезапустить приложение.
Чтобы решить эту проблему, мы добавили в наше приложение зависимость Actuator. Он предоставляет несколько готовых к работе конечных точек, которые могут дать представление о нашем приложении, которое можно использовать в административных целях.
Мы должны включить эти конечные точки вручную, указав
management.endpoints.web.exposure.include = *
в свойствах приложения.
Давайте добавим это в репозиторий Git и перезапустим приложение. Мы можем проверить многие детали нашего приложения, посетив конечные точки, такие как http: // localhost: 8080 / actator / env , http: // localhost: 8080 / actator / mappings и т. Д.
Нас интересует /actuator/refresh
. Мы можем заставить bean-компонент
обновить свою конфигурацию (т.е. снова получить конфигурацию с сервера
конфигурации), аннотируя bean-компонент с помощью @RefreshScope
.
Примечание . Если компонент обновляется, то при следующем обращении к нему (т. Е. При выполнении метода) создается новый экземпляр.
Это может быть вызвано отправкой пустого HTTP- запроса POST в конечную
точку обновления клиента - http://<host:port>/actuator/refresh
.
Давайте изменим значение единицы в репозитории Git на другое:
message.default.welcome = Welcome from cloud config server changed...
message.default.goodbye = Goodbye...
management.endpoints.web.exposure.include = *
Теперь давайте активируем конечную точку обновления:
curl localhost:8080/actuator/refresh -d {} -H "Content-Type: application/json"
Проверьте конечную точку /welcome
{.ezlazyload}
Итак, мы смогли обновить свойство работающего приложения без его перезапуска.
Заключение
В этой статье мы рассмотрели, как настроить свойства в нашем приложении Spring Boot.
Во-первых, мы обсудили простые способы добавления свойств в наше приложение, а затем изменения / переопределения этих свойств в зависимости от различных сред.
Во-вторых, мы рассмотрели, как получить свойства из Spring Config Server и как обновить свойства без перестройки или перезапуска.
Как всегда, код примеров, использованных в этой статье, можно найти на Github .