1. Обзор
В этом уроке мы сосредоточимся на представлении профилей в Spring.
Профили — это основная функция фреймворка , позволяющая нам сопоставлять наши bean-компоненты с разными профилями — например, dev
, test
и prod
.
Затем мы можем активировать разные профили в разных средах, чтобы загружать только те bean-компоненты, которые нам нужны.
2. Используйте @Profile
на бине
Давайте начнем с простого и посмотрим, как мы можем сделать bean-компонент принадлежащим определенному профилю. Мы используем аннотацию @Profile
— мы сопоставляем компонент с этим конкретным профилем ; аннотация просто берет имена одного (или нескольких) профилей.
Рассмотрим базовый сценарий: у нас есть bean-компонент, который должен быть активен только во время разработки, но не должен быть развернут в рабочей среде.
Мы аннотируем этот компонент профилем разработчика
, и он будет присутствовать в контейнере только во время разработки. В продакшене разработчик
просто не будет активен:
@Component
@Profile("dev")
public class DevDatasourceConfig
В качестве краткого примечания: имена профилей также могут иметь префикс оператора НЕ, например, !dev
, чтобы исключить их из профиля.
В примере компонент активируется, только если профиль разработчика
не активен:
@Component
@Profile("!dev")
public class DevDatasourceConfig
3. Объявить профили в XML
Профили также могут быть настроены в формате XML. Тег <beans>
имеет атрибут профиля
, который принимает разделенные запятыми значения применимых профилей:
<beans profile="dev">
<bean id="devDatasourceConfig"
class="org.foreach.profiles.DevDatasourceConfig" />
</beans>
4. Установите профили
Следующим шагом является активация и настройка профилей, чтобы соответствующие компоненты были зарегистрированы в контейнере.
Это можно сделать различными способами, которые мы рассмотрим в следующих разделах.
4.1. Программно через интерфейс WebApplicationInitializer
В веб-приложениях WebApplicationInitializer
можно использовать для программной настройки ServletContext
.
Это также очень удобное место для программной установки наших активных профилей:
@Configuration
public class MyWebApplicationInitializer
implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter(
"spring.profiles.active", "dev");
}
}
4.2. Программно через ConfigurableEnvironment
Мы также можем установить профили непосредственно в среде:
@Autowired
private ConfigurableEnvironment env;
...
env.setActiveProfiles("someProfile");
4.3. Параметр контекста в web.xml
Точно так же мы можем определить активные профили в файле web.xml
веб-приложения, используя параметр контекста:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-config.xml</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
4.4. Системный параметр JVM
Имена профилей также можно передать через системный параметр JVM. Эти профили будут активированы при запуске приложения:
-Dspring.profiles.active=dev
4.5. Переменная среды
В среде Unix профили также можно активировать с помощью переменной среды :
export spring_profiles_active=dev
4.6. Профиль Мейвена
Профили Spring также можно активировать через профили Maven, указав свойство конфигурации spring.profiles.active
.
В каждом профиле Maven мы можем установить свойство spring.profiles.active
:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
</properties>
</profile>
</profiles>
Его значение будет использоваться для замены заполнителя @ spring.profiles.active@
в application.properties
:
spring.profiles.active=@spring.profiles.active@
Теперь нам нужно включить фильтрацию ресурсов в pom.xml
:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
и добавьте параметр -P
, чтобы переключить, какой профиль Maven будет применяться:
mvn clean package -Pprod
Эта команда упакует приложение для профиля prod .
Он также применяет значение prod
spring.profiles.active
для этого приложения, когда оно работает. ``
4.7. @ActiveProfile
в тестах
Тесты позволяют очень легко указать, какие профили активны, используя аннотацию @ActiveProfile
для включения определенных профилей:
@ActiveProfiles("dev")
До сих пор мы рассматривали несколько способов активации профилей. Давайте теперь посмотрим, какой из них имеет приоритет над другим, и что произойдет, если мы используем более одного, от самого высокого до самого низкого приоритета:
- Параметр контекста в
web.xml
Инициализатор веб-приложений
- Системный параметр JVM
- Переменная среды
- Профиль Мейвена
5. Профиль по умолчанию
Любой bean-компонент, для которого не указан профиль, принадлежит профилю по умолчанию
.
Spring также предоставляет способ установить профиль по умолчанию, когда никакой другой профиль не активен — с помощью свойства spring.profiles.default
.
6. Получите активные профили
Активные профили Spring управляют поведением аннотации @Profile
для включения/отключения bean-компонентов. Однако мы также можем захотеть получить доступ к списку активных профилей программно.
У нас есть два способа сделать это, используя Environment
или spring.active.profile
.
6.1. Использование среды
Мы можем получить доступ к активным профилям из объекта Environment , внедрив его:
public class ProfileManager {
@Autowired
private Environment environment;
public void getActiveProfiles() {
for (String profileName : environment.getActiveProfiles()) {
System.out.println("Currently active profile - " + profileName);
}
}
}
6.2. Использование spring.active.profile
В качестве альтернативы мы могли бы получить доступ к профилям, внедрив свойство spring.profiles.active
:
@Value("${spring.profiles.active}")
private String activeProfile;
Здесь наша переменная activeProfile
будет содержать имя активного в данный момент профиля , а если их несколько, то их имена, разделенные запятой.
Однако мы должны подумать, что произойдет, если активного профиля вообще не будет. В приведенном выше коде отсутствие активного профиля предотвратило бы создание контекста приложения. Это приведет к исключению IllegalArgumentException
из-за отсутствия заполнителя для внедрения в переменную.
Чтобы избежать этого, мы можем определить значение по умолчанию :
@Value("${spring.profiles.active:}")
private String activeProfile;
Теперь, если нет активных профилей, наш активный профиль
будет содержать пустую строку.
И если мы хотим получить доступ к их списку, как в предыдущем примере, мы можем сделать это, разделив переменную activeProfile
:
public class ProfileManager {
@Value("${spring.profiles.active:}")
private String activeProfiles;
public String getActiveProfiles() {
for (String profileName : activeProfiles.split(",")) {
System.out.println("Currently active profile - " + profileName);
}
}
}
7. Пример: отдельные конфигурации источников данных с использованием профилей
Теперь, когда основы убраны, давайте взглянем на реальный пример.
Рассмотрим сценарий, в котором нам необходимо поддерживать конфигурацию источника данных как для среды разработки, так и для рабочей среды .
Давайте создадим общий интерфейс DatasourceConfig
, который должен быть реализован обеими реализациями источника данных:
public interface DatasourceConfig {
public void setup();
}
Ниже приведена конфигурация среды разработки:
@Component
@Profile("dev")
public class DevDatasourceConfig implements DatasourceConfig {
@Override
public void setup() {
System.out.println("Setting up datasource for DEV environment. ");
}
}
И конфигурация для производственной среды:
@Component
@Profile("production")
public class ProductionDatasourceConfig implements DatasourceConfig {
@Override
public void setup() {
System.out.println("Setting up datasource for PRODUCTION environment. ");
}
}
Теперь давайте создадим тест и внедрим наш интерфейс DatasourceConfig; в зависимости от активного профиля Spring внедрит bean-компонент DevDatasourceConfig
или ProductionDatasourceConfig
:
public class SpringProfilesWithMavenPropertiesIntegrationTest {
@Autowired
DatasourceConfig datasourceConfig;
public void setupDatasource() {
datasourceConfig.setup();
}
}
Когда профиль разработчика активен, Spring вводит объект
DevDatasourceConfig
, и при вызове метода setup()
выводится следующее:
Setting up datasource for DEV environment.
8. Профили в Spring Boot
Spring Boot поддерживает все конфигурации профилей, описанные до сих пор, с несколькими дополнительными функциями.
8.1. Активация или настройка профиля
Параметр инициализации spring.profiles.active
, представленный в разделе 4, также можно настроить как свойство в Spring Boot для определения текущих активных профилей. Это стандартное свойство, которое Spring Boot подберет автоматически:
spring.profiles.active=dev
Однако, начиная с Spring Boot 2.4, это свойство нельзя использовать в сочетании с spring.config.activate.on-profile
, так как это может вызвать исключение ConfigDataException
( т
. е . InvalidConfigDataPropertyException
или InactiveConfigDataAccessException
).
Для программной установки профилей мы также можем использовать класс SpringApplication
:
SpringApplication.setAdditionalProfiles("dev");
Чтобы установить профили с помощью Maven в Spring Boot, мы можем указать имена профилей в spring-boot-maven-plugin
в pom.xm
l
:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<profile>dev</profile>
</profiles>
</configuration>
</plugin>
...
</plugins>
и выполните цель Maven, специфичную для Spring Boot:
mvn spring-boot:run
8.2. Файлы свойств для конкретных профилей
Однако самая важная функция Spring Boot, связанная с профилями, — это файлы свойств для конкретных профилей. Они должны быть названы в формате application-{profile}.properties
.
Spring Boot автоматически загрузит свойства в файле application.properties
для всех профилей, а свойства в файлах .properties
для конкретных профилей — только для указанного профиля.
Например, мы можем настроить разные источники данных для профилей разработки
и производства
, используя два файла с именами application-dev.properties
и application-production.properties
:
В файле application-production.properties
мы можем настроить источник данных MySql
:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root
Затем мы можем настроить те же свойства для профиля dev в файле
application-dev.properties , чтобы использовать базу данных
H2
в памяти :
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
Таким образом, мы можем легко предоставить различные конфигурации для различных сред.
До Spring Boot 2.4 можно было активировать профиль из документов по конкретному профилю. Но это уже не так; в более поздних версиях инфраструктура снова выдаст InvalidConfigDataPropertyException
или InactiveConfigDataAccessException
в этих обстоятельствах.
8.3. Файлы с несколькими документами
Чтобы еще больше упростить определение свойств для отдельных сред, мы можем даже объединить все свойства в одном файле и использовать разделитель для обозначения профиля.
Начиная с версии 2.4, Spring Boot расширил поддержку многодокументных файлов для файлов свойств в дополнение к ранее поддерживаемому YAML . Итак, теперь мы можем указать свойства разработки
и производства в одном и том же
application.properties
:
my.prop=used-always-in-all-profiles
#---
spring.config.activate.on-profile=dev
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root
#---
spring.config.activate.on-profile=production
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
Этот файл читается Spring Boot сверху вниз. То есть, если какое-то свойство, скажем, my.prop
, еще раз встречается в конце в приведенном выше примере, будет рассматриваться самое конечное значение.
8.4. Группы профилей
Еще одна функция, добавленная в Boot 2.4, — группы профилей. Как следует из названия, это позволяет нам группировать похожие профили вместе .
Давайте рассмотрим вариант использования, в котором у нас будет несколько профилей конфигурации для производственной среды. Скажем, proddb
для базы данных и prodquartz
для планировщика в производственной
среде.
Чтобы включить эти профили сразу через наш файл application.properties
, мы можем указать:
spring.profiles.group.production=proddb,prodquartz
Следовательно, активация производственного
профиля также активирует proddb
и prodquartz
.
9. Заключение
В этой статье мы обсудили, как определить профиль для компонента и как затем включить нужные профили в нашем приложении.
Наконец, мы подтвердили наше понимание профилей на простом, но реальном примере.
Реализацию этого туториала можно найти в проекте GitHub .