Guia para @ConfigurationProperties no Spring Boot
1. Introdução
Um recurso útil do Spring Boot éexternalized configuration and easy access to properties defined in properties files. Umarticle anterior descreveu várias maneiras pelas quais isso pode ser feito.
Agora vamos explorar a anotação@ConfigurationProperties em mais detalhes.
Leitura adicional:
Um guia rápido para Spring @Value
Aprenda a usar a anotação Spring @Value para configurar campos de arquivos de propriedades, propriedades do sistema etc.
Propriedades com Spring e Spring Boot
Tutorial de como trabalhar com arquivos de propriedades e valores de propriedades no Spring.
2. Configuração
Este artigo usa uma configuração bastante padrão. Começamos adicionandospring-boot-starter-parent como o pai em nossopom.xml:
org.springframework.boot
spring-boot-starter-parent
2.1.3.RELEASE
Para poder validar as propriedades definidas no arquivo, também precisamos de uma implementação do JSR-303. hibernate-validator é um deles.
Vamos adicioná-lo ao nossopom.xml também:
org.hibernate
hibernate-validator
6.0.16.Final
A páginagetting started with Hibernate Validator tem mais detalhes.
3. Propriedades Simples
A documentação oficial informa que isolamos as propriedades de configuração em POJOs. separados
Então, vamos começar fazendo isso:
@Configuration
@PropertySource("classpath:configprops.properties")
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
// standard getters and setters
}
Usamos@Configuration para que o Spring crie um bean Spring no contexto do aplicativo.
Também usamos@PropertySource para definir a localização do nosso arquivo de propriedades. Caso contrário, o Spring usa o local padrão (classpath:application.properties).
@ConfigurationProperties works best with hierarchical properties that all have the same prefix. Portanto, adicionamos um prefixo demail.
A estrutura do Spring usa setters Java bean padrão, portanto, é essencial declarar setters para cada uma das propriedades.
Nota: Se não usarmos@Configuration in o POJO, então precisamos adicionar@EnableConfigurationProperties(ConfigProperties.class) in a classe de aplicativo Spring principal para vincular as propriedades ao POJO:
@SpringBootApplication
@EnableConfigurationProperties(ConfigProperties.class)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
É isso aí! Spring will automatically bind any property defined in our property file that has the prefix mail and the same name as one of the fields in the ConfigProperties class.
O Spring usa algumas regras flexíveis para propriedades de ligação. Portanto, as seguintes variações estão todas vinculadas à propriedadehostName:
mail.hostName
mail.hostname
mail.host_name
mail.host-name
mail.HOST_NAME
Podemos usar o seguinte arquivo de propriedades para definir todos os campos:
#Simple properties
[email protected]
mail.port=9000
[email protected]
4. Propriedades Aninhadas
Podemos ter propriedades aninhadas emLists, Maps,eClasses.
Vamos criar uma nova classeCredentials para usar para algumas propriedades aninhadas:
public class Credentials {
private String authMethod;
private String username;
private String password;
// standard getters and setters
}
Também atualizamos a classeConfigProperties para usar aList, aMape a classeCredentials:
public class ConfigProperties {
private String host;
private int port;
private String from;
private List defaultRecipients;
private Map additionalHeaders;
private Credentials credentials;
// standard getters and setters
}
O seguinte arquivo de propriedades definirá todos os campos:
#Simple properties
[email protected]
mail.port=9000
[email protected]
#List properties
mail.defaultRecipients[0][email protected]
mail.defaultRecipients[1][email protected]
#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true
#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1
5. Usando@ConfigurationProperties em um método@Bean
Também podemos usar a anotação@ConfigurationProperties em métodos anotados@Bean.
Essa abordagem pode ser particularmente útil quando queremos vincular propriedades a um componente de terceiros que está fora de nosso controle.
Vamos criar uma classeItem simples que usaremos no próximo exemplo:
public class Item {
private String name;
private int size;
// standard getters and setters
}
Agora, vamos ver como podemos usar@ConfigurationProperties em um método@Bean para vincular propriedades externalizadas à instânciaItem:
@Configuration
public class ConfigProperties {
@Bean
@ConfigurationProperties(prefix = "item")
public Item item() {
return new Item();
}
}
Dessa forma, qualquer propriedade com prefixo de item será mapeada para a instânciaItem gerenciada pelo contexto Spring.
6. Validação de propriedade
@ConfigurationProperties provides validation of properties using the JSR-303 format. Isso permite todos os tipos de coisas legais.
Por exemplo, vamos tornar a propriedadehostName obrigatória:
@NotBlank
private String hostName;
E a propriedadeauthMethod de 1 a 4 caracteres:
@Length(max = 4, min = 1)
private String authMethod;
E a propriedadeport de 1025 a 65536:
@Min(1025)
@Max(65536)
private int port;
Finalmente, a propriedadefrom deve corresponder a um formato de endereço de e-mail:
@Pattern(regexp = "^[a-z0-9._%+-][email protected][a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;
Isso nos ajuda a reduzir muitas das condiçõesif – else em nosso código e faz com que pareça muito mais limpo e conciso.
If any of these validations fail then the main application would fail to start with an IllegalStateException.
A estrutura de validação do Hibernate usa getters e setters Java bean padrão, por isso é importante que declaremos getters e setters para cada uma das propriedades.
7. Conversão de propriedade
@ConfigurationProperties oferece suporte à conversão de vários tipos para vincular as propriedades aos seus beans correspondentes.
7.1. Duration
Começaremos observando a conversão de propriedades em objetosDuration.
Aqui temos dois campos do tipoDuration:
@ConfigurationProperties(prefix = "conversion")
public class PropertyConversion {
private Duration timeInDefaultUnit;
private Duration timeInNano;
...
}
E nosso arquivo de propriedades:
conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns
Como resultado, o campotimeInDefaultUnit terá um valor de 10 milissegundos etimeInNano terá um valor de 9 nanossegundos.
As unidades com suporte sãons, us, ms, s, m, hed para nanossegundos, microssegundos, milissegundos, segundos, minutos, horas e dias, respectivamente.
A unidade padrão é milissegundos, o que significa que se não especificarmos uma unidade próxima ao valor numérico, o Spring converterá o valor em milissegundos.
Também podemos substituir a unidade padrão usando@DurationUnit:
@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;
e a propriedade correspondente:
conversion.timeInDays=2
7.2. DataSize
Da mesma forma, Spring Boot@ConfigurationProperties suporta conversão de tipoDataSize.
Vamos adicionar 3 campos do tipoDataSize:
private DataSize sizeInDefaultUnit;
private DataSize sizeInGB;
@DataSizeUnit(DataUnit.TERABYTES)
private DataSize sizeInTB;
e as propriedades correspondentes:
conversion.sizeInDefaultUnit=300
conversion.sizeInGB=2GB
conversion.sizeInTB=4
Neste caso, o valor desizeInDefaultUnit será de 300 bytes, pois a unidade padrão é bytes.
As unidades suportadas sãoB, KB, MB, GBeTB. Também podemos substituir a unidade padrão usando@DataSizeUnit.
7.3. Converter personalizado
Também podemos adicionar nosso próprioConverter personalizado para oferecer suporte à conversão de uma propriedade em um tipo de classe específico.
Vamos adicionar uma classe simplesEmployee:
public class Employee {
private String name;
private double salary;
}
E vamos criar um conversor personalizado para converter essa propriedade:
conversion.employee=john,2000
para um campo do tipoEmployee:
private Employee employee;
Precisaremos implementar a interfaceConverter, entãouse @ConfigurationPropertiesBinding annotation to register our custom*Converter*:
@Component
@ConfigurationPropertiesBinding
public class EmployeeConverter implements Converter {
@Override
public Employee convert(String from) {
String[] data = from.split(",");
return new Employee(data[0], Double.parseDouble(data[1]));
}
}
8. Conclusão
Exploramos a anotação@ConfigurationProperties e vimos alguns dos recursos úteis que ela fornece, como encadernação relaxada e validação de bean.
Como de costume, o código está disponívelover on Github.