是否可以从 Maven 多模块项目的父模块中的配置文件夹加载 Spring-Boot 属性?

Posted

技术标签:

【中文标题】是否可以从 Maven 多模块项目的父模块中的配置文件夹加载 Spring-Boot 属性?【英文标题】:Is it possible to load Spring-Boot properties from config folder within parent module of a Maven multi-module project? 【发布时间】:2021-05-02 16:58:53 【问题描述】:

是否可以从多模块项目的父模块内的config 文件夹中加载多个 Spring-Boot .yml 配置文件?

所以,结构看起来像这样:

parent-module/
  pom.xml
  config/
    application-prd.yml
    application-dev.yml
  module1
    pom.xml
    src/main/resources/
      logback-spring.xml
      bootstrap.yml

这可能吗?怎么办?

所以,如果我从多模块项目的根文件夹执行,我会使用这个命令:

mvn -pl module1 spring-boot:run
   OR
mvn spring-boot:run

我希望config 文件夹包含在类路径中?我正在尝试这样做,但没有让它发挥作用。我错过了什么吗?

我们知道这是真的:Child POMs inherit properties, dependencies, and plugin configurations from the parent. 但这不应该意味着parent/config/application.yml 已经在类路径中了吗?

用于证明的示例项目:https://github.com/djangofan/spring-boot-maven-multi-module-example。如果您认为可以解决,请克隆并修改。

【问题讨论】:

如果在package 阶段使用maven-resources-plugin 将文件从parent 复制到module1 会怎样? 【参考方案1】:

无需编写代码。您可以为此使用 Exec Maven 插件。将插件添加到父模块:

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>1.6.0</version>
      <configuration>
        <mainClass>PACKAGE.MODULE_MAIN_CLASS</mainClass>
        <arguments>
          <argument>--spring.profiles.active=dev</argument>
        </arguments>
      </configuration>
    </plugin>
  </plugins>
</build>

然后运行一次mvn install,然后在您想启动应用程序时运行mvn exec

mvn exec:java -pl module1

有关多模块项目中 Maven 目标的更多信息,请查看此答案 https://***.com/a/11091569/512667。

另一种配置方式是这样,需要workingDirectory arg:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <mainClass>com.example.Application</mainClass>
        <workingDirectory>$maven.multiModuleProjectDirectory</workingDirectory>
        <arguments>
            <argument>--spring.profiles.active=dev</argument>
        </arguments>
    </configuration>
</plugin>

在这种情况下,执行:

mvn spring-boot:run -pl module1

【讨论】:

感谢您的建议。我试过了,但没有用。这是我尝试过的分支:github.com/djangofan/spring-boot-maven-multi-module-example/… @djangofan github URL 不可访问 我的错,只需将配置文件参数附加到 mvn 命令: mvn exec:java -pl spring-boot-module -Dspring.profiles.active=dev 是的,这行得通。我想我会给你赏金。谢谢你。此外,spring“默认配置文件”可以放在属性文件中而不是在命令行中,使执行更简单。我宁愿使用 spring-boot-maven-plugin 但很高兴知道这个解决方案有效。 没问题。难道你的橡皮鸭不值得你承诺的赏金吗? ;-)【参考方案2】:

是的,有可能。

当您使用-pl 时,Maven 会将工作目录更改为模块的目录。所以它不再是具有config/ 目录的根。

您可以将您的 Maven 多模块设置重构为可以打包常见的 application.yml 文件并使用它们的方式。我不建议这样做,因为它有很多陷阱。

--spring.config-location 可能更容易使用

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

目前我无法对其进行测试,但如果它不起作用,您可以随时尝试-Dspring.config.locationSPRING_CONFIG_LOCATION 环境变量。

【讨论】:

寻找一个不需要以任何方式覆盖类路径的答案。最简单的命令行。我以前见过,但我不记得他们是怎么做到的。 根据我的回答定义环境变量或指定系统变量不会覆盖类路径。 我的意思是,我相信有一种方法可以做到这一点,而无需在命令行上指定 spring.config.location。我知道,因为我已经看到它起作用了;我只是不知道具体情况。我将致力于制作一个 Github 示例项目,如果我能自己解决,请分享。 问题可能是你在哪里看到的。 Afaik intelij idea 默认情况下会这样做。 发现将workingDirectory arg 传递给spring-boot-maven-plugin 解决了我的问题。 Spring 现在自动扫描我设置工作目录的/config 文件夹。【参考方案3】:

我发现了一个 customized way of doing it,我仍然认为它是一个 hack,如下所示,但我仍在寻找我的问题的实际答案,如果它存在的话。

@Slf4j
@SpringBootApplication
public class Application 

    private static String DEV_PROPS = "application-dev.properties";
    private static String PRD_PROPS = "application-prd.properties";
    private static String DEFAULT_PROPS = "application.properties";

    private static Path CONFIG = Paths.get(System.getProperty("user.dir"))
            .resolve(Paths.get(".."))
            .resolve("config");

    private static final String EXT_CONFIG_DIR = CONFIG.toString() + File.separator;

    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

    @Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() 
        PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer();
        Resource[] resources = new Resource[] 
                        new FileSystemResource(EXT_CONFIG_DIR + PRD_PROPS),
                        new FileSystemResource(EXT_CONFIG_DIR + DEV_PROPS),
                        new ClassPathResource(DEFAULT_PROPS)
                ;
        log.info("Properties: " + Arrays.deepToString(resources));
        properties.setIgnoreResourceNotFound(true);
        properties.setLocations(resources);
        return properties;
    


此方法的问题在于,必须更改配置以支持额外的environment profile names

【讨论】:

以上是关于是否可以从 Maven 多模块项目的父模块中的配置文件夹加载 Spring-Boot 属性?的主要内容,如果未能解决你的问题,请参考以下文章

maven 聚合与继承

Eclipse创建Maven多模块工程

Maven环境下多模块项目构建

基于 Spring MVC 注解的多模块项目配置

如何配置SonarQube以显示多模块maven项目的所有模块?

SpringBoot创建maven多模块项目