Загрузить определенные для среды свойства для использования с PropertyPlaceholderConfigurer?

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

Я работаю над JAVA-приложением командной строки с помощью Пакета Spring и Spring. Я использую файл свойств наряду с PropertyPlaceholderConfigurer, но я немного не уверен в лучшем способе обработать файлы свойств для нескольких сред (dev, тест, и т.д.). Мой поиск с помощью Google только поднимает программные способы загрузить свойства (т.е. в самом коде Java), который не работает на то, что я делаю.

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

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

<bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:job.properties.${env}</value>
        </list>
    </property>
</bean>

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

Я должен также упомянуть, что должен сделать замену во времени выполнения, а не в сборке. Процесс, который я вынужден использовать, требует единственной сборки, которая будет способствоваться через среды производству, таким образом, я буду не мочь использовать Знатока крыла замены или Муравья.

32
задан Mr. Polywhirl 18 April 2016 в 17:33
поделиться

4 ответа

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

Свойство Locations PropertyPlaceHolderConfigurer может занимать различные типы ресурсов. Может быть также файловая система resouce или url? Таким образом, вы можете установить расположение конфигурационного файла в файл на локальном сервере, а затем всякий раз, когда он будет запущен, он будет работать в режиме, указанном конфигурационным файлом на этом сервере. Если у вас есть определенные серверы для определенных режимов работы, это будет работать нормально.

Чтение между строк, хотя кажется, что вы хотите запустить одно и то же приложение в разных режимах на одном и том же сервере. В этом случае я бы предложил передать расположение конфигурационного файла через параметр командной строки. Было бы немного сложно передать это значение в PropertyPlaceHolderConfigurer, но это не будет невозможно.

3
ответ дан 27 November 2019 в 21:09
поделиться

Для подстановки времени сборки я использую свойства сборки Maven для подстановки переменных. Вы можете определить, какие свойства загружать в файл Maven settings.xml, и этот файл может быть специфичным для среды. Для производственных свойств с использованием PPC см. Этот блог

1
ответ дан 27 November 2019 в 21:09
поделиться

Раньше я обычно делал это, выполняя замену среды (dev / test / prod) каким-то образом во время пакета / развертывания.

Это может либо скопировать правильный файл конфигурации в нужное место на сервере, либо просто связать правильный файл конфигурации в пакете развертывания. Если вы используете Ant / Maven, этого должно быть довольно просто. Какой инструмент сборки вы используете? Ant / Maven, который должен предоставить вам возможность заменять значение.

Другой альтернативой, использующей PropertyPlaceholderConfigurer, является свойство SYSTEM_PROPERTIES_MODE_OVERRIDE. Вы можете использовать это, чтобы установить местоположение файла свойств, который вы хотите загрузить через системное свойство, см .:

http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/ beans / factory / config / PropertyPlaceholderConfigurer.html # SYSTEM_PROPERTIES_MODE_OVERRIDE

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

3
ответ дан 27 November 2019 в 21:09
поделиться

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

1) Положитесь на наличие файла свойств в домашнем каталоге пользователя.

Настройте PropertyPlaceholderConfigurer для ссылки на файл свойств, внешний по отношению к JAR, следующим образом:

<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreUnresolvablePlaceholders" value="false"/>
    <property name="order" value="1"/>
    <property name="locations">
      <list>
        <!-- User home holds secured information -->
        <value>file:${user.home}/MyApp/application.properties</value>
      </list>
    </property>
  </bean>

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

2) Если ваше приложение находится в контролируемой среде, так что база данных может быть видна, тогда проблема может быть сведена к одному из создания базовых учетных данных с использованием метода 1) выше для подключения к базе данных во время запуска контекста и последующего выполнения подстановки. используя значения, прочитанные через JDBC. Вам понадобится двухэтапный подход к запуску приложения: фаза 1 вызывает родительский контекст с файлом application.properties, заполняющим JdbcTemplate и связанный с ним DataSource;фаза 2 вызывает основной контекст, который ссылается на родительский объект, чтобы можно было использовать JdbcTemplate, как настроено в JdbcPropertyPlaceholderConfigurer.

Примером такого кода может быть следующее:

public class JdbcPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {

  private Logger log = Logger.getLogger(JdbcPropertyPlaceholderConfigurer.class);
  private JdbcTemplate jdbcTemplate;
  private String nameColumn;
  private String valueColumn;
  private String propertiesTable;

  /**
   * Provide a different prefix
   */
  public JdbcPropertyPlaceholderConfigurer() {
    super();
    setPlaceholderPrefix("#{");
  }

  @Override
  protected void loadProperties(final Properties props) throws IOException {
    if (null == props) {
      throw new IOException("No properties passed by Spring framework - cannot proceed");
    }
    String sql = String.format("select %s, %s from %s", nameColumn, valueColumn, propertiesTable);
    log.info("Reading configuration properties from database");
    try {
      jdbcTemplate.query(sql, new RowCallbackHandler() {

        public void processRow(ResultSet rs) throws SQLException {
          String name = rs.getString(nameColumn);
          String value = rs.getString(valueColumn);
          if (null == name || null == value) {
            throw new SQLException("Configuration database contains empty data. Name='" + name + "' Value='" + value + "'");
          }
          props.setProperty(name, value);
        }

      });
    } catch (Exception e) {
      log.fatal("There is an error in either 'application.properties' or the configuration database.");
      throw new IOException(e);
    }
    if (props.size() == 0) {
      log.fatal("The configuration database could not be reached or does not contain any properties in '" + propertiesTable + "'");
    }
  }

  public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }

  public void setNameColumn(String nameColumn) {
    this.nameColumn = nameColumn;
  }

  public void setValueColumn(String valueColumn) {
    this.valueColumn = valueColumn;
  }

  public void setPropertiesTable(String propertiesTable) {
    this.propertiesTable = propertiesTable;
  }

}

Вышеупомянутое будет затем настроено в Spring следующим образом (обратите внимание, что свойство order идет после обычных заполнителей с префиксом $):

  <!-- Enable configuration through the JDBC configuration with fall-through to framework.properties -->
  <bean id="jdbcProperties" class="org.example.JdbcPropertyPlaceholderConfigurer">
    <property name="ignoreUnresolvablePlaceholders" value="false"/>
    <property name="order" value="2"/>
    <property name="nameColumn" value="name"/>
    <property name="valueColumn" value="value"/>
    <property name="propertiesTable" value="my_properties_table"/>
    <property name="jdbcTemplate" ref="configurationJdbcTemplate"/> <!-- Supplied in a parent context -->
  </bean>

Это позволит происходят в конфигурации Spring

<!-- Read from application.properties -->
<property name="username">${username}</property>  
...
<!-- Read in from JDBC as part of second pass after all $'s have been fulfilled -->
<property name="central-thing">#{name.key.in.db}</property> 

3) Конечно, если вы находитесь в контейнере веб-приложения, вы просто используете JNDI. Но это не так.

Надеюсь, это поможет!

11
ответ дан 27 November 2019 в 21:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: