Spring Boot 应用程序配置文件和 Maven 多模块项目

51
我们正在一个多模块项目中使用Spring Boot。
我们有一个域访问模块,其中包括常见的域对象类、存储库以及用于数据源、JPA、Hibernate等的配置。这些都是使用application.properties进行配置的。我们将所有这些配置放入通用模块中,以避免在更高级别的模块中重复这些通用配置。
当构建域模块时,这一切都正常工作,因此配置在测试单元中被正确加载。
然而,当我们尝试在更高层次的模块中使用域模块时,问题就开始了,它们有自己的application.properties,这意味着Spring会加载它们而不是域模块的application.properties,这意味着数据源未配置,因为只有更高级别的模块的application.properties被加载。
我们希望Spring同时加载域模块和更高级别应用程序属性。但我们无法找到任何简单的方法来做到这一点。
我想这必须是一个普遍的问题,想知道是否有推荐的解决方案?
由于我们使用spring-boot,因此最好使用注释而不是applictionContext.xml来解决此问题。
5个回答

15

也许你应该只在顶层聚合项目中使用application.properties?

你可以在子项目中始终使用@PropertySource,为它们配置一个特定于它们的用例的名称。

或者你可以为每个项目使用不同的名称,并使用spring.config.location(逗号分隔)将它们在顶层项目中粘合在一起。


1
如果我们在顶级聚合器项目中有属性文件,那么我们如何为子项目编写测试?我们是否应该在子项目的测试资源中再次拥有这些属性? - DBS
我所做的是创建了另一个子模块,其中包含所有测试属性,并在所有其他模块中以测试范围导入。这样就不需要将属性复制到所有子模块中。 - TheBakker

7
也许另一种方法是为每个模块定义特定的配置文件,并使用应用程序属性文件仅指定哪些配置文件处于活动状态,使用spring.profiles.include属性。
domain-module
- application.properties
- application-domain.properties

app-module
- application.properties
- application-app.properties

将其添加到app-module的application.properties文件中

spring.profiles.include=domain,app

7
我同意@Dave Syer的观点。将应用程序拆分为多个模块的想法是每个模块都是一个独立的单元,即一个jar文件。理论上,您可以将每个这些jar文件拆分到它们自己的源代码库中,然后在多个项目中使用它们。假设您想要在Web和批处理应用程序中重用这些域类,如果所有应用级别的配置都存储在各个模块中,那么它们的可重用性将受到严重影响。
在我看来,只有聚合模块应包含运行应用程序所需的所有配置,其他所有内容都只是可以根据需要重新混合和重用的依赖项。

3
我需要找到的是一种在子模块中设置默认属性值的良好规范。这样聚合模块只需要关注它们需要更改的子模块属性,而不是所有的子模块属性。如果你思考一下,这就是Spring Boot的工作方式;它为JDBC、JPA、WEB项目提供了常用的默认值,然后你只需要更改你感兴趣的那些值即可。 - user1232555
那么在这种情况下,为什么不使用Spring Boot自动配置呢?如果您真的正在设置属性(数据源URL等),我认为这与Spring Boot所做的不一定相同-它们正在选择适当的依赖项和环境无关的设置,像数据源这样的设置是定义应用程序特定的。 对我来说,每个JAR文件应仅包含代码,应用程序特定的配置应存储在聚合应用程序中。 - Ben M

2

自从 2.4 版本以来,spring-boot 支持 spring.config.import

e.g

application.name=myapp
spring.config.import=developer.properties

# import from other module
spring.config.import=classpath:application-common.properties

或者使用 spring.config.activate.on-profile
spring.config.activate.on-profile=prod
spring.config.import=prod.properties

参考:https://spring.io/blog/2020/08/14/config-file-processing-in-spring-boot-2-4


2
另外一个你可以做的事情(除了像Dave Syer所提到的只在顶层使用application.properties),是将领域模块的属性文件命名为类似于domainConfig.properties的东西。这样,你就避免了与application.properties的名称冲突。 domainConfig.properties将包含所有领域模块需要测试的数据。与其余代码的集成可以很容易地通过使用多个@PropertySource(一个用于domainConfig.properties和一个用于application.properties)或在你的Java配置中配置PropertySourcesPlaceholderConfigurer bean(查看this教程),该bean引用所有所需的属性文件。

这基本上就是我说的,但如果能让任何人更清楚地理解,那就太好了。我不建议使用另一个PropertySourcesPlaceholderConfigurer(它只会重复已经存在的努力),但如果您无法在运行时更改spring.config.*属性,则可能是一种选择。 - Dave Syer
好的,我误解了你的回答,我以为你的意思是完全摒弃域中的属性文件,只使用顶层的属性文件。对此我感到抱歉! - geoand

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接