Чтение переменной среды в SpringBoot
Каков наилучший способ чтения переменных среды в SpringBoot?
В Java я сделал это используя:
String foo = System.getenv("bar");
Можно ли сделать это с помощью @Value
аннотаций?
9 ответов
Цитирование документации:
Spring Boot позволяет вам вывести свою конфигурацию наружу, чтобы вы могли работать с одним и тем же кодом приложения в разных средах. Вы можете использовать файлы свойств, YAML-файлы, переменные окружения и аргументы командной строки для внешней настройки конфигурации. Значения свойств могут быть введены непосредственно в ваши компоненты с помощью
@Value
аннотация, доступ к которой осуществляется через SpringEnvironment
абстракция или привязка к структурированным объектам через@ConfigurationProperties
,
Итак, поскольку загрузка Spring позволяет использовать переменные среды для конфигурации, а загрузка Spring также позволяет использовать @Value
чтобы прочитать свойство из конфигурации, ответ - да.
Это легко проверить, следующее даст тот же результат:
@Component
public class TestRunner implements CommandLineRunner {
@Value("${bar}")
private String bar;
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void run(String... strings) throws Exception {
logger.info("Foo from @Value: {}", bar);
logger.info("Foo from System.getenv(): {}", System.getenv("bar")); // Same output as line above
}
}
Вы можете сделать это с помощью аннотации @Value:
@Value("${bar}")
private String myVariable;
Вы также можете использовать двоеточие, чтобы задать значение по умолчанию, если оно не найдено:
@Value("${bar:default_value}")
private String myVariable;
Вот три "замещающих" синтаксиса, которые работают для доступа к системной переменной среды с именем MY_SECRET
:
@Value("${MY_SECRET:aDefaultValue}")
private String s1;
@Value("#{environment.MY_SECRET}")
private String s2;
@Value("${myApp.mySecretIndirect:aDefaultValue}") // via application property
private String s3;
В третьем случае заполнитель ссылается на свойство приложения, которое было инициализировано из системной среды в файле свойств:
myApp.mySecretIndirect=${MY_SECRET:aDefaultValue}
За @Value
чтобы работать, его нужно использовать внутри живого @Component
(или похожие). Если вы хотите, чтобы это работало во время модульного тестирования, есть дополнительные гоча - см. Мой ответ на вопрос Почему мое поле Spring @Autowired имеет значение null?
В качестве альтернативы вы можете использовать org.springframework.core.env.Environment
интерфейс для доступа к переменным среды:
@Autowired
private Environment env;
...
System.out.println(env.getProperty("bar"));
Да, ты можешь. Однако в большинстве ответов не упоминается, порядок очень важен, пожалуйста, проверьте это https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/html/boot-features-external-config.html
Ваш
OS environment variables
перезапишет значение, полученное из
Application properties packaged inside your jar (application.properties and YAML variants).
, поэтому в основном переменные среды имеют более высокий приоритет.
Вы можете поместить переменную среды в файл application.yml/application.properties, а затем получить значение с помощью аннотации @Value. Но для того, чтобы использовать аннотацию @Value, ваш класс должен быть bean-компонентом и должен быть аннотирован аннотацией @Component. Вы также можете указать значение по умолчанию для переменной.
@Component
@NoArgsConstructor
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class MyClass {
@Value("${something.variable:<default-value>}")
private String myEnvVariable;
}
В редких случаях, если вы хотите получить доступ к параметрам среды веснойmain
методы (которые являются статическими), вы должны разрешить сборку приложения Spring, а затем использовать методApplicationContext
чтобы получить доступenvironment
. Что-то вроде
public static void main(String[] args) {
ApplicationContext applicationContext = new SpringApplicationBuilder(MyApp.class).run(args);
Environment environment = applicationContext.getEnvironment();
System.out.println(environment.getProperty("spring.application.name"));
System.out.println(environment.getProperty("foo.bar"));
}
вы можете использовать его с аннотацией @Value для классов @Components и @service. Иногда это не сработает, если это обычный класс.
Пример:
@Component
public class Testclass{
@Value("${MY_SECRET:aDefaultValue}")
private String test1;
@Value("#{environment.MY_SECRET}")
private String test1;
@Value("${myApp.mySecretIndirect:aDefaultValue}")
private String test1;
//to get the properties list whih are in "," seperated
@Value("${my.list.of.strings}")
private List<String> myList;
}
Во-первых, вы должны определить соответствующую информацию о поле в файле конфигурации свойств, а затем использовать значение @ для получения и использования примера:
@Value("${abc}")
private String abc;