404 Not Found

404 Not Found


nginx

Gerenciamento de Configuração

O gerenciamento de configuração serve como ponte entre desenvolvimento e produção—uma base de código, múltiplas configurações, e a alternância entre ambientes requer apenas uma linha de parâmetros.

1. O Que Você Vai Aprender


2. Uma História Real de um Engenheiro de Operações

(1) Ponto de Dor: Configurações espalhadas por todo lado

Bob é um engenheiro de operações no OrderFlow, e toda implantação parece uma "escavação arqueológica": senhas de banco de dados estão hard-coded no código, e as configurações dos ambientes de teste e produção estão misturadas em um único arquivo. Alguém alterou a senha do banco de dados de produção mas esqueceu de atualizar o código, causando queda do sistema por duas horas. Quando Charlie cobrou dele sobre o SLA, Bob só pôde explicar, com um suspiro, que "o gerenciamento de configuração é uma bagunça."

(2) Soluções com Spring Boot Profiles

O Spring Boot usa o mecanismo de Profile para separar configurações de múltiplos ambientes:

YAML
# application-dev.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/orderflow_dev
    username: dev_user
    password: dev_pass
YAML
# application-prod.yml
spring:
  datasource:
    url: jdbc:mysql://prod-db.internal:3306/orderflow
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

(3) Resultado

Depois que Bob refatorou o código usando Profile e variáveis de ambiente, o ambiente de desenvolvimento agora usa dev e o ambiente de produção usa prod. Informações sensíveis não aparecem mais no repositório de código, e a alternância de implantações requer apenas --spring.profiles.active=prod, reduzindo o tempo de inatividade causado por erros de configuração a zero.


3. Profile: Configuração de Múltiplos Ambientes

(1) Convenções de Nomenclatura de Arquivo de Profile

O Spring Boot carrega configurações de perfil de acordo com a convenção de nomenclatura application-{profile}.yml:

TEXT
src/main/resources/
├── application.yml            # Configuração comum (compartilhada)
├── application-dev.yml        # Profile de dev
├── application-prod.yml       # Profile de produção
└── application-test.yml       # Profile de teste
100%
graph TD
    A["application.yml<br/>Configuração Comum"] --> B["application-dev.yml<br/>Substituições de Dev"]
    A --> C["application-prod.yml<br/>Substituições de Prod"]
    A --> D["application-test.yml<br/>Substituições de Test"]
    B --> E["Configuração Mesclada<br/>Profile=dev"]
    C --> F["Configuração Mesclada<br/>Profile=prod"]
Método de Ativação Comando Prioridade
Arquivo de Configuração spring.profiles.active=dev em application.yml Mínima
Variável de Ambiente SPRING_PROFILES_ACTIVE=dev Média
Argumento de linha de comando --spring.profiles.active=dev Máxima

(1) ▶ Exemplo: Profile

YAML
# application.yml (compartilhado)
spring:
  application:
    name: orderflow-service
  profiles:
    active: dev

server:
  port: 8080

Saída:

TEXT
Configuração aplicada com sucesso
YAML
# application-dev.yml
spring:
  datasource:
    url: jdbc:h2:mem:orderflow_dev
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true

logging:
  level:
    com.orderflow: DEBUG
YAML
# application-prod.yml
spring:
  datasource:
    url: jdbc:mysql://${DB_HOST:localhost}:3306/orderflow
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

logging:
  level:
    com.orderflow: WARN

4. Comparação de @Value e @ConfigurationProperties

(1) Dois Métodos de Injeção

(1) ▶ Exemplo: Injeção com @Value

JAVA
@RestController
public class OrderController {

    @Value("${orderflow.max-items-per-order:100}")
    private int maxItemsPerOrder;

    @Value("${orderflow.default-currency:USD}")
    private String defaultCurrency;

    @GetMapping("/api/config/check")
    public Map<String, Object> checkConfig() {
        return Map.of(
            "maxItemsPerOrder", maxItemsPerOrder,
            "defaultCurrency", defaultCurrency
        );
    }
}

Saída:

TEXT
// Execução bem-sucedida

(2) ▶ Exemplo: Binding tipo-seguro com @ConfigurationProperties

JAVA
@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
    int maxItemsPerOrder,
    String defaultCurrency,
    Duration orderTimeout,
    ShippingConfig shipping
) {
    public record ShippingConfig(
        boolean freeShippingEnabled,
        BigDecimal freeShippingThreshold
    ) {}
}

// Ativar na classe principal ou classe de configuração
@EnableConfigurationProperties(OrderFlowProperties.class)

Saída:

TEXT
// Execução bem-sucedida
Dimensão @Value @ConfigurationProperties
Segurança de Tipo Fraca (primariamente String) Forte (conversão automática de tipo)
Objetos aninhados Não suportado Suportado
Binding de Coleção Não Suportado Suporta List/Map
Verificação Nenhuma Em conjunto com @Validated
Suporte IDE Sem sugestões Auto-completar (metadados)
Casos de Uso Pequena Quantidade de Valores Simples Configuração de Negócio Estruturada

(3) ▶ Exemplo: Mapeamentos YAML e ConfigurationProperties

YAML
orderflow:
  max-items-per-order: 50
  default-currency: USD
  order-timeout: 30m
  shipping:
    free-shipping-enabled: true
    free-shipping-threshold: 49.99

Saída:

TEXT
A configuração entrou em vigor.
JAVA
// Exemplo de acesso
@Component
public class OrderService {
    private final OrderFlowProperties props;

    public OrderService(OrderFlowProperties props) {
        this.props = props;
    }

    public boolean isFreeShipping(BigDecimal orderTotal) {
        return props.shipping().freeShippingEnabled()
            && orderTotal.compareTo(props.shipping().freeShippingThreshold()) >= 0;
    }
}

5. Hierarquia de Prioridade de Configuração

(1) Prioridade da mais alta para a mais baixa

100%
graph TD
    A["1. Argumentos de Linha de Comando<br/>--server.port=9090"] --> B["2. Atributos JNDI"]
    B --> C["3. Propriedades do Sistema Java<br/>-Dserver.port=9090"]
    C --> D["4. Variáveis de Ambiente do SO<br/>SERVER_PORT=9090"]
    D --> E["5. application-{profile}.yml<br/>Específico do Profile"]
    E --> F["6. application.yml<br/>Configuração padrão"]
    F --> G["7. @Default Values<br/>Em anotações de código"]
Prioridade Origem Exemplo
1 (Mais Alta) Argumentos de linha de comando --server.port=9090
2 Propriedades JNDI java:comp/env/...
3 Propriedades do Sistema JVM -Dserver.port=9090
4 Variáveis de Ambiente do SO SERVER_PORT=9090
5 Profile application-prod.yml
6 Arquivo de Configuração Padrão application.yml
7 (mínima) Valor padrão @Value("${x:default}")
💡 Dica: Em ambiente de produção, recomenda-se sobrescrever configurações sensíveis usando variáveis de ambiente ou argumentos de linha de comando; não inclua senhas nos arquivos de configuração.


6. Configuração Aninhada e Binding de Coleção

(1) Binding de Listas e Maps

(1) ▶ Exemplo: Configuração de List e Map

YAML
orderflow:
  supported-currencies:
    - USD
    - EUR
    - GBP
  payment-gateways:
    stripe:
      api-key: ${STRIPE_API_KEY}
      webhook-secret: ${STRIPE_WEBHOOK_SECRET}
    paypal:
      client-id: ${PAYPAL_CLIENT_ID}
      secret: ${PAYPAL_SECRET}

Saída:

TEXT
Configuração do pipeline CI/CD foi carregada
Status do pipeline: passed
Testes: 12 passed, 0 failed
JAVA
@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
    List<String> supportedCurrencies,
    Map<String, GatewayConfig> paymentGateways
) {
    public record GatewayConfig(
        String apiKey,
        String webhookSecret,
        String clientId,
        String secret
    ) {}
}

7. Exemplo Abrangente: O Sistema de Configuração Completo do OrderFlow

JAVA
// OrderFlowProperties.java
package com.orderflow.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.List;
import java.util.Map;

@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
    int maxItemsPerOrder,
    String defaultCurrency,
    Duration orderTimeout,
    ShippingConfig shipping,
    List<String> supportedCurrencies,
    Map<String, GatewayConfig> paymentGateways
) {
    public record ShippingConfig(
        boolean freeShippingEnabled,
        BigDecimal freeShippingThreshold
    ) {}

    public record GatewayConfig(
        String apiKey,
        String webhookSecret,
        String clientId,
        String secret
    ) {}
}

// AppConfig.java
package com.orderflow.config;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(OrderFlowProperties.class)
public class AppConfig {}
YAML
# application.yml
spring:
  application:
    name: orderflow-service
  profiles:
    active: dev

orderflow:
  max-items-per-order: 50
  default-currency: USD
  order-timeout: 30m
  supported-currencies:
    - USD
    - EUR
    - GBP
  shipping:
    free-shipping-enabled: true
    free-shipping-threshold: 49.99
  payment-gateways:
    stripe:
      api-key: ${STRIPE_API_KEY:dev-key}
      webhook-secret: ${STRIPE_WEBHOOK_SECRET:dev-secret}

❓ Perguntas Frequentes

P Qual devo escolher, @ConfigurationProperties ou @Value?
R Use @ConfigurationProperties para configuração estruturada (segurança de tipo, aninhamento, suporte IDE), e @Value para um pequeno número de valores simples. Evite misturar muitos deles em um único projeto.
P Como posso evitar que informações sensíveis vazem para o repositório de código?
R 1) Use o placeholder ${ENV_VAR} em arquivos de configuração para referenciar variáveis de ambiente; 2) Exclua arquivos de configuração sensíveis no .gitignore; 3) Use K8s Secrets ou Vault para gerenciar secrets em ambientes de produção.
P Como as configurações de Profile e as configurações padrão são mescladas?
R O Spring Boot primeiro carrega a configuração padrão, depois usa a configuração do Profile para sobrescrever propriedades correspondentes. Para propriedades diferentes, elas se complementam; para propriedades correspondentes, o Profile tem precedência.
P Como escrever uma lista em YAML na seção "Properties"?
R orderflow.supported-currencies[0]=USD, orderflow.supported-currencies[1]=EUR. Índices de lista começam em 0.
P Como alterno profiles dinamicamente no código?
R A alteração dinâmica de profiles no código não é recomendada. Profiles devem ser determinados na inicialização. Se você precisa alternar configurações dinamicamente em tempo de execução, use Spring Cloud Config ou um mecanismo de refresh de configuração personalizado.
P Quais são as limitações de usar record como ConfigurationProperties?
R record é imutável e é adequado para configurações somente leitura. Spring Boot 3.x suporta binding de record. No entanto, ele não pode ser usado com @Validated para validação JSR-380 (já que record não tem construtor sem argumentos), então uma classe deve ser usada em vez disso.

📖 Resumo


📝 Exercícios

  1. Exercício Básico (Dificuldade ⭐): Configure dois profiles para o OrderFlow—um para dev e um para prod. O profile de dev usa o banco de dados em memória H2, enquanto o profile de prod usa MySQL. Alterne entre eles usando argumentos de linha de comando.

  2. Problema Avançado (Dificuldade ⭐⭐): Use @ConfigurationProperties para criar PaymentGatewayProperties, que inclui configurações de chave de API para Stripe e PayPal; injete os valores das chaves via variáveis de ambiente.

  3. Desafio (Dificuldade: ⭐⭐⭐): Implemente um PropertySource personalizado para carregar configuração de um centro de configuração remoto (você pode usar um endpoint HTTP simulado), e considere a intenção de design por trás da abstração Environment do Spring Boot.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%