web-dev-qa-db-fra.com

Spring Boot Property Yml/Propriétés avec une structure de liste

J'ai regardé partout sur stackoverflow et sur le net pour une solution à cela. Aucune solution, j’ai vu fonctionner car il se peut qu’aucun des articles ne corresponde exactement à mon cas d’utilisation, qui contient une liste à l’intérieur du fichier et une structure d’objet. 

Voici un échantillon en tant que yaml

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

Voici le même exemple qu'un fichier de propriété

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

Je souhaite pouvoir fournir un fichier teddy.yml ou teddy.properties à mon application pour la configuration.

Voici mon cours pour ça:

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;
        }
    }
}

J'ai essayé cette configuration, en utilisant l'environnement pour essayer d'accéder aux propriétés, en supprimant le préfixe, en déclarant un bean de "PropertySourcesPlaceholderConfigurer".

Avec le code actuel, spring renvoie une exception IllegalStateException car il ne peut pas convertir Java.lang.string en classe TeddyBear.

3
GSUgambit

Cela devrait marcher. 

@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;
    }
  }
}

Mettre à jour

Le code ci-dessus fonctionne pour le fichier de propriétés que vous avez donné ci-dessus.
Si vous souhaitez utiliser le fichier yml, vous pouvez le faire. mais il y a quelques points.
1. Votre structure yml n'est pas correcte, ça devrait être comme ça 

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

2. Après avoir corrigé votre structure yml (et le nom du fichier dans votre TeddyBearConfig), vous verrez que springboot ne se plaint pas au démarrage, mais si la liste de variables dans TeddBearConfig sera nulle. C'est un bug dans la façon dont springboot gère les fichiers yml via @PropertySource

3.Si vous déplacez ce contenu yml vers application.yml et supprimez la ligne @PropertySource dans votre fichier de configuration, vous constaterez que tout fonctionne parfaitement.

2
pvpkiran

Puisque vous utilisez l'annotation ConfigurationProperties, au lieu de

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

Vous pouvez directement faire

private List<TeddyBear> list;

Pas besoin d'annotation @Value

En outre, le nom de la variable doit être list car c'est ce que vous avez fourni dans yml.

0
Yogesh Badke