2015-04-10 2 views
2

У нас есть устаревшая система с 50 -60 модулями maven, все эти режимы использовали плагин ресурсов maven для фильтрации свойств (замените токены на время сборки в файлах свойств). Это очень болезненно, когда речь идет о создании для разных сред, потому что мы должны создавать приложение каждый раз, когда нам нужно развертывать для разных сред.Сборка и развертывание для многих сред

У нас есть новое требование для создания приложения один раз и развертывания для многих сред. Что было бы лучшим решением для этого? Я думал об экстернализации свойств фильтра, но самой большой проблемой является замена токена существующих файлов свойств приложения (см. Приложение.properties) ниже. Я хочу сохранить существующие файлы свойств так, как есть, и выбрать значения из внешнего файла конфигурации.

Любая помощь была бы очень признательна.

например Фильтр.properties, введенный в maven.

generic.sharepoint.host=xxxxx 
generic.deploy.apps.host=xxxxx 
generic.deploy.apps.url=xxxx 
generic.deploy.trusted.host=xxxx 
generic.deploy.trusted.url=xxxx 
generic.deploy.orderentry=xxxxx 

application.properties

generic.sharepoint.host=${generic.sharepoint.host} 
generic.deploy.apps.host=${generic.deploy.apps.host} 
generic.deploy.apps.url=${generic.deploy.apps.url} 
generic.deploy.trusted.host=${generic.deploy.trusted.host} 
generic.deploy.trusted.url=${generic.deploy.trusted.url} 
generic.deploy.orderentry=${generic.deploy.orderentry} 

ответ

2

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

я не мог найти способ, чтобы передать от этой задачи к Maven, поэтому я решил экстернализовать конфигурацию и обнаружил, что эксплуатирует Spring мне удалось добиться того, что только выполнив два шага:

  1. сделать приложение «знать» среды, к которой она была развернута, путем чтения файла, содержащего имя среды (например, DEV, TEST, PRODUCTION)
  2. В соответствии с найденным значением среды задайте системное свойство, а затем загрузите файл конфигурации, помещенный в соответствует папка.

Имея Tomcat, мы задаем структуру папок конфигурации под shared/classes таким образом, как это:

config structure

и положить в application-config folder файл application-config.properties, содержащий Descripton среды:

application-config.env=DEV 

и одинаковые файлы конфигурации под каждой дочерней папкой, правильно настроенной как связанная среда требуется. После этого мы должны были добавить к контексту Spring приложения другой application-config-context.xml с некоторыми бин для того, чтобы взаимодействовать с org.springframework.beans.factory.config.PropertiesFactoryBean:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 

    <bean id="environmentDetector" class="com.mycompany.myapp.spring.util.PropertiesBasedEnvironmentDetector" init-method="init" > 
    <property name="properties" ref="environmentDefinitionProperties" /> 
    <property name="environmentDefinitionPropertyName" value="application-config.env"/> 
    </bean> 

    <bean id="environmentDefinitionProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
    <property name="ignoreResourceNotFound" value="true" /> 
    <property name="locations"> 
     <list> 
     <value>classpath:application-config/application-config.properties</value> 
     </list> 
    </property> 
    </bean> 

    <bean 
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" > 
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> 
    <property name="ignoreResourceNotFound" value="false" /> 
    <property name="ignoreUnresolvablePlaceholders" value="true" /> 
    <property name="properties" ref="applicationExternalProperties" /> 
    </bean> 

    <bean id="applicationExternalProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean" > 
    <property name="location" value="${application-config.prefix}application-config/${application-config.env}/application.properties" /> 
    </bean> 

</beans> 

Я должен был закодировать класс, чтобы переопределить postProcessBeanFactory метод весной по интерфейсу org.springframework.beans.factory.config.BeanFactoryPostProcessor как это:

package com.mycompany.myapp.doc.spring.util; 

import java.util.Properties; 

import javax.annotation.PostConstruct; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 
import org.springframework.core.PriorityOrdered; 

public class PropertiesBasedEnvironmentDetector implements BeanFactoryPostProcessor, PriorityOrdered{ 
    private static final Log log = LogFactory.getLog(PropertiesBasedEnvironmentDetector.class); 

    private Properties properties; 
    private String environmentDefinitionPropertyName ="env"; 
    private String defaultEnvironment="DEV"; 
    private String environmentSystemPropertyName; 
    private int order = PriorityOrdered.HIGHEST_PRECEDENCE; 

    private String prefixSystemPropertyName = "application-config.prefix"; 
    private String prefixDefault = "classpath:"; 
    private String prefix; 

    public void setProperties(Properties properties) { 
     this.properties = properties; 
    } 

    @PostConstruct 
    public void init() 
    { 
     if (environmentSystemPropertyName == null) { 
      environmentSystemPropertyName = environmentDefinitionPropertyName; 
     } 
     String activeEnvironment = properties.getProperty(environmentDefinitionPropertyName, defaultEnvironment); 
     prefix = properties.getProperty(prefixSystemPropertyName); 
     if (prefix == null) { 
      prefix = prefixDefault; 
      properties.put(prefixSystemPropertyName, prefix); 
     } 
     System.setProperty(environmentSystemPropertyName , activeEnvironment); 
     System.setProperty(prefixSystemPropertyName , prefix); 

     log.warn("Initializing Environment: "+activeEnvironment); 

    } 

    public String getEnvironmentDefinitionPropertyName() { 
     return environmentDefinitionPropertyName; 
    } 

    public void setEnvironmentDefinitionPropertyName(
     String environmentDefinitionPropertyName) { 
     this.environmentDefinitionPropertyName = environmentDefinitionPropertyName; 
    } 

    public String getDefaultEnvironment() { 
     return defaultEnvironment; 
    } 

    public void setDefaultEnvironment(String defaultEnvironment) { 
     this.defaultEnvironment = defaultEnvironment; 
    } 

    public String getEnvironmentSystemPropertyName() { 
     return environmentSystemPropertyName; 
    } 

    public void setEnvironmentSystemPropertyName(String environmentSystemPropertyName) 
    { 
     this.environmentSystemPropertyName = environmentSystemPropertyName; 
    } 

    @Override 
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
     throws BeansException 
    { 
     String activeEnvironment = System.getProperty(environmentSystemPropertyName); 
     log.warn("PostProcessing ApplicationContext for Environment: "+activeEnvironment+" from "+prefix); 
    } 

    @Override 
    public int getOrder() { 
     return order; 
    } 

    public void setOrder(int order) { 
     this.order = order; 
    } 

} 

Когда приложение запускается, Spring загружает все контексты и вызывается наш пользовательский класс. В методе init() сначала загружается environmentDefinitionPropertyName через вложенное свойство properties, а затем устанавливается как системное свойство, имеющее в качестве ключа значение environmentDefinitionPropertyName, установленное в определении компонента.

После этого PropertyPlaceholderConfigurer можно загрузить расположение свойства файла, так как он решает:

<property name="location" value="${application-config.prefix}application-config/${application-config.env}/application.properties" /> 

в

<property name="location" value="classpath:application-config/DEV/application.properties" /> 

Этот подход имел следующие основные преимущества:

  • вы можете легко добавьте дополнительные среды, просто добавив другую папку в папку с исходной конфигурацией
  • исходный пакет приложений был одинаковым во всех средах
  • Файл свойств имеет «нормальный» формат key=value, например, файл application.properties.

Надеюсь, что это поможет и может помочь другим.

+0

Это отличное решение для весеннего основания, к сожалению, наше приложение не использует пружину. Свойства загружаются непосредственно из java. –

Смежные вопросы