Spring:使用java配置样式加载多个属性文件

时间:2016-08-03 11:02:33

标签: java spring properties spring-boot

给定以下简单的spring启动示例应用程序:

@SpringBootApplication
public class Application {

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

@PropertySource(value="classpath:properties/tables/adres.properties")
@PropertySource(value="classpath:properties/tables/person.properties")
@Component
public class Sample {

    @Value("${table.name}")
    private String tableName;

    @Value("${table.columns}")
    private String[] columns;

    @Value("${table.data.types}")
    private String[] dataTypes;

    @PostConstruct
    public void init() {
        // do something with values from properties...
        for (String column : columns) {
            System.out.println(column);
        }
    }
}

以及以下示例属性:
adres.properties:

table.name=adres
table.columns=personId,streetName,cityName
table.data.types=integer,string,string

person.properties:

table.name=person
table.columns=personId,firstName,lastName
table.data.types=integer,string,string

我想

  1. 使用一个导入添加目录中的所有属性文件,而不必将每个属性添加为@PropertySource
  2. 检索每个属性文件的值并使用它们执行某些操作
  3. 我尝试了以下内容:

    1

    使用通配符*从目录(http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html#resources-classpath-wildcards)获取所有属性,如下所示:

    @PropertySource(value="classpath*:properties/tables/*.properties")
    

    抛出java.io.FileNotFoundException: class path resource [properties/tables/*.properties] cannot be opened because it does not exist,所以看起来它将*解析为文字值而不是通配符。

    按照How to read multiple properties having the same keys in Spring?

    中的建议将PropertySourcesPlaceholderConfigurer添加到Application类
    @Bean
    public static PropertySourcesPlaceholderConfigurer properties() {
        PropertySourcesPlaceholderConfigurer config = new PropertySourcesPlaceholderConfigurer();
        config.setIgnoreUnresolvablePlaceholders(true);
        return config;
    }
    

    似乎无法正常工作,因为java.io.FileNotFoundException在加载PropertySourcesPlaceholderConfigurer之前被抛出。

    2

    重新获取值也很困难,因为每个属性都使用相同的键。这样做是为了保证属性文件的一致性和可维护性。我尝试通过使用更多占位符来解决这个问题:

    table.name=person
    {table.name}.columns=personId,firstName,lastName
    {table.name}.data.types=integer,string,string
    

    和Sample.class

    @Value("${table.name}")
    private String tableName;
    
    @Value("${{table.name}.columns}")
    private String[] columns;
    
    @Value("${{table.name}.data.types}")
    private String[] dataTypes;
    

    占位符有效,但我仍然需要手动添加所有@PropertySource,并且只能从最后加载的@Value中获取@PropertySource

    编辑:占位符实际上不起作用。使用以下语法时: ${table.name}.columns=personId,firstName,lastName@Value("${${table.name}.columns}")发生以下异常:

    Could not resolve placeholder 'person.columns' in string value "${${table.name}.columns}" 
    

    问题

    如何解决有关加载多个属性文件然后以java配置样式方式(但仍使用相同的键名)从每个单独的属性文件中检索值的问题?

    编辑2:部分解决方案/解决方法

    管理以创建关于值冲突的变通方法解决方案:

    @PropertySource(value="classpath:properties/tables/tables.properties")
    @PropertySource(value="classpath:properties/tables/person.properties")
    @PropertySource(value="classpath:properties/tables/address.properties")
    @Component
    public class Sample {
    
        private static final String COLUMNS = ".columns";
        private static final String DATA_TYPES = ".data.types";
    
        @Autowired
        private Environment env;
    
        @Value("${table.names}")
        private String[] tableNames;    
    
        @PostConstruct
        public void init() {
            for (String tableName : tableNames) {
                getTableValues(tableName);
            }       
        }
    
        private void getTableValues(String tableName) {
            String col = env.getProperty(tableName + COLUMNS);
            List<String> columns = Arrays.asList(col.split("\\s*,\\s*"));
            for (String column : columns) {
                System.out.println(String.format("The table %s contains the column %s", tableName, column));
            }
            String types = env.getProperty(tableName + DATA_TYPES);
            List<String> dataTypes = Arrays.asList(types.split("\\s*,\\s*"));
            // do more stuff
        }
    }
    

0 个答案:

没有答案