【Java】springboot 多模块情况下多配置文件问题

一个springboot的项目,使用mavan管理,希望做成模块化划分
例如分为service、admin-web、front-web、interface,每个模块为一个独立的maven项目
service为最底层公共服务,提供业务逻辑处理,数据库存储等
其他三个为控制层,提供页面展示、接口等

现在问题:每一个模块都有自己的配置文件application.yml,整合的时候怎么将两个文件合并,例如,启动admin-web时,加载service中的application.yml

大致项目结构如下:
【Java】springboot 多模块情况下多配置文件问题
【Java】springboot 多模块情况下多配置文件问题

例如数据库配置文件放在service的yml中,页面thymeleaf相关配置放在web的yml中,web依赖于service,目前在web的yml中使用spring.profiles.include 可以将service中,对应yml文件引入项目,并且可以实现各模块配置文件相互独立,但有点问题:

  1. service配置文件格式必须为application-xxx.yml
  2. web的yml中必须显示的配置include值

问题:是否能在service中提供一个@Configuration,能将service中yml的属性值注入到spring容器中,而不再需要在web的yml中显示引入service的yml文件,这样的话只需要在web的pom中依赖service就可以了,配置文件不需要做处理


项目代码:
https://gitee.com/soft_xiang/...

数据库为公网测试库,随时删数据,不要乱来

====2018.06.19更新=============================================
分模块配置文件加载问题已初步解决,参见我的回答,推荐第二种方法

第二种方法引起的多环境配置文件加载问题暂未解决,走过路过的都帮忙看一下
====2018.06.19更新 end=============================================

回答

spring boot官网的EnvironmentPostProcessorExample,可以完美解决你的一切问题。
Spring Boot Reference Guide 2.1.1.RELEASE
76.3 Customize the Environment or ApplicationContext Before
It Starts

用application.yml配置无非也是生产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

可以在编码中这样去实现:

@Bean

@Primary

public DataSource dataSource() {

return DataSourceBuilder

.create()

.username("")

.password("")

.url("")

.driverClassName("")

.build();

}

第一种方法

试过在module1-service中添加自定义datasource(只支持properties,Yml可能能实现,但还不太会写),可以实现(此种方式不清楚是否会影响原来spring datasource机制,对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;

}

}

由第二种用法引起的新的问题:

项目中如果存在多环境配置文件,如application-module1-service-dev.yml/application-module1-service-test.yml/application-module1-service/-release.yml时,怎样根据module1-web中配置的spring.profiles.active加载对应的配置文件?
思路为在加载文件时使用SpringContextUtil获取配置文件中的active,在properties()中根据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;

}

/// 获取当前环境

public static String getActiveProfile() {

return context.getEnvironment().getActiveProfiles()[0];

}

/// 获取当前环境

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/...

然而这里会有循环依赖问题
运行代码会有

SpringContextUtil...未加载...

没有实现根据active加载对应配置文件

以上是 【Java】springboot 多模块情况下多配置文件问题 的全部内容, 来源链接: utcz.com/a/87078.html

回到顶部