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

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


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


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

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;

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.


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.


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

-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.


Tentando isso no spring-boot 1.5, isso não funciona. Você precisa de uma vírgula após Bootstrap-servidores
— Taugenichts

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.