Конкретная конфигурация среды в Scala

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

Мне нужно специально иметь разные базы данных для разработки, test и production (аналогично тому, как это делается в Rails)

Ответы

Ответ 1

Используйте typafe Config. Создайте объект Config следующим образом:

import com.typesafe.config._

object Config {
  val env = if (System.getenv("SCALA_ENV") == null) "development" else System.getenv("SCALA_ENV")

  val conf = ConfigFactory.load()
  def apply() = conf.getConfig(env)
}

Затем создайте файл application.conf в папке src/main/resources:

development {
  your_app {
    databaseUrl = "jdbc:mysql://localhost:3306/dev_db"
    databaseUser = "xxxx"
    databasePassword = "xxxx"
  }
}
test {
  your_app {
    databaseUrl = "jdbc:mysql://localhost:3306/test_db"
    databaseUser = "xxxxx"
    databasePassword = "xxxx"
  }
}

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

Config(). GetString ( "your_app.databaseUrl" )

Если вы создали свою среду (например, export SCALA_ENV=test) при запуске приложения, она рассмотрит правильный раздел конфигурации. По умолчанию используется

Ответ 2

Другая стратегия, которую я использую, состоит в использовании includes. Обычно я храню настройки DEV в файле default application.conf, тогда я создаю новый файл conf для других сред и включаю по умолчанию.

Скажем, мой DEV conf application.conf выглядит следующим образом:

myapp {
    server-address = "localhost"
    server-port = 9000

    some-other-setting = "cool !"
}

Тогда для PROD мог бы быть другой файл с именем prod.conf:

include "application"

# override default (DEV) settings
myapp {
    server-address = ${PROD_SERVER_HOSTNAME}
    server-port = ${PROD_SERVER_PORT}
}

Обратите внимание, что я переопределяю только параметры, которые изменяются в среде PROD (some-other-setting, таким же образом, как в DEV).

Код начальной загрузки конфигурации не проверяет ничего

...
val conf = ConfigFactory.load()
...

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

java -Dconfig.resource=prod.conf ...

В DEV нет необходимости передавать его, так как application.conf будет загружаться по умолчанию.

Итак, для этого мы используем механизм загрузки по умолчанию Configafe Config.

Я создал простой проект, чтобы продемонстрировать эту технику. Не стесняйтесь клонировать и экспериментировать.

Ответ 3

Я был недоволен тем, как решение Дэниела Кукьера не разрешало дефолты и переопределения, поэтому я изменил его, чтобы в полной мере использовать их.

Единственная конфигурация, которую вы должны сделать, это установить переменную ENVIRONMENT в системе (по умолчанию "dev", если ни один не установлен)

(Java-решение, совместимое с Scala):

import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;

public class MyCompanyConfig {
    public final static Config base = ConfigFactory.load().getConfig("mycompany");
    public final static String environment = System.getenv("ENVIRONMENT") == null ? "dev" : System.getenv("ENVIRONMENT");

    /**
     * Returns a subtree of the base configuration with environment settings applied.
     *
     * @param setting The subtree to return config for.
     * @return A config with base in given setting, with environment modifications applied.
     */
    public static Config load(String setting) {

        Config config = base.getConfig(setting);

        if (config.hasPath(environment)) {
            return config.getConfig(environment).withFallback(config);
        }

        return config;
    }
}

Это позволяет использовать один файл reference.conf в следующей библиотеке:

mycompany.module1 {
    setting1 : "adefaultvalue"
    url : "localhost"

    test {
        // will be used where ENVIRONMENT="test"
        url : "test.mycompany.com"
    }

    prod {
        // will be used where ENVIRONMENT="prod"
        setting1 : "changethedefault"
        url : "www.mycompany.com"
    }
}

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

Config conf = MyCompanyConfig.load("module1")