🚀 Como Construir APIs de alta qualidade
Se você está desenvolvendo uma API RESTful com Java + Spring Boot e quer entregar algo verdadeiramente profissional, robusto e escalável, este artigo é para você. Vamos percorrer os principais pilares para criar uma API de alta qualidade — da arquitetura aos testes, passando por segurança, performance e documentação.
1. 🧱 Arquitetura: A Base de Tudo
Uma boa API começa com uma arquitetura bem definida. A clássica arquitetura em camadas é a mais adotada:
src/
└── main/
└── java/
└── com/empresa/projeto/
├── controller/ # Endpoints REST
├── service/ # Regras de negócio
├── repository/ # Acesso a dados
├── model/ # Entidades JPA
├── dto/ # Data Transfer Objects
├── config/ # Configurações
├── exception/ # Tratamento de exceções
└── security/ # Segurança e autenticação
Princípios essenciais:
- SRP (Single Responsibility Principle): cada classe faz uma única coisa.
- Separação de responsabilidades: mantenha controle, lógica e dados separados.
- Inversão de dependência: use interfaces e injeção de dependência para acoplamento baixo.
2. ✍️ Padrões de Código
✅ Convenções de nomenclatura
Exemplo de um Controller RESTful bem estruturado:
@RestController
@RequestMapping("/api/v1/usuarios")
public class UsuariosController {
@GetMapping
public ResponseEntity<List<UsuarioDTO>> listarUsuarios() { }
@PostMapping
public ResponseEntity<UsuarioDTO> criarUsuario(@RequestBody @Valid CriarUsuarioDTO dto) { }
}
✅ Estrutura de DTOs
Utilize DTOs específicos por operação:
public class CriarUsuarioDTO {
@NotBlank private String nome;
@Email @NotBlank private String email;
}
public class UsuarioDTO {
private Long id;
private String nome;
private String email;
}
3. ❗Tratamento de Erros
🛡️ Exceções Globais
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ValidationException.class)
public ResponseEntity<ErrorResponse> handleValidation(ValidationException ex) {
return ResponseEntity.badRequest().body(
new ErrorResponse("VALIDATION_ERROR", "Dados inválidos", ex.getErrors())
);
}
}
⚠️ Exceções Customizadas
public class UsuarioJaExisteException extends BusinessException {
public UsuarioJaExisteException(String email) {
super("USER_ALREADY_EXISTS", "Usuário com email %s já existe", email);
}
}
4. 📡 Status HTTP
Respeite os significados dos códigos HTTP:
200 OK
: sucesso na leitura/atualização201 Created
: recurso criado400 Bad Request
: erro de validação409 Conflict
: recurso duplicado500 Internal Server Error
: falha inesperada
Exemplo:
@PostMapping
public ResponseEntity<UsuarioDTO> criarUsuario(@RequestBody @Valid CriarUsuarioDTO dto) {
try {
return ResponseEntity.status(HttpStatus.CREATED).body(service.criarUsuario(dto));
} catch (UsuarioJaExisteException ex) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}
}
5. 🔄 JPA e Relacionamentos
🔗 Entidades com relações
@Entity
public class Usuario {
@Id @GeneratedValue private Long id;
@OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Pedido> pedidos;
}
🚀 Estratégias de performance
Evite problemas de N+1 com @EntityGraph
:
@EntityGraph(attributePaths = {"perfis"})
Optional<Usuario> findByIdWithDetails(Long id);
Use projeções para respostas otimizadas:
public interface UsuarioResumo {
Long getId();
String getNome();
}
6. ⚙️ Configurações Essenciais
Banco de Dados – application.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/api_db
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
Validação
@Configuration
public class ValidationConfig {
@Bean
public Validator validator() {
return Validation.buildDefaultValidatorFactory().getValidator();
}
}
Serialização JSON
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.registerModule(new JavaTimeModule())
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
}
}
7. 📚 Documentação
Swagger + OpenAPI
@OpenAPIDefinition(
info = @Info(title = "API de Usuários", version = "1.0.0")
)
public class OpenApiConfig {}
Documentação de endpoints
@Operation(summary = "Criar usuário")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "Criado com sucesso"),
@ApiResponse(responseCode = "400", description = "Erro de validação")
})
8. ✅ Testes
Testes Unitários
@ExtendWith(MockitoExtension.class)
class UsuarioServiceTest {
@Test
void deveCriarUsuarioComDadosValidos() {
// Given / When / Then
}
}
Testes de Integração com Testcontainers
@SpringBootTest
@Testcontainers
class UsuariosControllerIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:14");
}
9. 🔐 Segurança
Autenticação e Autorização com JWT
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/v1/auth/**").permitAll()
.anyRequest().authenticated())
.build();
}
}
Validação Rigorosa de Inputs
@Pattern(regexp = "^[a-zA-ZÀ-ÿ\\s]+$", message = "Nome inválido")
private String nome;
Rate Limiting com Redis
@Component
public class RateLimitingFilter implements Filter {
// Limita requisições por IP
}
✅ Checklist Final
🔹 Arquitetura
- Camadas bem separadas
- Padrões de nomenclatura claros
- SRP e injeção de dependência
🔹 Banco de Dados
- Relacionamentos corretos
- Queries otimizadas
- Pool de conexões e índices
🔹 Tratamento de Erros
- Exceções globais
- Mensagens de erro úteis
- Códigos HTTP corretos
🔹 Segurança
- JWT e roles
- Validação rigorosa
- Rate limiting
🔹 Testes
- Unitários e de integração
- Testcontainers
- Cobertura mínima de 80%
🔹 Documentação
- OpenAPI
- README com instruções
- Changelog atualizado
🔹 Deploy e Observabilidade
- Logs estruturados
- Health check
- CI/CD + rollback + backup
🏁 Conclusão
Criar uma API de alta qualidade vai muito além de "fazer funcionar". É sobre projetar algo que seja escalável, legível, seguro e confiável. Este guia cobre os pilares principais para te ajudar a construir aplicações profissionais e preparadas para produção.
Se você gostou, compartilhe com sua equipe, salve este artigo e use como checklist em seus próximos projetos. 🚀