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

Как установить активный профиль среды spring 3.1 через файл properites, а не через переменную env или системное свойство

Мы используем новую функцию профилей окружения spring 3.1. В настоящее время мы устанавливаем активный профиль, задавая переменную среды spring.profiles.active = xxxxx на сервере, на которую мы развертываем приложение.

Мы считаем, что это неоптимальное решение, так как файл войны, который мы хотим развернуть, должен иметь только дополнительный файл свойств, который устанавливает среду, в которой должен загружаться контекст приложения spring, поэтому развертывание не зависит от некоторого env var set на сервере.

Я попытался выяснить, как это сделать и нашел:

ConfigurableEnvironment.setActiveProfiles()

который я могу использовать для программной настройки профиля, но затем я до сих пор не знаю, где и когда выполнять этот код. Где-то где загружается контекст spring? Могу ли я загрузить параметр, который я хочу передать методу из файла свойств?

UPDATE: я только что нашел в docs, который я мог бы реализовать, чтобы установить активный профиль?

4b9b3361

Ответ 1

Ответ от Thomasz действителен до тех пор, пока имя профиля может быть предоставлено статически в файле web.xml или используется новый тип конфигурации без XML-кода, где можно программно загрузить профиль для установки из файла свойств.

Поскольку мы все еще используем версию XML, которую я исследовал дальше, и нашел следующее красивое решение, в котором вы реализуете свой собственный ApplicationContextInitializer, где вы просто добавляете новый PropertySource с файлом свойств в список источников для поиска настроек конфигурации, специфичных для конкретной среды, в приведенном ниже примере можно установить свойство spring.profiles.active в файле env.properties.

public class P13nApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    private static Logger LOG = LoggerFactory.getLogger(P13nApplicationContextInitializer.class);

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        try {
            environment.getPropertySources().addFirst(new ResourcePropertySource("classpath:env.properties"));
            LOG.info("env.properties loaded");
        } catch (IOException e) {
            // it ok if the file is not there. we will just log that info.
            LOG.info("didn't find env.properties in classpath so not loading it in the AppContextInitialized");
        }
    }

}

Затем вам нужно добавить этот инициализатор в качестве параметра в ContextLoaderListener of spring, как показано ниже, на ваш web.xml:

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>somepackage.P13nApplicationContextInitializer</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Вы также можете применить его к DispatcherServlet:

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextInitializerClasses</param-name>
        <param-value>somepackage.P13nApplicationContextInitializer</param-value>
    </init-param>
</servlet>

Ответ 2

В web.xml

<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>profileName</param-value>
</context-param>

Использование WebApplicationInitializer

Этот подход используется, когда у вас нет файла web.xml в среде Servlet 3.0 и полностью загружается Spring из Java:

class SpringInitializer extends WebApplicationInitializer {

    void onStartup(ServletContext container) {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.getEnvironment().setActiveProfiles("profileName");
        rootContext.register(SpringConfiguration.class);
        container.addListener(new ContextLoaderListener(rootContext));
    }
}

Где SpringConfiguration класс аннотируется с помощью @Configuration.

Ответ 3

По какой-то причине для меня работает только один способ

public class ActiveProfileConfiguration implements ServletContextListener {   
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.setProperty(AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME, "dev");
        System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "dev");
    }

....

 <listener>
     <listener-class>somepackahe.ActiveProfileConfiguration</listener-class>
 </listener>
 <listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

Ответ 4

Вот вариант подхода P13nApplicationContextInitializer. Однако на этот раз мы получаем путь к env свойствам из JNDI. В моем случае я установил глобальную переменную среды JNDI как coacorrect/ spring -profile = file:/tmp/env.properties

  • В tomcat/tomee server.xml добавьте это: <Environment name="coacorrect/spring-profile" type="java.lang.String" value="/opt/WebSphere/props"/>
  • Далее, в tomcat/tomee, добавьте в WAR META-INF/context.xml <ResourceLink global="coacorrect/spring-profile" name="coacorrect/spring-profile" type="java.lang.String"/>
  • В любом контейнере добавьте соответствующее в web.xml

    public class SpringProfileApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>{
    
    public static final Logger log = LoggerFactory.getLogger(SpringProfileApplicationContextInitializer.class);
    private static final String profileJNDIName="coacorrect/spring-profile";
    private static final String failsafeProfile="remote-coac-dbserver";
    
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
    
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
    
        try {
            InitialContext ic = new InitialContext();
            Object r1 = ic.lookup(profileJNDIName);
            if (r1 == null) {
                // try the tomcat variant of JNDI lookups in case we are on tomcat/tomee
                r1 = ic.lookup("java:comp/env/"+profileJNDIName);
            }
            if (r1 == null) {
                log.error("Unable to locate JNDI environment variable {}", profileJNDIName);
                return;
            }
    
            String profilePath=(String)r1;
            log.debug("Found JNDI env variable {} = {}",r1);
            environment.getPropertySources().addFirst(new ResourcePropertySource(profilePath.trim()));
            log.debug("Loaded COAC dbprofile path. Profiles defined {} ", Arrays.asList(environment.getDefaultProfiles()));
    
        } catch (IOException e) {
            // it ok if the file is not there. we will just log that info.
            log.warn("Could not load spring-profile, defaulting to {} spring profile",failsafeProfile);
            environment.setDefaultProfiles(failsafeProfile);
        } catch (NamingException ne) {
            log.error("Could not locate JNDI variable {}, defaulting to {} spring profile.",profileJNDIName,failsafeProfile);
            environment.setDefaultProfiles(failsafeProfile);
        }
    }
    

    }