Подтвердить что ты не робот

Как загрузить файл свойств на основе серверной среды с помощью spring, чтобы значения могли быть введены?

К моему удивлению, мне было трудно найти ответ на этот вопрос. Я видел много примеров, где вы можете использовать @PropertySource для загрузки определенного файла свойств для класса. Я также видел примеры, в которых вы можете легко добавить разные файлы свойств в spring загрузочных проектах. Но я хочу сделать это для проекта spring, который НЕ является spring загружать и загружать файл свойств, чтобы значения этого файла могли быть введены в классы, аннотированные @Component, которые зависят от сервера Окружающая среда. Так, например, если я на сервере разработки, я хочу, чтобы файл определенных свойств загружался и в процессе создания другого файла свойств. Причина, по которой я делаю это, заключается в том, что мои уровни данных и обслуживания являются их собственными модулями. Эти модули содержат свои собственные модульные тесты и могут быть импортированы как их собственные модули в другие проекты загрузки spring. Мне нужны файлы свойств для загрузки этих модулей, которые используют spring, но не spring boot. Я пробовал следующее, но это не работает.

@Configuration
@Profile("test")
@EnableJpaRepositories("com.hi.repository")
@EnableTransactionManagement
@EnableScheduling
public class InfrastructureConfig  {
...
    @Bean
    public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        Map<String, String> env = System.getenv();
        String propertiesFile=null;

        String e = env.get("SERVER_ENV");

        if (e.equals("dev")) {
            propertiesFile = "environment/development.properties";
        } else if (e.equals("prod")) {
            propertiesFile = "environment/production.properties";
        }

        configurer.setLocation(new ClassPathResource(propertiesFile));


        return configurer;

    }

Тогда у меня есть тест, который выглядит как

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/spring/DealServiceTest-context.xml"})
@ActiveProfiles("test")
public class LogTest {

    private static final Logger log = LogManager.getLogger(LogTest.class);

    @Autowired
    PathsService pathsService;

    @Autowired
    Environment environment;


    @Test
    public void testBeans(){
        System.out.println("********** WASSUP from LogTest");
        System.out.println(environment.getProperty("imageBucket"));

    }

Несмотря на то, что в тесте выводится значение null, которое указывает мне, что файл свойств не был загружен и подготовлен для его значений, которые нужно ввести. Как я могу достичь этого?

4b9b3361

Ответ 1

Вам не нужно устанавливать свойства самостоятельно, но вы можете сделать это с помощью конфигурации spring. Проверьте документацию: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-properties

Если вы используете spring boot - все, что вам нужно сделать, это создать несколько файлов свойств для вашей среды. И только для свойств, которые вам нужно переопределить.

Итак, ваш основной файл свойств будет

src/main/resources/application.properties

Продукция

src/main/resources/application-prod.properties

Разработка

src/main/resources/application-dev.properties

Тестирование

src/main/resources/application-test.properties

И тогда просто используйте имя профиля в качестве переменной среды

java -jar -Dspring.profiles.active=prod demo-0.0.1-SNAPSHOT.jar

Ответ 2

Собственно, вы можете просто использовать заполнитель в аннотации @PropertySource. См. документация:

Любые заполнители ${...}, присутствующие в местоположении ресурса @PropertySource, будут разрешены в отношении набора источников свойств, уже зарегистрированных в среде.

Предполагая, что местозаполнитель присутствует в одном из уже зарегистрированных источников свойств, например. системных свойств или переменных среды, местозаполнитель будет разрешен к соответствующему значению.

Я сделал простой пример: он получает значение property.environment ', который должен использоваться как файл свойств .properties. У меня есть два файла ресурсов в моем пути к классам - application-test.properties и application-dev.properties, каждый из которых содержит значение test.property '(' test-env 'и' dev-env ' соответственно).

Конфигурация свойства:

@Configuration
@PropertySource("classpath:/config/application-${property.environment}.properties")
public class PropertyConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
       return propertySourcesPlaceholderConfigurer;
    }        
}

Компонент с @Value

@Component
public class TestService {

    @Value("${test.property}")
    String testProperty;

    @PostConstruct
    void init() {
        System.out.println("---------------------------------------------------------");
        System.out.println("Running in " + testProperty + " environment");
        System.out.println("---------------------------------------------------------");
    }
}

Пример командной строки сборки (он запускает тесты со свойствами тестовой среды)

mvn clean install -DargLine="-Dproperty.environment=test"

Выход

---------------------------------------------------------
Running in test-env environment
---------------------------------------------------------

Выполнить пример командной строки

java -jar -Dproperty.environment=dev PATH_TO_YOUR_JAR.jar

Выход

---------------------------------------------------------
Running in dev-env environment
---------------------------------------------------------

Ответ 3

Не жесткий код на основе другой среды, при загрузке spring вы можете легко поддерживать среду, специфичную для свойств. См. https://spapas.github.io/2016/03/31/spring-boot-settings/

Ответ 4

Я попытался бы воспользоваться профильным механизмом, уже установленным в Spring. Вы сами уже сделали эту работу, единственное, что вам нужно изменить, - это иметь разные конфигурации для профилей "тест" и "производство". Я предпочитаю держать все, что связано с тестом, от производственного кода (позволяя мне разместить класс TestConfig ниже в пути источника теста), поэтому я, вероятно, сделаю что-то вроде этого:

@Configuration
@Profile("!test")
@PropertySource(value = "classpath:/environment/production.properties")
@Import(AppConfig.class)
public class ProductionConfig
{
    // Your production-specific config goes here
}

@Configuration
@Profile("test")
@PropertySource(value = "classpath:/environment/development.properties")
@Import(AppConfig.class)
public class TestConfig
{
    // Your test-specific config goes here
}

@Configuration
public class AppConfig
{
    // Needed for spring to handle ${property:default} syntax 
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigIn() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

Если вы предпочитаете иметь одну конфигурацию для обоих случаев, вы можете позволить AppConfig импортировать TestConfig и ProductionConfig вместо этого, но это приведет к созданию тестового кода для производства...

Удачи вам в вашем проекте!