鍍金池/ 問(wèn)答/Java  Linux/ springboot 多模塊情況下多配置文件問(wèn)題

springboot 多模塊情況下多配置文件問(wèn)題

一個(gè)springboot的項(xiàng)目,使用mavan管理,希望做成模塊化劃分
例如分為service、admin-web、front-web、interface,每個(gè)模塊為一個(gè)獨(dú)立的maven項(xiàng)目
service為最底層公共服務(wù),提供業(yè)務(wù)邏輯處理,數(shù)據(jù)庫(kù)存儲(chǔ)等
其他三個(gè)為控制層,提供頁(yè)面展示、接口等

現(xiàn)在問(wèn)題:每一個(gè)模塊都有自己的配置文件application.yml,整合的時(shí)候怎么將兩個(gè)文件合并,例如,啟動(dòng)admin-web時(shí),加載service中的application.yml

大致項(xiàng)目結(jié)構(gòu)如下:
圖片描述
圖片描述

例如數(shù)據(jù)庫(kù)配置文件放在service的yml中,頁(yè)面thymeleaf相關(guān)配置放在web的yml中,web依賴于service,目前在web的yml中使用spring.profiles.include 可以將service中,對(duì)應(yīng)yml文件引入項(xiàng)目,并且可以實(shí)現(xiàn)各模塊配置文件相互獨(dú)立,但有點(diǎn)問(wèn)題:

  1. service配置文件格式必須為application-xxx.yml
  2. web的yml中必須顯示的配置include值

問(wèn)題:是否能在service中提供一個(gè)@Configuration,能將service中yml的屬性值注入到spring容器中,而不再需要在web的yml中顯示引入service的yml文件,這樣的話只需要在web的pom中依賴service就可以了,配置文件不需要做處理


項(xiàng)目代碼:
https://gitee.com/soft_xiang/...

數(shù)據(jù)庫(kù)為公網(wǎng)測(cè)試庫(kù),隨時(shí)刪數(shù)據(jù),不要亂來(lái)

====2018.06.19更新=============================================
分模塊配置文件加載問(wèn)題已初步解決,參見我的回答,推薦第二種方法

第二種方法引起的多環(huán)境配置文件加載問(wèn)題暫未解決,走過(guò)路過(guò)的都幫忙看一下
====2018.06.19更新 end=============================================

回答
編輯回答
我不懂

第一種方法

試過(guò)在module1-service中添加自定義datasource(只支持properties,Yml可能能實(shí)現(xiàn),但還不太會(huì)寫),可以實(shí)現(xiàn)(此種方式不清楚是否會(huì)影響原來(lái)spring datasource機(jī)制,對(duì)spring原理不熟)
代碼如下:

@Component
@ConfigurationProperties(prefix = "spring.datasource")
@PropertySource("classpath:service-jdbc.properties")
public class MyDataSourceProperties {
    private String url;
    ...
}
@EnableConfigurationProperties(MyDataSourceProperties.class)
public class MyDataSourceConfig {
    @Autowired
    private MyDataSourceProperties myDataSourceProperties;
    @Bean
    @Primary
    public DataSource dataSource() {
        return DataSourceBuilder.create(myDataSourceProperties.getClassLoader()).type(myDataSourceProperties.getType()).driverClassName(myDataSourceProperties.determineDriverClassName()).url(myDataSourceProperties.determineUrl()).username(myDataSourceProperties.determineUsername()).password(myDataSourceProperties.determinePassword()).build();
    }
}

完整代碼:https://gitee.com/soft_xiang/...

第二種方法

在module1-service中自定義properties bean(此種方法較好,推薦),代碼如下

@Configuration
public class ServiceConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer properties() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
        yaml.setResources(new ClassPathResource("application-module1-service.yml"));
        configurer.setProperties(yaml.getObject());
        return configurer;
    }
}

由第二種用法引起的新的問(wèn)題:

項(xiàng)目中如果存在多環(huán)境配置文件,如application-module1-service-dev.yml/application-module1-service-test.yml/application-module1-service/-release.yml時(shí),怎樣根據(jù)module1-web中配置的spring.profiles.active加載對(duì)應(yīng)的配置文件?
思路為在加載文件時(shí)使用SpringContextUtil獲取配置文件中的active,在properties()中根據(jù)active加載文件
代碼如下:

SpringContextUtil.java

@Order(Integer.MIN_VALUE)
@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext context = null;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.context = applicationContext;
    }
    /// 獲取當(dāng)前環(huán)境
    public static String getActiveProfile() {
        return context.getEnvironment().getActiveProfiles()[0];
    }
    /// 獲取當(dāng)前環(huán)境
    public static String[] getActiveProfiles() {
        return context.getEnvironment().getActiveProfiles();
    }
}

ServiceConfig

    @Bean
    public static PropertySourcesPlaceholderConfigurer properties() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        String path = "application-module1-service.yml";
        try {
            String profile = SpringContextUtil.getActiveProfile();
            if (StringUtils.isNotBlank(profile)) {
                path = "application-module1-service-" + profile + ".yml";
            }
        }catch (NullPointerException e){
            e.printStackTrace();
            System.out.println("SpringContextUtil...未加載...");
        }
        YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
        yaml.setResources(new ClassPathResource(path));//File引入
        configurer.setProperties(yaml.getObject());
        return configurer;
    }

完整代碼:https://gitee.com/soft_xiang/...

然而這里會(huì)有循環(huán)依賴問(wèn)題
運(yùn)行代碼會(huì)有

SpringContextUtil...未加載...

沒有實(shí)現(xiàn)根據(jù)active加載對(duì)應(yīng)配置文件

2018年1月24日 16:17
編輯回答
葬憶

用application.yml配置無(wú)非也是生產(chǎn)bean, 比如你示例代碼中application-module1-service.yml:

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://140.143.26.196:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true
    username: test
  

可以在編碼中這樣去實(shí)現(xiàn):

@Bean
@Primary
public DataSource dataSource() {
    return DataSourceBuilder
        .create()
        .username("")
        .password("")
        .url("")
        .driverClassName("")
        .build();
}
2018年8月7日 14:07