Configuração yaml do Boot Spring para obter uma lista de strings

149

Estou tentando carregar uma matriz de seqüências de caracteres do arquivo application.yml. Esta é a configuração:

ignore:
    filenames:
        - .DS_Store
        - .hg

Esta é a classe:

@Value("${ignore.filenames}")
private List<String> igonoredFileNames = new ArrayList<>();

Existem outras configurações na mesma classe que carregam perfeitamente. Não há guias no meu arquivo yaml. Ainda recebo a seguinte exceção:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'ignore.filenames' in string value "${ignore.filenames}"
Bahadır Yağan
fonte

Respostas:

71

Meu palpite é que o @Valuenão pode lidar com tipos "complexos". Você pode ir com uma classe de suporte como esta:

@Component
@ConfigurationProperties('ignore')
class IgnoreSettings {
    List<String> filenames
}

Observe: este código é Groovy - não Java - para manter o exemplo curto! Veja os comentários para obter dicas sobre como adotar.

Veja o exemplo completo https://github.com/christoph-frick/so-springboot-yaml-string-list

cfrick
fonte
1
Você pode vincular uma vírgula com @Value(desde que um conversor esteja registrado, que será no Spring Boot, eu acho).
Dave Syer
2
Ele está pegando as configurações de string, mas não as configurações da List <>
Bahadır Yağan
1
Não consegui fazê-lo funcionar @Configuration, mas usar o que @Componentfoi feito.
Stijn Van Bael
1
@ cfrick sim, foi a única alteração que fiz. Olhando para o propósito de ambas as anotações, eu diria que @Componenté mais apropriado: stackoverflow.com/questions/12229282/...
Stijn Van Bael
2
Isto olha como ele é uma limitação com os processos de inicialização mola que anotação - github.com/spring-projects/spring-boot/issues/501
wontondon
134

use valores separados por vírgula em application.yml

ignoreFilenames: .DS_Store, .hg

código java para acesso

@Value("${ignoreFilenames}")    
String[] ignoreFilenames

Está funcionando ;)

Ahmet Vehbi Olgaç
fonte
Eu estava esperando que isso também funcionasse no Dropwizard: '(embora obrigado!
RST
1
Essa deveria ter sido a melhor resposta.
Mohamed Elsayed
3
Nos meus próprios testes, isso é equivalente a ".DS_Store, .hg", mas não ".DS_Store", ".hg" - o último falha com "org.yaml.snakeyaml.parser.ParserException: ao analisar um mapeamento de bloco". Portanto, o que você está fazendo aqui é fornecer a propriedade como uma única sequência separada por vírgula (que o Spring divide em uma matriz ou lista) em vez de uma matriz YAML. Isso "funciona", mas não responde à pergunta original. Ainda não encontrei uma maneira de analisar uma matriz YAML em uma propriedade de bean anotado @Value.
Zirzirikos 13/03/19
38

Nos documentos de inicialização da primavera, https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

As listas YAML são representadas como chaves de propriedade com desreferencers [index], por exemplo, este YAML:

my:
   servers:
       - dev.bar.com
       - foo.bar.com

Seria transformado nessas propriedades:

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

Para vincular a propriedades como essa usando os utilitários Spring DataBinder (que é o que @ConfigurationPropertiesfaz), você precisa ter uma propriedade no bean de destino do tipo java.util.Liste precisa fornecer um setter ou inicializá-lo com um valor mutável, por exemplo, isso será vinculado para as propriedades acima. Aqui está a aparência do código da pergunta.

@ConfigurationProperties(prefix="ignore")
public class Filenames {

    private List<String> ignoredFilenames = new ArrayList<String>();

    public List<String> getFilenames() {
        return this.ignoredFilenames;
    }
}
dskow
fonte
2
Isso deve estar funcionando, getXxx()é necessário que o BTW funcione e deve usar um List, não Set.
Eric Wang
No yaml, a lista de valores para o ArrayList pode ser uma lista delimitada por vírgula. No meu caso, tenho muitos valores, portanto, uma lista compacta é mais limpa que um item por linha. Assim, no exemplo, você pode fazer servidores: dev.bar.com, foo.bar.com
Violaman
O yaml pode ser carregado a partir de um arquivo de propriedades como este servers: ${my.servers}:? Para entrar my.servers[0]e my.servers[1]entrar no yaml? Estou tentando ter configurações dependentes do estágio
ochs.tobi
25

Além da resposta de Ahmet, você pode adicionar quebras de linha à sequência separada por coma usando o >símbolo.

application.yml :

ignoreFilenames: >
  .DS_Store, 
  .hg

Código Java :

@Value("${ignoreFilenames}")    
String[] ignoreFilenames;
Sasha Shpota
fonte
Isso funciona bem desde que você não tenha mais vírgulas (,) em suas strings.
Valentin Despa
Isso não funciona para ler propriedades como arraylist. Ele os lê como String única.
Sree Lakshmi
6

A resposta de Ahmet fornece como atribuir os valores separados por vírgula ao array String.

Para usar a configuração acima em diferentes classes, pode ser necessário criar getters / setters para isso. Mas se você deseja carregar essa configuração uma vez e continuar usando-a como um bean com anotação com conexão automática, aqui está como eu realizei:

No ConfigProvider.java

@Bean (name = "ignoreFileNames")
@ConfigurationProperties ( prefix = "ignore.filenames" )
public List<String> ignoreFileNames(){
    return new ArrayList<String>();
}

Nas aulas externas:

@Autowired
@Qualifier("ignoreFileNames")
private List<String> ignoreFileNames;

você pode usar a mesma lista em qualquer outro lugar por ligação automática.

Deepak
fonte
Isso funciona. No meu caso, embora o aplicativo falhe, a menos que eu adicione @Configurationno início da classe em ConfigProvider.java. Caso contrário, obtive o Source necessário um bean do tipo 'java.util.List' que não pôde ser encontrado.
Diana
3
@Value("#{'${your.elements}'.split(',')}")  
private Set<String> stringSet;

arquivo yml:

your:
 elements: element1, element2, element3

Você pode jogar muito mais com o jogo de primavera.

Vivek Swansi
fonte
2

Bem, a única coisa que posso fazer funcionar é assim:

servers: >
    dev.example.com,
    another.example.com

@Value("${servers}")
private String[] array;

E não se esqueça da @Configuration acima da sua classe ....

Sem a separação ",", não há tanta sorte ...

Funciona também (boot 1.5.8 versie)

servers: 
       dev.example.com,
       another.example.com
Roland Roos
fonte
-1

No meu caso, esse foi um problema de sintaxe no arquivo .yml. Eu tinha:

@Value("${spring.kafka.bootstrap-servers}")
public List<String> BOOTSTRAP_SERVERS_LIST;

e a lista no meu arquivo .yml:

bootstrap-servers:
  - s1.company.com:9092
  - s2.company.com:9092
  - s3.company.com:9092

não estava lendo no campo anotado @ Value. Quando alterei a sintaxe no arquivo .yml para:

bootstrap-servers >
  s1.company.com:9092
  s2.company.com:9092
  s3.company.com:9092

funcionou bem.

Matt Campbell
fonte
Tentando isso no spring-boot 1.5, isso não funciona. Você precisa de uma vírgula após Bootstrap-servidores
Taugenichts
-2
@Value("${your.elements}")    
private String[] elements;

arquivo yml:

your:
 elements: element1, element2, element3
Sashanet Buryk
fonte
1
Como essa resposta é diferente de Ahmet? stackoverflow.com/a/41462567/2065796
Sasha Shpota
1
Resposta já fornecida. Respondendo apenas por uma questão de pontos não agrega valor
Deepak