【发布时间】:2014-03-03 16:25:07
【问题描述】:
什么是在 Scala 中设置项目的好方法,该项目根据环境使用不同的配置。
我需要专门为开发、测试和生产环境设置不同的数据库(类似于Rails中所做的)
【问题讨论】:
标签: scala configuration environment-variables config development-environment
什么是在 Scala 中设置项目的好方法,该项目根据环境使用不同的配置。
我需要专门为开发、测试和生产环境设置不同的数据库(类似于Rails中所做的)
【问题讨论】:
标签: scala configuration environment-variables config development-environment
我使用的另一个策略是使用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会被default加载。
所以这里我们使用Typesafe Config的默认加载机制来实现这一点。
我创建了一个简单的project 来演示这种技术。随意克隆和试验。
【讨论】:
fork in run := true 和 java -Dconfig.resource=stg.conf。文件 stg.conf 在资源下,但我的配置仍然来自 application.conf。还要注意,当我使用:val conf = ConfigFactory.load("stg.conf") 时,我的配置会根据 stg.conf 加载。有什么想法吗?
使用类型安全配置。像这样创建一个 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)
}
然后在src/main/resources文件夹中创建application.conf文件:
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),它将考虑正确的配置部分。默认是开发
【讨论】:
我对 Daniel Cukiers 解决方案不允许默认值和覆盖的方式不满意,因此我对其进行了更改以充分利用它们。
您需要做的唯一配置是在系统上设置一个 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")
【讨论】: