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

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

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

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

ConfigurableEnvironment.setActiveProfiles()

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

ОБНОВЛЕНИЕ: я только нашел в документах, которые я мог бы реализовать, чтобы установить активный профиль?

4 ответа

Решение

Ответ от 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's 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 весны следующим образом 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>

В 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,

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

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>

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

  1. В tomcat / tomee server.xml добавьте это: <Environment name="coacorrect/spring-profile" type="java.lang.String" value="/opt/WebSphere/props"/>
  2. Далее, в tomcat / tomee добавьте в WAR-файл META-INF/context.xml. <ResourceLink global="coacorrect/spring-profile" name="coacorrect/spring-profile" type="java.lang.String"/>
  3. В любой контейнер добавьте соответствующий в 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's 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);
        }
    }
    

    }

Другие вопросы по тегам