🚀 Capítulo 16: O Arquiteto de APIs (Tema: Matrix)
NOTE
Este capítulo utiliza a temática de Matrix para explicar o padrão DTO (Data Transfer Object). Aprenda a proteger os dados do seu banco não expondo tudo para a internet!
1. 🎯 Objetivo da Aula
Compreender o padrão de projeto DTO (Data Transfer Object), por que não devemos expor as nossas entidades de banco de dados diretamente nas rotas e como criar classes DTO em Java.
2. 🏢 O Cenário Prático (Seu Desafio)
Voltamos ao mundo de Matrix! O Arquiteto planejou minuciosamente cada fluxo de dados. Ele sabe que se um usuário comum tiver acesso direto aos códigos raiz do sistema, ele pode causar um colapso! Por isso, o sistema só mostra para o usuário o que ele realmente precisa ver, escondendo os segredos do código-fonte.
No desenvolvimento de APIs com Spring Boot, nós criamos as nossas Entidades (como a classe Usuario que vimos no capítulo anterior) para representar as tabelas do banco de dados.
- Se nós retornarmos a entidade
Usuariodireto na rota de busca, o JSON vai mostrar tudo: o ID do banco, a data de criação e, pior ainda, a senha criptografada do usuário! - Para resolver isso, o Arquiteto usa os DTOs (Data Transfer Objects)!
- São classes que servem exclusivamente para modelar os dados que vão “viajar” do servidor para o usuário. Seu desafio é desenhar esses pacotes de dados!
🧠 Fundamentos: A Teoria Traduzida
📦 1. O que é um DTO?
É uma classe Java simples que não tem nenhuma lógica de negócio, apenas as variáveis que queremos enviar ou receber pela internet.
🛡️ 2. Por que usar DTOs?
- Segurança: Você esconde campos sensíveis (como senhas).
- Performance: Você só envia o que o usuário vai usar, economizando internet.
- Flexibilidade: Você pode juntar dados de duas tabelas diferentes em um único DTO para enviar para o usuário.
4. 📖 Exemplo Guiado: O DTO de Resposta
Imagine que a nossa entidade de banco de dados tem muitos campos:
public class Usuario {
private Long id;
private String nome;
private String email;
private String senha; // SEGREDO!
private LocalDateTime dataCriacao; // O usuário não precisa ver isso.
}Nós criamos um DTO apenas com o que o aplicativo do usuário precisa exibir na tela:
public class UsuarioDTO {
private String nome;
private String email;
// Construtor que transforma a Entidade em DTO
public UsuarioDTO(Usuario usuario) {
this.nome = usuario.getNome();
this.email = usuario.getEmail();
}
// Getters...
}5. 🛠️ Prática Obrigatória 1: A Vantagem do DTO
Com base no texto:
- Qual é o principal problema de segurança que acontece quando um programador retorna a própria classe
@Entity(do banco de dados) diretamente no método do Controller para o usuário ver?
6. 🛠️ Prática Obrigatória 2: O Record do Java (Opcional)
A partir do Java 14, surgiu uma forma ultra curta de criar DTOs chamada record, onde não precisamos digitar getters nem construtores!
public record UsuarioDTO(String nome, String email) { }- Escreva a linha de código usando
recordpara criar um DTO chamadoProdutoDTOcontendo apenas as variáveisString nomeeDouble preco.
7. 📤 Instruções de Entrega (GitHub Desktop + Microsoft Teams)
- Faça o Commit: No GitHub Desktop, digite a mensagem (ex:
Finaliza Capítulo 16 Java_Arquiteto) e clique em Commit to main. - Envie para a Nuvem (Push): Clique em Push origin.
8. 📂 Estrutura de Pastas
spec_backend_com_java_e_springboot/
├── capitulos/
│ └── capitulo_16_arquiteto.md💡 Checkpoint de Lógica
Para não precisarmos ficar digitando código para copiar os dados da Entidade para o DTO manualmente, existem bibliotecas famosas no Java como o ModelMapper ou o MapStruct que fazem isso em uma linha!
10. 🔥 Desafio de Fixação
Pesquise qual é a diferença entre um Input DTO (dados que chegam do usuário) e um Output DTO (dados que enviamos para o usuário).
🔑 Gabarito de Código/Fórmulas
Gabarito da Prática 1:
- O principal problema é o vazamento de dados sensíveis! Se a entidade tiver campos como senha, CPF, ou dados internos do banco, todos eles serão transformados em JSON e enviados para a tela do usuário, o que gera uma falha grave de segurança. Gabarito da Prática 2:
public record ProdutoDTO(String nome, Double preco) { }