Springboot failed to map properties file to variab

2019-09-20 08:48发布

问题:

i want to map values between a yaml file with a Map<String, List<String>> in springboot

country.yml file:

entries:
  map:
     MY:
      - en
      - zh

SampleConfig file:

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("entries")
public class SampleConfig {

    private Map<String, List<String>> map = new HashMap<>();

    @Bean
    public void bean1(){
        System.err.println("map has size: "+map.size());
    }
}

But the map.size() is always 0, not sure what i do wrong.

回答1:

There are two problems

1) By default spring will look for application.yml or application.properties in default locations

To solve the above problem you can use application.yml instead of country.yml

2) You can use @PropertySource to load any external properties file but yml is not supported with this annotation

24.7.4 YAML Shortcomings you cannot use @PropertySource with yml file

YAML files cannot be loaded by using the @PropertySource annotation. So, in the case that you need to load values that way, you need to use a properties file.

How to read yml file using Spring @PropertySource



回答2:

this will work and print out CountryData : {MY=[en, zh]}

but surely read the answer from Deadpool.

the hack is here to override the default configuration name 'application' by 'country'

in the example, I have done it by setting it via a System property, but starting your application via java -jar mycountryapp.jar --spring.config.name=country should work perfectly

@SpringBootApplication
public class Application {

    static {
      System.setProperty("spring.config.name", "country");
    }

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

}

@Service
class CountryService {
  private final CountryData countryData;
    public CountryService(CountryData countryData) {
        this.countryData = countryData;
    }

    @EventListener(ApplicationReadyEvent.class)
    public void showCountryDataOnStartup() {
      System.err.println("CountryData : " + countryData.getMap());
    }

}

@Configuration
@ConfigurationProperties(prefix = "entries")
class CountryData {

    Map<String, List<String>> map;

    public Map<String, List<String>> getMap() {
        return map;
    }

    public void setMap(Map<String, List<String>> map) {
        this.map = map;
    }

}


回答3:

Assuming your application is picking the configuration from country.yml (I would check that as well) - You need getters and setters to get it to work. just add:

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("entries")
public class SampleConfig {

    private Map<String, List<String>> map = new HashMap<>();

    public Map<String, List<String>> getMap(){
        return map;
    }
    public void setMap(Map<String, List<String>> map){
        this.map=map;
    }

}