O Spring Cloud Config fornece suporte para configurações externas em sistemas distribuídos, tanto do lado do servidor quanto do cliente. Com o Config Server, centraliza-se o gerenciamento de todas as propriedades de aplicativos em diferentes ambientes (desenvolvimento, teste, produção).
Configuração do Servidor (Config Server)
Para criar um servidor de configuração, é necessário iniciar um projeto Spring Boot e incluir a dependência do servidor de configuração. Neste exemplo, utilizaremos o GitHub como repositório para os arquivos de propreidades.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
No arquivo application.properties do servidor, definimos as configurações de integração com o Git e o registro no Eureka:
server.port=8888
spring.application.name=config-server
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
# Integração com Repositório Git
spring.cloud.config.server.git.uri=https://github.com/seu-usuario/repositorio-config.git
spring.cloud.config.server.git.search-paths=config-repo
spring.cloud.config.label=main
spring.cloud.config.server.git.username=usuario
spring.cloud.config.server.git.password=senha
A classe principal deve ser anotada com @EnableConfigServer para ativar as funcionalidades de servidor:
@EnableConfigServer
@EnableDiscoveryClient
@SpringBootApplication
public class CentralConfigApplication {
public static void main(String[] args) {
SpringApplication.run(CentralConfigApplication.class, args);
}
}
Tratamento de Codificação de Caracteres
Em sistemas Windows ou ao lidar com caracteres especiais em arquivos .properties, pode ocorrer corrupção de caracteres. Para garantir a leitura correta em UTF-8, podemos implementar um carregador customizado:
public class CodificacaoPropertiesHandler extends PropertiesPropertySourceLoader {
@Override
public String[] getFileExtensions() {
return new String[]{"properties", "xml"};
}
@Override
public List<PropertySource<?>> load(String nome, Resource recurso) throws IOException {
Properties propriedades = new Properties();
try (InputStreamReader leitor = new InputStreamReader(recurso.getInputStream(), StandardCharsets.UTF_8)) {
propriedades.load(leitor);
}
List<PropertySource<?>> lista = new ArrayList<>();
if (!propriedades.isEmpty()) {
lista.add(new PropertiesPropertySource(nome, propriedades));
}
return lista;
}
}
Para ativar esse handler, crie o arquivo src/main/resources/META-INF/spring.factories:
org.springframework.boot.env.PropertySourceLoader=com.exemplo.config.CodificacaoPropertiesHandler
Configuração do Cliente (Config Client)
O cliente precisa de uma dependência específica para se comunicar com o servidor de configuração:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
É fundamental utilizar o arquivo bootstrap.properties (ou bootstrap.yml) no cliente, pois ele é processado antes do application.properties durante a fase de inicialização do contexto:
spring.application.name=app-cliente
spring.cloud.config.profile=dev
spring.cloud.config.label=main
# Localização do Config Server via URL direta
spring.cloud.config.uri=http://localhost:8888/
# Ou via Service Discovery (Eureka)
# spring.cloud.config.discovery.enabled=true
# spring.cloud.config.discovery.service-id=config-server
Para testar o recebimento dos valores, utilize a anotação @Value em um controlador:
@RestController
@SpringBootApplication
public class ClienteApplication {
@Value("${custom.config.mensagem:Padrao}")
private String mensagem;
@GetMapping("/msg")
public String obterMensagem() {
return "Valor remoto: " + mensagem;
}
public static void main(String[] args) {
SpringApplication.run(ClienteApplication.class, args);
}
}
Atualização Dinâmica de Parâmetros
Por padrão, o cliente lê as configurações no momento da inicialização e as mantém em cache. Se houver mudanças no repositório Git, o Config Server as detecta, mas o cliente não as atualiza automaticamente. Para resolver isso, utilizamos o módulo Actuator.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Adicione a anotação @RefreshScope no Bean que utiliza os valores injetados:
@RefreshScope
@RestController
public class MensagemController {
@Value("${config.usuario.nome}")
private String nomeUsuario;
// ... métodos
}
No Spring Boot 2.x e superiores, os endpoints do Actuator são restritos por padrão. É necessário expor o endpoint de refresh nas configurações do cliente:
management.endpoints.web.exposure.include=refresh
Para forçar a atualização dos dados sem reiniciar a aplicação, envie uma requisição HTTP POST para o endpoint /actuator/refresh do cliente:
curl -X POST http://localhost:8080/actuator/refresh