在我工作的大多数Java项目(Maven,Spring)中,我有以下要求:
到目前为止,我已经通过将所有配置属性放入单独的属性文件(每个环境一个)来完成此操作。然后我从类路径中加载这些文件中的Spring。然后我只需在运行时更改类路径以加载所需的属性。
当我使用Eclipse时,这种方法运行良好,因为很容易设置多个运行配置并改变每个运行配置的类路径。完成此操作后,切换环境就是选择相关的运行配置。
不幸的是,这在IntelliJ中要难得多,因为运行时依赖只能添加到模块的配置(as documented in this answer)。如果我尝试在运行配置本身中设置类路径,那么这将覆盖所有模块依赖项,从而阻止应用程序运行(as documented here)。因此,要切换环境,我每次都必须重新编辑模块依赖项。
使用IntelliJ有更简单的方法吗?
如果没有,那是因为我的配置要求或我的解决方案是不寻常的吗?在哪种情况下,有更好的方法吗?
以前的方法
我已经尝试过并拒绝了许多方法:
Maven配置文件 - 每当我想切换环境时,这些都需要重建我的jar。除了烦人和危险之外,这似乎完全不适合运行时配置(但对于构建时配置是理想的)。这似乎是冒着将破坏的构建投入到生产中的一种很好的方法,因为您没有针对实际部署的相同jar进行测试。呸!
Spring配置文件 - 这些看起来更合适,但似乎要求所有配置都与jar一起部署并通过文件名区分,例如dev.properties,prod.properties。然后,您可以通过在运行时传递变量来选择所需的那个。这要好得多,但我不希望我的prod.properties找到进入版本控制的方式,也不希望使用jar本身进行部署。因此,似乎仍然需要修改类路径以包含它们在IntelliJ中我不能轻易做到的
答案 0 :(得分:1)
当我遇到类似问题时,我开始使用帮助程序类加载我的属性。辅助类将查找System属性,该属性包含环境或从中加载属性的绝对/类路径相对路径。
这样,代码总是相同的,我不必更改项目的配置。我只是使用不同的启动配置来设置不同的属性。
这里的主要缺点当然是测试/ dev配置泄漏到prod。使用Maven,简单的解决方案是将它们移动到一个新模块中,并将其范围设置为provided
。这样,模块将在Maven内部可见,但在WAR包装等期间不会包含该模块。
答案 1 :(得分:1)
我做了类似于@AaronDigulla的事情,但我覆盖属性。那就是我首先从类路径中的属性文件中加载所有属性(使用Spring)。然后我搜索特定的变量名称和值(按以下顺序):
此变量名称和值包含属性文件的路径,这些文件将覆盖/覆盖从类路径加载的属性。此外,每个加载的属性都将执行相同类型的解析(即系统属性,环境变量和servlet init参数覆盖属性文件中的属性)。
现在所有开发人员都被推到使用类路径中的默认配置(即为他们的数据库使用相同的用户名/密码)。具有不同设置的那些可以使用以上3种不同的方式来覆盖。
我使用的 You can use the same bootstrapping configuration code将首先加载classpath*:META-INF/spring/*.properties
中的所有属性文件然后它将加载所有属性文件,其中文件/类路径URL在名为{{的property / environment / init参数变量中设置。 1}}(如果设置)。
然后最后在加载属性文件之后,它将通过拉动名为MyConfigParameter
的属性/ environment / init参数(逗号分隔)来设置Spring配置文件。
因此,在生产中,您可以设置环境变量MyConfig.profiles
。
然后在其中一个属性文件中,您可以设置MyConfigParameter=file://etc/myapp/*.properties
,这将设置Spring个人资料MyConfig.profiles=production,postgres
和production
。
用于在构建计算机上发布/构建的Maven配置文件显然可以使用“系统属性”调整环境中的postgres
。但是你必须告诉surefire单元测试这个属性(特别是如果分叉):
MyConfigParameter