Spring Boot具有相同名称和相同属性名称的多个配置文件

时间:2018-01-28 18:16:28

标签: java spring-mvc spring-boot properties configuration

我正在尝试设置一个Spring Boot单片应用程序,它应该像微服务一样,我有一些问题需要管理配置(.properties)。 这是我组织项目(resources文件夹)的方式: resources directory tree

正如您所看到的,有一些常见的属性文件:application.propertiesapplication-dev.propertiesapplication-prod.properties这些属性应该由所有子属性共享,并且最终可以覆盖它们。

每个service都有自己的数据源网址,并且还取决于有效的个人资料:[{1}}为H2devMySQL

以下是我如何管理配置的例子:

常见prod的内容:

application.properties

常见spring.profiles.active=dev spring.config.additional-location=classpath:productservice/, classpath:userservice/,classpath:financeservice/, classpath:securityservice/ #I am not sure this works... spring.datasource.username=root spring.datasource.password=root spring.jpa.database=default spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=none spring.jpa.properties.validation-mode=none 的内容:

application-dev.properties

常见spring.datasource.driver-class-name=org.h2.Driver spring.h2.console.enabled=true spring.h2.console.path=/db spring.h2.console.settings.trace=false spring.h2.console.settings.web-allow-others=false spring.datasource.username=sa # We override data source username and paswword spring.datasource.password= spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect 的内容:

application-prod.properties

现在针对特定服务:

productservice:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver 的内容:

application.properties

spring.liquibase.change-log=classpath:productservice/db/changelog/db.changelog-master.xml spring.liquibase.default-schema=productservicedb spring.liquibase.check-change-log-location=true 的内容:

application-dev.properties

spring.datasource.url=jdbc:h2:mem:productservicedb;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS productservicedb;MV_STORE=FALSE;MVCC=FALSE spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect 的内容:

application-prod.properties

对于 userservice ,我有:

spring.datasource.url=jdbc:mysql://localhost:3306/productservicedb?useSSL=false 的内容:

application.properties

spring.liquibase.change-log=classpath:userservice/db/changelog/db.changelog-master.xml spring.liquibase.default-schema=userservice spring.liquibase.check-change-log-location=true 的内容:

application-dev.properties

spring.datasource.url=jdbc:h2:mem:userservicedb;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS userservicedb;MV_STORE=FALSE;MVCC=FALSE spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect 的内容:

application-prod.properties

等等......用于其他服务。

要配置每个数据源,我按照以下步骤操作:

productservice:

1-从环境中检索属性:

spring.datasource.url=jdbc:mysql://localhost:3306/userservicedb

2-在数据库配置中注入它们:

@Configuration( "productServiceProperties" )
@Getter
@Setter
@PropertySource( value = { "classpath:productservice/application.properties",
  "classpath:productservice/application-${spring.profiles.active}.properties" } )
public class ProductServiceProperties {

   @Autowired//I want `Environment` to contain properties from common properties + files in @PropertySource above
   private Environment environment;

    // ========DATASOURCE PROPERTIES=========
   private String      datasourceDriverClass;
   private String      datasourceUsername;
   private String      dataSourcePassword;
   private String      dataSourceUrl;

   // ========LIQUIBASE PROPERTIES==========
   private String      liquibaseChangeLog;
   private String      liquibaseDefaultSchema;

   @PostConstruct
   public void init() {
      this.datasourceDriverClass = environment.getProperty( "spring.datasource.driver-class-name" );
      datasourceUsername = environment.getProperty( "spring.datasource.username" );
      dataSourcePassword = environment.getProperty( "spring.datasource.password" );
      dataSourceUrl = environment.getProperty( "spring.datasource.url" );

      liquibaseChangeLog = environment.getProperty( "spring.liquibase.change-log" );
      liquibaseDefaultSchema = environment.getProperty( "spring.liquibase.default-schema" );
      log.debug( "Initialisation {} ", datasourceDriverClass );
  }
}

userservice:

1-

@Configuration
@EnableJpaRepositories( basePackages = "com.company.product.repository", entityManagerFactoryRef = "productServiceEntityManager", transactionManagerRef = "productServiceTransactionManager", considerNestedRepositories = true )
@EnableTransactionManagement( proxyTargetClass = false )
public class ProductServiceDBConfig {

    private static final String      packageToScan = "com.company.product.models";

    @Autowired
    private ProductServiceProperties productServiceProperties;

    @Bean( name = "productServiceDataSource" )
    public DataSource productServiceDataSource() {
       DriverManagerDataSource dataSource = new DriverManagerDataSource();
       dataSource.setDriverClassName( productServiceProperties.getDatasourceDriverClass() );
       dataSource.setUrl( productServiceProperties.getDataSourceUrl() );
       dataSource.setUsername( productServiceProperties.getDatasourceUsername() );
       dataSource.setPassword( productServiceProperties.getDataSourcePassword() );
       return dataSource;
    }

   @Bean
public JpaVendorAdapter productServiceVendorAdapter() {
    HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
    hibernateJpaVendorAdapter.setGenerateDdl( false );
    hibernateJpaVendorAdapter.setShowSql( true );
    return hibernateJpaVendorAdapter;
}

@Bean( name = "productServiceEntityManager" )
public LocalContainerEntityManagerFactoryBean productServiceEntityManager() {
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
    emf.setDataSource( productServiceDataSource() );
    emf.setPackagesToScan( packageToScan );
    emf.setJpaVendorAdapter( productServiceVendorAdapter() );
    return emf;
}

@Bean( name = "productServiceTransactionManager" )
public PlatformTransactionManager productServiceTransactionManager() {
    JpaTransactionManager productTransactionManager = new JpaTransactionManager();
    productTransactionManager.setEntityManagerFactory( productServiceEntityManager().getObject() );
    return productTransactionManager;
}

@Bean
public SpringLiquibase productServiceLiquibase() {
    SpringLiquibase liquibase = new SpringLiquibase();
    liquibase.setDataSource( productServiceDataSource() );
    liquibase.setChangeLog( productServiceProperties.getLiquibaseChangeLog() );
    liquibase.setDefaultSchema( productServiceProperties.getLiquibaseDefaultSchema() );
    return liquibase;
  }
}

2-

@Configuration( "userServiceProperties" )
@Getter
@Setter
@PropertySource( value = { "classpath:userservice/application.properties",
    "classpath:userservice/application-${spring.profiles.active}.properties" } ) //I want properties from properties file source above
public class UserServiceProperties {

    @Autowired //I want `Environment` to contain properties from common properties + files in @PropertySource above
    private Environment environment;

    // ========DATASOURCE PROPERTIES=========
    private String      datasourceDriverClass;
    private String      datasourceUsername;
    private String      dataSourcePassword;
    private String      dataSourceUrl;

    // ========LIQUIBASE PROPERTIES==========
    private String      liquibaseChangeLog;
    private String      liquibaseDefaultSchema;

    @PostConstruct
    public void init() {
        datasourceDriverClass = environment.getProperty( "spring.datasource.driver-class-name" );
        datasourceUsername = environment.getProperty( "spring.datasource.username" );
        dataSourcePassword = environment.getProperty( "spring.datasource.password" );
        dataSourceUrl = environment.getProperty( "spring.datasource.url" );

        liquibaseChangeLog = environment.getProperty( "spring.liquibase.change-log" );
        liquibaseDefaultSchema = environment.getProperty( "spring.liquibase.default-schema" );
    }
}

问题是,由于我@Configuration @EnableJpaRepositories( basePackages = "com.company.user.repository", entityManagerFactoryRef = "userServiceEntityManager", transactionManagerRef = "userServiceTransactionManager", considerNestedRepositories = true ) @EnableTransactionManagement( proxyTargetClass = false ) public class UserServiceDBConfig { private static final String packageToScan = "com.company.user.models"; @Autowired private UserServiceProperties userServiceProperties; @Bean( name = "userServiceDataSource" ) public DataSource userServiceDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName( userServiceProperties.getDatasourceDriverClass() ); dataSource.setUrl( userServiceProperties.getDataSourceUrl() ); dataSource.setUsername( userServiceProperties.getDatasourceUsername() ); dataSource.setPassword( userServiceProperties.getDataSourcePassword() ); return dataSource; } @Bean public JpaVendorAdapter userServiceVendorAdapter() { HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); hibernateJpaVendorAdapter.setGenerateDdl( false ); hibernateJpaVendorAdapter.setShowSql( true ); return hibernateJpaVendorAdapter; } @Bean( name = "userServiceEntityManager" ) public LocalContainerEntityManagerFactoryBean userServiceEntityManager() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource( userServiceDataSource() ); emf.setPackagesToScan( packageToScan ); emf.setJpaVendorAdapter( userServiceVendorAdapter() ); return emf; } @Bean( name = "userServiceTransactionManager" ) public PlatformTransactionManager userServiceTransactionManager() { JpaTransactionManager userTransactionManager = new JpaTransactionManager(); userTransactionManager.setEntityManagerFactory( userServiceEntityManager().getObject() ); return userTransactionManager; } @Bean public SpringLiquibase userServiceLiquibase() { SpringLiquibase liquibase = new SpringLiquibase(); liquibase.setDataSource( userServiceDataSource() ); liquibase.setChangeLog( userServiceProperties.getLiquibaseChangeLog() ); liquibase.setDefaultSchema( userServiceProperties.getLiquibaseDefaultSchema() ); return liquibase; } } 获取我的属性并且所有属性具有相同的名称,因此某些属性始终优先于其他属性。例如。属性@Autowired Environment在两个服务中包含相同的值。

我使用spring.datasource.url而不是Environment @Value,因为它会根据活动配置文件获取属性,而这正是我想要的。

我的问题是:

  • 是否可以配置@ConfigurationProperties从注入它的配置类中获取属性?

  • 如果没有,有没有一种简单的方法来实现我想做的事情?

  • 我应该配置多个应用程序上下文(每个服务一个)以将每个Environment变量与其他变量隔离开来吗? (我不确定这会起作用)

非常感谢(对于这篇文章的篇幅感到抱歉)

1 个答案:

答案 0 :(得分:0)

我自己在推特上提出Andy Wilkinson(@ankinson)的建议解决了这个问题。

我们不能拥有许多同名的属性文件。所以我不得不重命名我的子配置文件:

product.properties
product-dev.properties
product-prod.properties

等等......