Para criar um microsserviço de validação de CPF com Spring Boot e Docker, estruture o projeto em camadas (controller, service, config, DTO), implemente a lógica de validação algorítmica localmente e delegue a consulta de dados à API CPFHub.io, depois containerize com multi-stage build para uma imagem de produção enxuta (~200MB). O Spring Actuator entrega health checks e métricas prontas sem configuração adicional.
Introdução
Microsserviços são a arquitetura padrão para sistemas modernos, e um serviço dedicado à validação de CPF centraliza essa responsabilidade para toda a organização. O Spring Boot simplifica a criação do serviço, enquanto o Docker garante portabilidade e consistência entre ambientes.
Estrutura do projeto
O projeto segue a estrutura padrão do Spring Boot com separação por camada.
// Estrutura de diretórios
// cpf-service/
// src/main/java/com/cpfservice/
// CpfServiceApplication.java
// config/
// CpfHubConfig.java
// controller/
// CpfController.java
// HealthController.java
// service/
// CpfValidationService.java
// dto/
// CpfRequest.java
// CpfResponse.java
// exception/
// GlobalExceptionHandler.java
// src/main/resources/
// application.yml
// Dockerfile
// docker-compose.yml
| Camada | Responsabilidade | Pacote |
|---|---|---|
| Controller | Endpoints REST | controller |
| Service | Lógica de negócio | service |
| Config | Configuração de beans | config |
| DTO | Objetos de transferência | dto |
| Exception | Tratamento global de erros | exception |
Configuração e DTOs
Configure a aplicação e defina os objetos de transferência de dados.
// application.yml
// server:
// port: 8080
// cpfhub:
// api-key: ${CPFHUB_API_KEY}
// base-url: https://api.cpfhub.io
// timeout: 10000
// management:
// endpoints:
// web:
// exposure:
// include: health,metrics,info
// endpoint:
// health:
// show-details: always
// CpfHubConfig.java
package com.cpfservice.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;
@Configuration
public class CpfHubConfig {
@Value("${cpfhub.timeout:10000}")
private int timeout;
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(5000))
.setReadTimeout(Duration.ofMillis(timeout))
.build();
}
}
// CpfRequest.java
package com.cpfservice.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
public record CpfRequest(
@NotBlank(message = "CPF e obrigatorio")
@Pattern(
regexp = "\\d{11}|\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}",
message = "CPF deve estar no formato correto"
)
String cpf
) {}
// CpfResponse.java
public record CpfResponse(
boolean sucesso,
String fonte,
DadosCpf dados,
String erro
) {
public record DadosCpf(
String cpf,
String name,
String nameUpper,
String gender,
String birthDate,
int day,
int month,
int year
) {}
}
Service layer
O service implementa a lógica de validação algorítmica e consulta via API.
package com.cpfservice.service;
import com.cpfservice.dto.CpfResponse;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class CpfValidationService {
private final RestTemplate restTemplate;
private final String apiKey;
private final String baseUrl;
private final ObjectMapper mapper;
public CpfValidationService(
RestTemplate restTemplate,
@Value("${cpfhub.api-key}") String apiKey,
@Value("${cpfhub.base-url}") String baseUrl) {
this.restTemplate = restTemplate;
this.apiKey = apiKey;
this.baseUrl = baseUrl;
this.mapper = new ObjectMapper();
}
public CpfResponse validar(String cpf) {
String cpfLimpo = cpf.replaceAll("\\D", "");
// Validação algorítmica
if (!validarAlgoritmo(cpfLimpo)) {
return new CpfResponse(
false, "algoritmo", null,
"CPF invalido (digitos verificadores)"
);
}
// Consulta via API
try {
HttpHeaders headers = new HttpHeaders();
headers.set("x-api-key", apiKey);
ResponseEntity<String> response =
restTemplate.exchange(
baseUrl + "/cpf/" + cpfLimpo,
HttpMethod.GET,
new HttpEntity<>(headers),
String.class
);
JsonNode root = mapper.readTree(response.getBody());
if (root.get("success").asBoolean()) {
JsonNode data = root.get("data");
CpfResponse.DadosCpf dados =
new CpfResponse.DadosCpf(
data.get("cpf").asText(),
data.get("name").asText(),
data.get("nameUpper").asText(),
data.get("gender").asText(),
data.get("birthDate").asText(),
data.get("day").asInt(),
data.get("month").asInt(),
data.get("year").asInt()
);
return new CpfResponse(true, "api", dados, null);
}
return new CpfResponse(
false, "api", null, "CPF nao encontrado"
);
} catch (Exception e) {
return new CpfResponse(
false, "erro", null,
"Erro na consulta: " + e.getMessage()
);
}
}
private boolean validarAlgoritmo(String cpf) {
if (cpf.length() != 11) return false;
if (cpf.chars().distinct().count() == 1) return false;
int soma = 0;
for (int i = 0; i < 9; i++) {
soma += Character.getNumericValue(cpf.charAt(i))
* (10 - i);
}
int resto = (soma * 10) % 11;
if (resto == 10) resto = 0;
if (resto != Character.getNumericValue(cpf.charAt(9)))
return false;
soma = 0;
for (int i = 0; i < 10; i++) {
soma += Character.getNumericValue(cpf.charAt(i))
* (11 - i);
}
resto = (soma * 10) % 11;
if (resto == 10) resto = 0;
return resto == Character.getNumericValue(cpf.charAt(10));
}
}
Controller e exception handler
O controller expõe os endpoints REST para validação de CPF.
package com.cpfservice.controller;
import com.cpfservice.dto.CpfResponse;
import com.cpfservice.service.CpfValidationService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/v1/cpf")
public class CpfController {
private final CpfValidationService service;
public CpfController(CpfValidationService service) {
this.service = service;
}
@GetMapping("/{cpf}")
public ResponseEntity<CpfResponse> validar(
@PathVariable String cpf) {
CpfResponse resultado = service.validar(cpf);
int status = resultado.sucesso() ? 200 : 404;
return ResponseEntity.status(status).body(resultado);
}
@PostMapping("/lote")
public ResponseEntity<Map<String, Object>> validarLote(
@RequestBody List<String> cpfs) {
List<CpfResponse> resultados = cpfs.stream()
.map(service::validar)
.toList();
long validos = resultados.stream()
.filter(CpfResponse::sucesso).count();
return ResponseEntity.ok(Map.of(
"total", cpfs.size(),
"validos", validos,
"invalidos", cpfs.size() - validos,
"resultados", resultados
));
}
}
| Endpoint | Método | Descrição |
|---|---|---|
/api/v1/cpf/{cpf} | GET | Validar CPF individual |
/api/v1/cpf/lote | POST | Validar lote de CPFs |
/actuator/health | GET | Health check |
/actuator/metrics | GET | Métricas da aplicação |
Dockerfile e Docker Compose
Containerize o serviço com multi-stage build para uma imagem otimizada. A documentação oficial do Docker recomenda essa abordagem para reduzir o tamanho da imagem final em aplicações JVM.
# Dockerfile
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "app.jar"]
# docker-compose.yml
version: "3.8"
services:
cpf-service:
build: .
ports:
- "8080:8080"
environment:
- CPFHUB_API_KEY=${CPFHUB_API_KEY}
- SPRING_PROFILES_ACTIVE=prod
- JAVA_OPTS=-Xmx256m -Xms128m
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 3s
retries: 3
restart: unless-stopped
deploy:
resources:
limits:
memory: 512M
cpus: "0.5"
| Estágio | Imagem | Tamanho |
|---|---|---|
| Builder | eclipse-temurin:21-jdk-alpine | ~400MB |
| Runtime | eclipse-temurin:21-jre-alpine | ~180MB |
| Imagem final | Com aplicação | ~200MB |
Perguntas frequentes
Por que usar um microsserviço dedicado em vez de validar o CPF diretamente em cada serviço?
Centralizar a validação em um microsserviço elimina duplicação de código, garante consistência nas regras de negócio e facilita auditoria. Quando as regras mudam (novo provider de API, lógica de cache, requisitos de PLD/FT), a atualização ocorre em um único ponto sem impactar os consumidores.
Como o Spring Actuator ajuda em produção?
O Actuator expõe endpoints /actuator/health e /actuator/metrics que orquestradores como Kubernetes e balanceadores de carga usam para saber se o serviço está saudável. O health check configurado no Dockerfile e no docker-compose.yml reinicia o container automaticamente em caso de falha.
Como lidar com timeouts nas chamadas à API CPFHub.io?
Configure setConnectTimeout (recomendado: 5s) e setReadTimeout (recomendado: 10s) no RestTemplateBuilder. A latência típica da CPFHub.io é ~900ms, então um timeout de 10s cobre picos ocasionais sem prejudicar a experiência. Em caso de timeout, retorne um erro controlado em vez de deixar a thread travar.
A API CPFHub.io bloqueia requisições se o limite do plano for atingido?
Não. Se o volume de consultas ultrapassar o limite do plano contratado, a API continua respondendo normalmente e cobra R$0,15 por consulta adicional. Isso garante que o microsserviço nunca perca disponibilidade por causa de cotas — apenas revise o faturamento em app.cpfhub.io/settings/billing.
Conclusão
Um microsserviço de validação de CPF com Spring Boot e Docker centraliza a responsabilidade de validação, oferecendo endpoints REST consistentes para toda a organização. O Spring Actuator fornece health checks e métricas prontas para produção, enquanto o Docker garante portabilidade e consistência entre ambientes. Essa arquitetura permite escalar o serviço independentemente e atualizá-lo sem impactar os consumidores.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e integre a API CPFHub.io ao seu microsserviço Spring Boot em menos de 30 minutos.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



