具有List结构的Spring Boot属性Yml / Properties

时间:2018-03-13 05:04:23

标签: java spring spring-boot properties yaml

我已经遍布stackoverflow和网络寻找解决方案。没有我见过的解决方案,因为可能没有任何帖子完全符合我的用例,其中包含文件内的列表以及对象结构。

这是一个样本作为yaml

teddy.list:
    -
      name: Red
      price: Five
    -
      name: Blue
      price: One
    -
      name: Yellow
      price: Two
    -
      name: Green
      price: Three

以下是与属性文件相同的示例

teddy.list[0].name=Red
teddy.list[0].price=Five
teddy.list[1].name=Blue
teddy.list[1].price=One
teddy.list[2].name=Yellow
teddy.list[2].price=Two
teddy.list[3].name=Green
teddy.list[3].price=Three

我希望能够将teddy.yml或teddy.properties文件提供给我的应用程序进行配置。

以下是我的课程:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration
@PropertySource(name = "props", value = "classpath:teddy.yml", ignoreResourceNotFound = false)
@ConfigurationProperties(prefix = "teddy")
public class TeddyBearConfig {

    @Autowired
    Environment env;

    @Value("${teddy.list}")
    private TeddyBear[] teddyBears;

    public TeddyBear[] getTeddyBears() {
        return teddyBears;
    }

    public void setTeddyBears(TeddyBear[] teddyBears) {
        this.teddyBears = teddyBears;
    }

    public static class TeddyBear {
        private String name;
        private String price;

        public TeddyBear() {

        }

        public TeddyBear(String name, String price) {
            this.name = name;
            this.price = price;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPrice() {
            return price;
        }

        public void setPrice(String price) {
            this.price = price;
        }
    }
}

我尝试过这个设置,使用环境尝试访问属性,删除前缀,声明一个bean“PropertySourcesPlaceholderConfigurer”。

使用当前代码,spring抛出IllegalStateException,因为它无法将java.lang.string转换为我的TeddyBear类。

3 个答案:

答案 0 :(得分:3)

这应该有效。

@Configuration
@PropertySource(name = "props", value = "classpath:teddy.properties", ignoreResourceNotFound = false)
@ConfigurationProperties(prefix = "teddy")
public class TeddyBearConfig {

  private List<TeddyBear> list;

  public List<TeddyBear> getList() {
    return list;
  }

  public void setList(List<TeddyBear> list) {
    this.list = list;
  }

  public static class TeddyBear {
    private String name;
    private String price;

    public TeddyBear() {

    }

    public TeddyBear(String name, String price) {
      this.name = name;
      this.price = price;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public String getPrice() {
      return price;
    }

    public void setPrice(String price) {
      this.price = price;
    }
  }
}

更新

以上代码适用于您上面提供的属性文件。
如果您希望使用yml文件,则可以这样做。但有几点 你的yml结构不正确,应该是这样的

teddy:
  list:
    -
      name: Red
      price: Five
    -
      name: Blue
      price: One
    -
      name: Yellow
      price: Two
    -
      name: Green
      price: Three

2。修复yml结构(以及TeddyBearConfig中的文件名)之后,您将看到springboot在启动时没有出现问题,但是如果TeddBearConfig中的列表变量为null。这是springboot通过@PropertySource处理yml文件的方式中的一个错误。

3.如果您将此yml内容移至application.yml并删除配置文件中的@PropertySource行,您会发现一切正常。

答案 1 :(得分:0)

由于您使用的是ConfigurationProperties注释,而不是

@Value("${teddy.list}")
private TeddyBear[] teddyBears;

你可以直接做

private List<TeddyBear> list;

无需@Value注释。

此外,变量名称必须为list,因为这是您提供给yml的内容。

答案 2 :(得分:0)

当心。取决于Spring版本,上面的代码可能不起作用!

这可能!

private List<TeddyBear> list = new ArrayList<>;

public List<TeddyBear> getList() {
  return list;
}

窍门是Spring分解调用getList()并将TeddyBears添加到新的ArrayList中。在空指针上没有要添加的内容。抛弃吸气剂。未使用。

您只需要进一步:

@Autowired
TeddyBearConfig teddyBearConfig;

最后一句话:如果要在SpringBootTest下进行测试,则可能需要更多提示。

提供一个测试应用作为上下文。肯定有一种更优雅的方式,但是我这样做是这样的:

@SpringBootTest(classes = {TestApplication.class,..

@SpringBootApplication
public class TestApplication {
   public static void main(String[] args) throws Throwable {
      SpringApplication.run(TestApplication.class, args);
  }
 }

如果您的app.properties在TestSources路径下,请使用TestPropertySource:

@TestPropertySource(locations="classpath:application.properties")