Spring Boot & Java | GMASystem Tecnologia
GMASystem Tecnologia
Spring Boot & Java
Desenvolvimento de APIs Modernas
Do Iniciante ao Profissional
Com exemplos práticos, projetos reais e atividades
2025 • Primeira Edição
© 2025 GMASystem Tecnologia | Página 1 de 43
Spring Boot & Java | GMASystem Tecnologia
Sobre Este Livro
Este livro foi desenvolvido pela GMASystem Tecnologia para capacitar desenvolvedores Java
a dominarem o ecossistema Spring Boot e a criação de APIs REST modernas, robustas e
escaláveis.
Ao longo de 250 páginas repletas de exemplos práticos, projetos reais e atividades
desafiadoras, você aprenderá desde os fundamentos do Java moderno até a construção de
microsserviços profissionais com Spring Boot.
O que você vai aprender:
• Fundamentos sólidos de Java 17+ e programação orientada a objetos
• Spring Framework e o ecossistema Spring Boot 3.x
• Criação de APIs REST completas com boas práticas
• Persistência de dados com Spring Data JPA e Hibernate
• Segurança com Spring Security e JWT
• Testes automatizados com JUnit 5 e Mockito
• Deploy e containerização com Docker
• Documentação de APIs com Swagger/OpenAPI
Para quem é este livro:
• Desenvolvedores Java que querem aprender Spring Boot
• Estudantes de tecnologia e sistemas de informação
• Profissionais que desejam migrar para o desenvolvimento back-end
• Programadores de outras linguagens que querem conhecer o ecossistema Java
© 2025 GMASystem Tecnologia | Página 2 de 43
Spring Boot & Java | GMASystem Tecnologia
Sumário
Capítulo 1: Introdução ao Java Moderno ............... 15
Capítulo 2: Orientação a Objetos em Java ............. 30
Capítulo 3: Introdução ao Spring Framework ........... 50
Capítulo 4: Spring Boot — Primeiros Passos ........... 65
Capítulo 5: APIs REST com Spring Boot ................ 85
Capítulo 6: Persistência com Spring Data JPA ........ 110
Capítulo 7: Validação e Tratamento de Erros ......... 135
Capítulo 8: Spring Security e JWT ................... 155
Capítulo 9: Testes Automatizados .................... 180
Capítulo 10: Docker e Deploy ........................ 205
Capítulo 11: Projeto Final — Sistema Completo ....... 225
© 2025 GMASystem Tecnologia | Página 3 de 43
Spring Boot & Java | GMASystem Tecnologia
© 2025 GMASystem Tecnologia | Página 4 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 1
Introdução ao Java Moderno
Java é uma das linguagens de programação mais utilizadas no mundo, com mais de 30 anos
de evolução e uma comunidade gigantesca. Desde sua criação por James Gosling na Sun
Microsystems em 1995, Java tem se mantido relevante graças ao seu princípio "Write Once,
Run Anywhere" (escreva uma vez, execute em qualquer lugar).
As versões modernas do Java (17, 21 LTS) trouxeram inúmeras melhorias de sintaxe e
desempenho que tornam o desenvolvimento mais produtivo e elegante.
1.1 Instalação do Ambiente de Desenvolvimento
Para começar a programar em Java, você precisará instalar o JDK (Java Development Kit) e
uma IDE (Integrated Development Environment).
Instalando o JDK 21 LTS
ℹ️ Recomendamos o uso do JDK 21 LTS (Long Term Support) por ser a versão mais estável e
suportada por longo prazo.
Acesse [Link] e baixe o Eclipse Temurin JDK 21. Após a instalação, verifique:
$ java -version
openjdk version "21.0.2" 2024-01-16
OpenJDK Runtime Environment Temurin-21.0.2+13
$ javac -version
javac 21.0.2
IDEs Recomendadas
• IntelliJ IDEA Community (gratuita) — recomendada para Spring Boot
• Eclipse IDE — opção popular e gratuita
• Visual Studio Code com extensão Java Extension Pack
1.2 Seu Primeiro Programa Java
Todo programa Java começa com uma classe contendo o método main. Veja o exemplo
clássico:
public class OlaMundo {
public static void main(String[] args) {
[Link]("Olá, Mundo!");
[Link]("Bem-vindo ao Spring Boot com GMASystem!");
}
}
© 2025 GMASystem Tecnologia | Página 5 de 43
Spring Boot & Java | GMASystem Tecnologia
1.3 Tipos de Dados e Variáveis
Java é uma linguagem fortemente tipada. Cada variável deve ter um tipo declarado:
// Tipos primitivos
int idade = 25;
double salario = 5500.75;
boolean ativo = true;
char inicial = 'J';
long populacaoBrasil = 215000000L;
float temperatura = 36.6f;
// Tipos por referência
String nome = "GMASystem Tecnologia";
Integer idadeObjeto = 25; // Autoboxing
Double salarioObjeto = 5500.75;
1.4 Operadores e Expressões
int a = 10, b = 3;
// Aritméticos
[Link](a + b); // 13
[Link](a - b); // 7
[Link](a * b); // 30
[Link](a / b); // 3 (divisão inteira)
[Link](a % b); // 1 (módulo/resto)
// Relacionais
[Link](a > b); // true
[Link](a == b); // false
[Link](a != b); // true
// Lógicos
[Link](a > 5 && b < 10); // true (AND)
[Link](a > 15 || b < 10); // true (OR)
[Link](!(a > 5)); // false (NOT)
1.5 Estruturas de Controle
If-Else e Switch
int nota = 85;
// If-Else tradicional
if (nota >= 90) {
[Link]("A - Excelente");
} else if (nota >= 80) {
[Link]("B - Bom");
} else if (nota >= 70) {
[Link]("C - Regular");
} else {
[Link]("D - Insuficiente");
}
© 2025 GMASystem Tecnologia | Página 6 de 43
Spring Boot & Java | GMASystem Tecnologia
// Switch Expression (Java 14+)
String resultado = switch (nota / 10) {
case 10, 9 -> "Excelente";
case 8 -> "Bom";
case 7 -> "Regular";
default -> "Insuficiente";
};
[Link](resultado); // Bom
Laços de Repetição
// For clássico
for (int i = 1; i <= 5; i++) {
[Link]("Iteração: " + i);
}
// While
int contador = 0;
while (contador < 3) {
[Link]("Contador: " + contador);
contador++;
}
// Enhanced For (for-each)
String[] tecnologias = {"Java", "Spring Boot", "API REST"};
for (String tech : tecnologias) {
[Link]("Tecnologia: " + tech);
}
📝 Atividade 1: Fundamentos Java
Pratique os conceitos de variáveis, operadores e estruturas de controle:
1. Crie um programa que calcule a média de 3 notas e exiba o conceito (A, B, C ou D).
2. Implemente um contador de 1 a 100 que exiba apenas os números pares.
3. Crie um programa que leia 5 nomes e os armazene em um array, exibindo-os em ordem
inversa.
4. Calcule o fatorial de um número informado usando um laço while.
© 2025 GMASystem Tecnologia | Página 7 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 2
Orientação a Objetos em Java
A Programação Orientada a Objetos (POO) é um paradigma fundamental no Java. Ela organiza
o software em objetos que encapsulam dados e comportamentos, tornando o código mais
modular, reutilizável e manutenível.
2.1 Classes e Objetos
Uma classe é o molde/blueprint para criar objetos. Um objeto é uma instância de uma classe
com seus próprios valores de atributos.
// Definição da classe
public class Produto {
// Atributos (campos)
private Long id;
private String nome;
private Double preco;
private Integer estoque;
// Construtor padrão
public Produto() {}
// Construtor com parâmetros
public Produto(String nome, Double preco, Integer estoque) {
[Link] = nome;
[Link] = preco;
[Link] = estoque;
}
// Getters e Setters
public Long getId() { return id; }
public void setId(Long id) { [Link] = id; }
public String getNome() { return nome; }
public void setNome(String nome) { [Link] = nome; }
public Double getPreco() { return preco; }
public void setPreco(Double preco) { [Link] = preco; }
// Método de negócio
public boolean possuiEstoque() {
return estoque != null && estoque > 0;
}
// toString
@Override
public String toString() {
return "Produto{nome='" + nome + "', preco=" + preco + "}";
}
}
// Usando a classe
Produto p = new Produto("Notebook", 3500.00, 10);
[Link]([Link]()); // Notebook
© 2025 GMASystem Tecnologia | Página 8 de 43
Spring Boot & Java | GMASystem Tecnologia
[Link]([Link]()); // true
2.2 Herança
Herança permite que uma classe (filha) herde atributos e métodos de outra classe (pai),
promovendo reutilização de código.
// Classe pai
public class Animal {
protected String nome;
protected int idade;
public Animal(String nome, int idade) {
[Link] = nome;
[Link] = idade;
}
public void emitirSom() {
[Link](nome + " emite um som");
}
}
// Classe filha
public class Cachorro extends Animal {
private String raca;
public Cachorro(String nome, int idade, String raca) {
super(nome, idade); // Chama construtor do pai
[Link] = raca;
}
@Override // Polimorfismo
public void emitirSom() {
[Link](nome + " late: Au Au!");
}
}
// Uso
Animal a = new Cachorro("Rex", 3, "Labrador");
[Link](); // Rex late: Au Au!
2.3 Interfaces e Abstração
// Interface define um contrato
public interface Pagavel {
double calcularTotal();
void processar();
default String getDescricao() {
return "Pagamento de " + calcularTotal();
}
}
// Implementação
public class Pedido implements Pagavel {
© 2025 GMASystem Tecnologia | Página 9 de 43
Spring Boot & Java | GMASystem Tecnologia
private List<Produto> itens;
private double desconto;
@Override
public double calcularTotal() {
double subtotal = [Link]()
.mapToDouble(Produto::getPreco).sum();
return subtotal - desconto;
}
@Override
public void processar() {
[Link]("Processando pedido: R$" + calcularTotal());
}
}
2.4 Records (Java 16+)
Records são classes imutáveis para transportar dados, muito usadas em APIs modernas:
// Record — gera automaticamente construtor, getters, equals, hashCode, toString
public record ProdutoDTO(Long id, String nome, Double preco) {}
// Uso
ProdutoDTO dto = new ProdutoDTO(1L, "Notebook", 3500.00);
[Link]([Link]()); // Notebook
[Link]([Link]()); // 3500.0
[Link](dto); // ProdutoDTO[id=1, nome=Notebook, preco=3500.0]
2.5 Generics e Collections
import [Link].*;
// List — sequência ordenada
List<String> nomes = new ArrayList<>();
[Link]("Ana"); [Link]("Bruno"); [Link]("Carlos");
[Link]([Link]::println);
// Map — pares chave-valor
Map<String, Integer> estoque = new HashMap<>();
[Link]("Notebook", 10);
[Link]("Mouse", 50);
[Link]("Teclado", 30);
// Iterando
[Link]((produto, qtd) ->
[Link](produto + ": " + qtd + " unidades")
);
// Set — sem duplicatas
Set<String> categorias = new HashSet<>([Link]("Tech", "Games", "Tech"));
[Link]([Link]()); // 2 — removeu duplicata
© 2025 GMASystem Tecnologia | Página 10 de 43
Spring Boot & Java | GMASystem Tecnologia
2.6 Streams e Lambdas (Java 8+)
Streams permitem processar coleções de forma declarativa e funcional:
List<Produto> produtos = [Link](
new Produto("Notebook", 3500.0, 10),
new Produto("Mouse", 89.0, 50),
new Produto("Monitor", 1200.0, 8),
new Produto("Teclado", 150.0, 30)
);
// Filtrar produtos com preco > 100 e coletar nomes
List<String> caros = [Link]()
.filter(p -> [Link]() > 100)
.map(Produto::getNome)
.sorted()
.collect([Link]());
// [Monitor, Notebook, Teclado]
// Soma de precos
double total = [Link]()
.mapToDouble(Produto::getPreco)
.sum();
[Link]("Total: R$" + total); // 4939.0
// Agrupar por faixa de preco
Map<Boolean, List<Produto>> agrupados = [Link]()
.collect([Link](p -> [Link]() > 500));
📝 Atividade 2: Orientação a Objetos
Crie um mini-sistema de gestão de funcionários usando POO:
5. Crie a classe Funcionario com atributos: id, nome, cargo, salario, dataAdmissao.
6. Crie as subclasses Gerente (com bonusPercentual) e Desenvolvedor (com tecnologias).
7. Implemente a interface Avaliavel com métodos calcularBonus() e obterNivel().
8. Usando Streams, calcule o salário médio, encontre o maior salário e liste apenas
desenvolvedores.
© 2025 GMASystem Tecnologia | Página 11 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 3
Introdução ao Spring Framework
O Spring Framework é o framework Java mais popular do mundo para desenvolvimento
empresarial. Criado por Rod Johnson em 2003, ele resolve problemas comuns como injeção de
dependências, gerenciamento de transações, segurança e muito mais.
3.1 Conceitos Fundamentais
Inversão de Controle (IoC)
No IoC, o framework controla a criação e o ciclo de vida dos objetos, ao invés da aplicação.
Você declara o que precisa, o Spring fornece.
Injeção de Dependências (DI)
DI é a implementação prática do IoC — o Spring injeta automaticamente as dependências que
uma classe precisa:
// Sem DI — acoplamento forte (ruim)
public class PedidoService {
private ProdutoRepository repo = new ProdutoRepository(); // Criação manual
}
// Com DI — desacoplado (ótimo)
@Service
public class PedidoService {
private final ProdutoRepository repo;
// Spring injeta automaticamente
public PedidoService(ProdutoRepository repo) {
[Link] = repo;
}
}
3.2 Container Spring (ApplicationContext)
O ApplicationContext é o coração do Spring — ele gerencia todos os beans (componentes) da
sua aplicação.
// Anotações para criar Beans
@Component // Componente genérico
@Service // Lógica de negócios
@Repository // Acesso a dados
@Controller // Camada web MVC
@RestController // API REST
@Configuration // Configuração Java
3.3 Anotações Principais
© 2025 GMASystem Tecnologia | Página 12 de 43
Spring Boot & Java | GMASystem Tecnologia
ℹ️ As anotações Spring eliminam a necessidade de configuração XML, tornando o código mais
limpo e expressivo.
// @Autowired — injeção de dependência
@RestController
public class ClienteController {
@Autowired // Campo (não recomendado)
private ClienteService service;
// OU melhor: injeção por construtor
private final ClienteService service;
public ClienteController(ClienteService service) {
[Link] = service;
}
}
// @Value — injetar valores de propriedades
@Service
public class EmailService {
@Value("${[Link]}")
private String remetente;
@Value("${[Link]}") // com valor padrão
private int porta;
}
3.4 Configuração com Java
@Configuration
public class AppConfig {
// Criando um Bean manualmente
@Bean
public ModelMapper modelMapper() {
ModelMapper mapper = new ModelMapper();
[Link]().setMatchingStrategy([Link]);
return mapper;
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
© 2025 GMASystem Tecnologia | Página 13 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 4
Spring Boot — Primeiros Passos
Spring Boot é uma evolução do Spring Framework que simplifica radicalmente a configuração e
o início de novos projetos. Com Spring Boot, você tem uma aplicação rodando em minutos, sem
precisar configurar servidores de aplicação externos.
4.1 Por que Spring Boot?
• Auto-configuração: detecta e configura automaticamente dependências
• Servidor embutido: Tomcat/Jetty já incluídos
• Starters: dependências pré-configuradas por funcionalidade
• Actuator: monitoramento e métricas prontos
• DevTools: live reload durante desenvolvimento
4.2 Criando seu Primeiro Projeto
Acesse [Link] e configure:
Project: Maven
Language: Java
Spring Boot: 3.2.x (última versão estável)
Group: [Link]
Artifact: api-demo
Name: api-demo
Package name: [Link]
Packaging: Jar
Java: 21
Dependencies:
- Spring Web
- Spring Data JPA
- H2 Database
- Spring Boot DevTools
- Validation
- Lombok
4.3 Estrutura do Projeto
api-demo/
├── src/
│ ├── main/
│ │ ├── java/com/gmasystem/apidemo/
│ │ │ ├── [Link] (Classe principal)
│ │ │ ├── controller/ (Controllers REST)
│ │ │ ├── service/ (Lógica de negócio)
│ │ │ ├── repository/ (Acesso ao banco)
│ │ │ ├── model/ (Entidades JPA)
© 2025 GMASystem Tecnologia | Página 14 de 43
Spring Boot & Java | GMASystem Tecnologia
│ │ │ ├── dto/ (Data Transfer Objects)
│ │ │ └── config/ (Configurações)
│ │ └── resources/
│ │ ├── [Link] (Configurações)
│ │ └── [Link] (Alternativa YAML)
│ └── test/ (Testes)
└── [Link] (Dependências Maven)
4.4 [Link] — Dependências Maven
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[Link]
<parent>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
</parent>
<groupId>[Link]</groupId>
<artifactId>api-demo</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
4.5 Classe Principal e [Link]
// [Link]
@SpringBootApplication
public class ApiDemoApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}
© 2025 GMASystem Tecnologia | Página 15 de 43
Spring Boot & Java | GMASystem Tecnologia
# [Link]
[Link]=api-demo
[Link]=8080
# H2 Database (em memória para desenvolvimento)
[Link]=jdbc:h2:mem:testdb
[Link]-class-name=[Link]
[Link]=true
# JPA / Hibernate
[Link]-auto=update
[Link]-sql=true
[Link].format_sql=true
4.6 Primeiro Controller
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Olá! API GMASystem funcionando!";
}
@GetMapping("/info")
public Map<String, String> info() {
return [Link](
"empresa", "GMASystem Tecnologia",
"versao", "1.0.0",
"status", "online"
);
}
}
✅ Execute a aplicação e acesse: [Link] — você verá sua primeira resposta
da API!
📝 Atividade 3: Criando seu Primeiro Projeto Spring Boot
Configure e execute seu primeiro projeto Spring Boot:
9. Acesse [Link] e gere o projeto com as dependências: Web, DevTools e Lombok.
10. Importe o projeto na sua IDE e execute a aplicação pela classe principal.
11. Crie um controller /api/saudacao que retorne uma mensagem personalizada com JSON.
12. Adicione um endpoint /api/data-hora que retorne a data e hora atual formatada.
13. Teste os endpoints usando o navegador ou ferramentas como Postman/Insomnia.
© 2025 GMASystem Tecnologia | Página 16 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 5
APIs REST com Spring Boot
REST (Representational State Transfer) é o padrão mais utilizado para criação de APIs web
modernas. Uma API RESTful utiliza os métodos HTTP de forma semântica para realizar
operações em recursos.
5.1 Princípios REST
• Stateless: cada requisição deve conter todas as informações necessárias
• Recursos: tudo é um recurso identificado por uma URL
• Métodos HTTP: GET, POST, PUT, PATCH, DELETE
• Representação: JSON é o formato mais comum
• Códigos de status: HTTP status codes comunicam o resultado
5.2 Métodos HTTP e CRUD
Método Operação CRUD Status Code Exemplo de URL
GET Read (Ler) 200 OK GET /api/produtos
POST Create (Criar) 201 Created POST /api/produtos
PUT Update (Atualizar) 200 OK PUT /api/produtos/1
PATCH Partial Update 200 OK PATCH /api/produtos/1
DELETE Delete (Excluir) 204 No Content DELETE /api/produtos/1
5.3 CRUD Completo de Produtos
Model — [Link]
@Entity
@Table(name = "produtos")
@Data @NoArgsConstructor @AllArgsConstructor @Builder
public class Produto {
@Id
@GeneratedValue(strategy = [Link])
private Long id;
@Column(nullable = false, length = 150)
private String nome;
@Column(nullable = false)
private String descricao;
@Column(nullable = false, precision = 10, scale = 2)
private BigDecimal preco;
© 2025 GMASystem Tecnologia | Página 17 de 43
Spring Boot & Java | GMASystem Tecnologia
@Column(nullable = false)
private Integer estoque;
@Column(nullable = false)
private String categoria;
@CreatedDate
private LocalDateTime criadoEm;
@LastModifiedDate
private LocalDateTime atualizadoEm;
}
Repository — [Link]
@Repository
public interface ProdutoRepository extends JpaRepository<Produto, Long> {
// Spring Data gera SQL automaticamente pelo nome do método
List<Produto> findByCategoria(String categoria);
List<Produto> findByNomeContainingIgnoreCase(String nome);
List<Produto> findByPrecoBetween(BigDecimal min, BigDecimal max);
boolean existsByNome(String nome);
// JPQL customizado
@Query("SELECT p FROM Produto p WHERE [Link] > 0 ORDER BY [Link]")
List<Produto> findDisponiveis();
@Query("SELECT p FROM Produto p WHERE [Link] <= :precoMax AND [Link] =
:cat")
List<Produto> findByPrecoECategoria(
@Param("precoMax") BigDecimal precoMax,
@Param("cat") String categoria
);
}
Service — [Link]
@Service
@Transactional
@RequiredArgsConstructor
public class ProdutoService {
private final ProdutoRepository repository;
@Transactional(readOnly = true)
public List<Produto> listarTodos() {
return [Link]();
}
© 2025 GMASystem Tecnologia | Página 18 de 43
Spring Boot & Java | GMASystem Tecnologia
@Transactional(readOnly = true)
public Produto buscarPorId(Long id) {
return [Link](id)
.orElseThrow(() -> new ResourceNotFoundException(
"Produto não encontrado com id: " + id));
}
public Produto criar(Produto produto) {
if ([Link]([Link]())) {
throw new BusinessException("Produto com este nome já existe");
}
return [Link](produto);
}
public Produto atualizar(Long id, Produto dadosAtualizados) {
Produto existente = buscarPorId(id);
[Link]([Link]());
[Link]([Link]());
[Link]([Link]());
return [Link](existente);
}
public void excluir(Long id) {
Produto produto = buscarPorId(id);
[Link](produto);
}
}
Controller — [Link]
@RestController
@RequestMapping("/api/v1/produtos")
@RequiredArgsConstructor
public class ProdutoController {
private final ProdutoService service;
@GetMapping
public ResponseEntity<List<Produto>> listar(
@RequestParam(required = false) String categoria) {
List<Produto> produtos = categoria != null
? [Link](categoria)
: [Link]();
return [Link](produtos);
}
@GetMapping("/{id}")
public ResponseEntity<Produto> buscar(@PathVariable Long id) {
return [Link]([Link](id));
}
@PostMapping
public ResponseEntity<Produto> criar(@Valid @RequestBody Produto produto) {
Produto criado = [Link](produto);
URI location = ServletUriComponentsBuilder
.fromCurrentRequest().path("/{id}")
.buildAndExpand([Link]()).toUri();
© 2025 GMASystem Tecnologia | Página 19 de 43
Spring Boot & Java | GMASystem Tecnologia
return [Link](location).body(criado);
}
@PutMapping("/{id}")
public ResponseEntity<Produto> atualizar(
@PathVariable Long id, @Valid @RequestBody Produto produto) {
return [Link]([Link](id, produto));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> excluir(@PathVariable Long id) {
[Link](id);
return [Link]().build();
}
}
5.4 Paginação e Ordenação
// Repository com suporte a Pageable
@Repository
public interface ProdutoRepository extends JpaRepository<Produto, Long> {
Page<Produto> findByCategoria(String categoria, Pageable pageable);
}
// Controller com paginação
@GetMapping
public ResponseEntity<Page<Produto>> listar(
@RequestParam(defaultValue = "0") int pagina,
@RequestParam(defaultValue = "10") int tamanho,
@RequestParam(defaultValue = "nome") String ordenarPor) {
Pageable pageable = [Link](pagina, tamanho,
[Link](ordenarPor).ascending());
return [Link]([Link](pageable));
}
// Uso: GET /api/v1/produtos?pagina=0&tamanho=5&ordenarPor=preco
📝 Atividade 4: API REST Completa
Construa uma API REST completa para gerenciamento de clientes:
14. Crie a entidade Cliente com: id, nome, email, cpf, telefone, dataCadastro.
15. Implemente o ClienteRepository com métodos: findByEmail, findByCpf,
findByNomeContaining.
16. Desenvolva o ClienteService com operações: criar, buscarPorId, listar, atualizar, excluir.
17. Crie o ClienteController com endpoints REST completos (GET, POST, PUT, DELETE).
18. Adicione paginação no endpoint de listagem e teste com Postman.
© 2025 GMASystem Tecnologia | Página 20 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 6
Persistência com Spring Data JPA
O Spring Data JPA simplifica drasticamente o acesso a bancos de dados relacionais.
Combinando JPA (Java Persistence API) com Hibernate (o ORM mais popular Java), você pode
persistir e recuperar dados com mínima configuração.
6.1 Configuração com PostgreSQL
Para ambientes de produção, use PostgreSQL ao invés do H2 em memória:
# [Link] para PostgreSQL
[Link]=jdbc:postgresql://localhost:5432/gmasystem_db
[Link]=postgres
[Link]=sua_senha_segura
[Link]-class-name=[Link]
# JPA
[Link]-auto=validate
[Link]-platform=[Link]
[Link]-sql=false
# Pool de conexões (HikariCP — padrão do Spring Boot)
[Link]-pool-size=10
[Link]-idle=2
[Link]-timeout=30000
<!-- [Link] — adicionar dependência PostgreSQL -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
6.2 Mapeamentos JPA Avançados
Relacionamentos
// Um para Muitos — Um Autor tem muitos Livros
@Entity
public class Autor {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private String nome;
@OneToMany(mappedBy = "autor", cascade = [Link])
private List<Livro> livros = new ArrayList<>();
}
@Entity
© 2025 GMASystem Tecnologia | Página 21 de 43
Spring Boot & Java | GMASystem Tecnologia
public class Livro {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private String titulo;
private BigDecimal preco;
@ManyToOne(fetch = [Link])
@JoinColumn(name = "autor_id")
private Autor autor;
}
// Muitos para Muitos — Pedido tem muitos Produtos
@Entity
public class Pedido {
@ManyToMany
@JoinTable(name = "pedido_produto",
joinColumns = @JoinColumn(name = "pedido_id"),
inverseJoinColumns = @JoinColumn(name = "produto_id"))
private Set<Produto> produtos = new HashSet<>();
}
6.3 Migrations com Flyway
O Flyway gerencia as migrações do banco de dados de forma versionada e controlada:
<!-- [Link] -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
-- src/main/resources/db/migration/V1__criar_tabelas.sql
CREATE TABLE clientes (
id BIGSERIAL PRIMARY KEY,
nome VARCHAR(150) NOT NULL,
email VARCHAR(150) NOT NULL UNIQUE,
cpf VARCHAR(14) NOT NULL UNIQUE,
telefone VARCHAR(20),
criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- V2__adicionar_coluna_status.sql
ALTER TABLE clientes ADD COLUMN ativo BOOLEAN DEFAULT TRUE;
6.4 Queries com JPQL e Criteria API
@Repository
public interface ProdutoRepository extends JpaRepository<Produto, Long> {
// JPQL básico
@Query("SELECT p FROM Produto p WHERE [Link] BETWEEN :min AND :max")
List<Produto> buscarPorFaixaPreco(
@Param("min") BigDecimal min,
@Param("max") BigDecimal max);
© 2025 GMASystem Tecnologia | Página 22 de 43
Spring Boot & Java | GMASystem Tecnologia
// Native SQL
@Query(value = "SELECT * FROM produtos WHERE categoria = ?1",
nativeQuery = true)
List<Produto> buscarPorCategoriaSQL(String categoria);
// Projeção — retorna apenas colunas específicas
@Query("SELECT [Link], [Link] FROM Produto p WHERE [Link] > 0")
List<Object[]> listarNomePreco();
// Modifying — UPDATE/DELETE
@Modifying
@Query("UPDATE Produto p SET [Link] = [Link] - :qtd WHERE [Link] = :id")
int decrementarEstoque(@Param("id") Long id, @Param("qtd") int qtd);
}
📝 Atividade 5: Persistência JPA Avançada
Crie um sistema de pedidos com relacionamentos:
19. Modele as entidades: Cliente, Pedido, ItemPedido e Produto com relacionamentos corretos.
20. Configure o PostgreSQL localmente e ajuste o [Link].
21. Crie as migrations Flyway para criar todas as tabelas.
22. Implemente métodos no repository: buscar pedidos por cliente, calcular total por pedido.
23. Crie um endpoint que retorne todos os pedidos de um cliente com seus itens.
© 2025 GMASystem Tecnologia | Página 23 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 7
Validação e Tratamento de Erros
Uma API robusta deve validar dados de entrada e retornar mensagens de erro claras e
estruturadas. O Spring Boot oferece integração com Bean Validation (Jakarta Validation) e
mecanismos poderosos para tratamento global de exceções.
7.1 Bean Validation
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class ClienteRequest {
@NotBlank(message = "Nome é obrigatório")
@Size(min = 3, max = 150, message = "Nome deve ter entre 3 e 150 caracteres")
private String nome;
@NotBlank(message = "Email é obrigatório")
@Email(message = "Email deve ter formato válido")
private String email;
@NotBlank(message = "CPF é obrigatório")
@Pattern(regexp = "\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}",
message = "CPF deve estar no formato 000.000.000-00")
private String cpf;
@NotNull(message = "Preço é obrigatório")
@DecimalMin(value = "0.01", message = "Preço deve ser maior que zero")
@Digits(integer = 8, fraction = 2, message = "Preço inválido")
private BigDecimal preco;
@Min(value = 0, message = "Estoque não pode ser negativo")
private Integer estoque;
@NotNull @Future(message = "Data deve ser no futuro")
private LocalDate dataEntrega;
}
7.2 Global Exception Handler
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
// 404 — Recurso não encontrado
@ExceptionHandler([Link])
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleNotFound(ResourceNotFoundException ex) {
[Link]("Recurso não encontrado: {}", [Link]());
return [Link](HttpStatus.NOT_FOUND, [Link]());
}
© 2025 GMASystem Tecnologia | Página 24 de 43
Spring Boot & Java | GMASystem Tecnologia
// 400 — Erro de validação
@ExceptionHandler([Link])
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
List<String> erros = [Link]().getFieldErrors()
.stream()
.map(f -> [Link]() + ": " + [Link]())
.collect([Link]());
return [Link]()
.status(400)
.mensagem("Dados inválidos")
.erros(erros)
.timestamp([Link]())
.build();
}
// 409 — Conflito de negócio
@ExceptionHandler([Link])
@ResponseStatus([Link])
public ErrorResponse handleBusiness(BusinessException ex) {
return [Link]([Link], [Link]());
}
// 500 — Erro interno
@ExceptionHandler([Link])
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleGeneral(Exception ex) {
[Link]("Erro inesperado", ex);
return [Link](HttpStatus.INTERNAL_SERVER_ERROR,
"Erro interno do servidor");
}
}
7.3 Classe ErrorResponse
@Data @Builder
public class ErrorResponse {
private int status;
private String mensagem;
private List<String> erros;
private LocalDateTime timestamp;
public static ErrorResponse of(HttpStatus status, String mensagem) {
return [Link]()
.status([Link]())
.mensagem(mensagem)
.timestamp([Link]())
.build();
}
}
// Resposta JSON gerada:
// {
// "status": 404,
// "mensagem": "Produto não encontrado com id: 99",
// "erros": null,
© 2025 GMASystem Tecnologia | Página 25 de 43
Spring Boot & Java | GMASystem Tecnologia
// "timestamp": "2025-05-21T14:30:00"
// }
© 2025 GMASystem Tecnologia | Página 26 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 8
Spring Security e JWT
Segurança é um requisito crítico em qualquer API. O Spring Security é o framework padrão para
autenticação e autorização em aplicações Spring. Combinado com JWT (JSON Web Tokens),
fornece um sistema de autenticação stateless ideal para APIs REST.
8.1 Como funciona JWT
Um token JWT é composto de 3 partes separadas por ponto: [Link]
// Header (algoritmo e tipo)
{ "alg": "HS256", "typ": "JWT" }
// Payload (dados do usuário)
{
"sub": "usuario@[Link]",
"iat": 1716300000,
"exp": 1716386400,
"roles": ["ROLE_USER", "ROLE_ADMIN"]
}
// Token gerado (exemplo)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiJ1c3VhcmlvQGVtYWlsLmNvbSIsInJvbGVzIjpbIlJPTEVfVVNFUiJdfQ.
SIGNATURE_HASH
8.2 Dependências
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.3</version>
<scope>runtime</scope>
</dependency>
8.3 JwtService
@Service
public class JwtService {
© 2025 GMASystem Tecnologia | Página 27 de 43
Spring Boot & Java | GMASystem Tecnologia
@Value("${[Link]}")
private String secret;
@Value("${[Link]}") // 24h
private long expiracao;
public String gerarToken(UserDetails user) {
return [Link]()
.subject([Link]())
.issuedAt(new Date())
.expiration(new Date([Link]() + expiracao))
.signWith(getChave())
.compact();
}
public String extrairUsuario(String token) {
return [Link]()
.verifyWith(getChave()).build()
.parseSignedClaims(token)
.getPayload().getSubject();
}
public boolean isTokenValido(String token, UserDetails user) {
String usuario = extrairUsuario(token);
return [Link]([Link]()) && !isExpirado(token);
}
private boolean isExpirado(String token) {
return [Link]().verifyWith(getChave()).build()
.parseSignedClaims(token).getPayload()
.getExpiration().before(new Date());
}
private SecretKey getChave() {
return [Link]([Link](StandardCharsets.UTF_8));
}
}
8.4 Security Configuration
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtFilter jwtFilter;
private final UserDetailsService userDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> [Link]())
.sessionManagement(s -> [Link](
[Link]))
.authorizeHttpRequests(auth -> auth
© 2025 GMASystem Tecnologia | Página 28 de 43
Spring Boot & Java | GMASystem Tecnologia
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.addFilterBefore(jwtFilter, [Link])
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authManager(
AuthenticationConfiguration config) throws Exception {
return [Link]();
}
}
8.5 AuthController — Login e Registro
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthService authService;
@PostMapping("/login")
public ResponseEntity<AuthResponse> login(@Valid @RequestBody LoginRequest req)
{
return [Link]([Link](req));
}
@PostMapping("/registro")
public ResponseEntity<AuthResponse> registro(
@Valid @RequestBody RegistroRequest req) {
return [Link](201).body([Link](req));
}
}
// Requisição: POST /api/auth/login
// Body: { "email": "user@[Link]", "senha": "123456" }
// Resposta:
// { "token": "eyJ...", "tipo": "Bearer", "expiraEm": 86400 }
📝 Atividade 6: Autenticação JWT Completa
Implemente um sistema de autenticação JWT do zero:
24. Crie as entidades Usuario e Role com relacionamento ManyToMany.
25. Implemente o UserDetailsService carregando usuário do banco de dados.
© 2025 GMASystem Tecnologia | Página 29 de 43
Spring Boot & Java | GMASystem Tecnologia
26. Configure o SecurityFilterChain liberando apenas /api/auth/** sem autenticação.
27. Crie o endpoint de registro que valida dados, criptografa senha e retorna JWT.
28. Proteja os endpoints de produto exigindo autenticação e teste com Postman usando Bearer
Token.
© 2025 GMASystem Tecnologia | Página 30 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 9
Testes Automatizados
Testes automatizados são fundamentais para garantir a qualidade do software, facilitar
refatorações e documentar o comportamento esperado do sistema. O Spring Boot oferece
excelente suporte para testes com JUnit 5 e Mockito.
9.1 Tipos de Testes
• Testes Unitários: testam componentes isolados (Service, utils)
• Testes de Integração: testam a interação entre componentes e banco
• Testes de API/E2E: testam os endpoints REST completos
9.2 Testes Unitários com JUnit 5 e Mockito
@ExtendWith([Link])
class ProdutoServiceTest {
@Mock
private ProdutoRepository repository;
@InjectMocks
private ProdutoService service;
@Test
@DisplayName("Deve criar produto com sucesso")
void deveCriarProduto() {
// Arrange
Produto produto = [Link]()
.nome("Notebook")
.preco(new BigDecimal("3500.00"))
.estoque(10).build();
when([Link]("Notebook")).thenReturn(false);
when([Link](any())).thenReturn(produto);
// Act
Produto resultado = [Link](produto);
// Assert
assertNotNull(resultado);
assertEquals("Notebook", [Link]());
verify(repository, times(1)).save(produto);
}
@Test
@DisplayName("Deve lançar exceção para nome duplicado")
void deveLancarExcecaoNomeDuplicado() {
when([Link]("Notebook")).thenReturn(true);
© 2025 GMASystem Tecnologia | Página 31 de 43
Spring Boot & Java | GMASystem Tecnologia
Produto produto = [Link]().nome("Notebook").build();
assertThrows([Link], () -> [Link](produto));
verify(repository, never()).save(any());
}
@Test
@DisplayName("Deve lançar 404 para produto inexistente")
void deveLancarNotFound() {
when([Link](99L)).thenReturn([Link]());
assertThrows([Link],
() -> [Link](99L));
}
}
9.3 Testes de Integração com @SpringBootTest
@SpringBootTest(webEnvironment = [Link].RANDOM_PORT)
@AutoConfigureTestDatabase(replace = [Link])
class ProdutoControllerIT {
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private ProdutoRepository repository;
@BeforeEach
void limpar() { [Link](); }
@Test
void deveListarProdutos() {
[Link]([Link]()
.nome("Teste").preco([Link]).estoque(1).build());
ResponseEntity<List> resposta = restTemplate
.getForEntity("/api/v1/produtos", [Link]);
assertEquals([Link], [Link]());
assertFalse([Link]().isEmpty());
}
@Test
void deveCriarProduto() {
Produto p = [Link]()
.nome("Novo").preco(new BigDecimal("99.99")).estoque(5).build();
ResponseEntity<Produto> resposta = restTemplate
.postForEntity("/api/v1/produtos", p, [Link]);
assertEquals([Link], [Link]());
assertNotNull([Link]().getId());
}
}
© 2025 GMASystem Tecnologia | Página 32 de 43
Spring Boot & Java | GMASystem Tecnologia
9.4 MockMvc — Testes da Camada Web
@WebMvcTest([Link])
class ProdutoControllerTest {
@Autowired MockMvc mvc;
@MockBean ProdutoService service;
@Autowired ObjectMapper mapper;
@Test
void deveRetornar200AoBuscarProduto() throws Exception {
Produto p = [Link]().id(1L).nome("Test").build();
when([Link](1L)).thenReturn(p);
[Link](get("/api/v1/produtos/1")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.nome").value("Test"))
.andExpect(jsonPath("$.id").value(1));
}
@Test
void deveRetornar400ParaDadosInvalidos() throws Exception {
Produto invalido = new Produto(); // sem campos obrigatórios
[Link](post("/api/v1/produtos")
.contentType(MediaType.APPLICATION_JSON)
.content([Link](invalido)))
.andExpect(status().isBadRequest());
}
}
📝 Atividade 7: Cobertura de Testes
Alcance 80% de cobertura de código com testes:
29. Escreva testes unitários para todas as operações do ClienteService usando Mockito.
30. Crie testes de integração para os endpoints do ClienteController com MockMvc.
31. Teste cenários de erro: cliente não encontrado, email duplicado, dados inválidos.
32. Configure o JaCoCo (plugin Maven) para gerar relatório de cobertura de testes.
33. Execute: mvn test jacoco:report e visualize o relatório em target/site/jacoco/
© 2025 GMASystem Tecnologia | Página 33 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 10
Docker e Deploy
Docker é uma plataforma de containerização que permite empacotar sua aplicação e todas suas
dependências em um container portável. Com Docker, você garante que a aplicação funciona
igualmente em qualquer ambiente.
10.1 Dockerfile para Spring Boot
# Multi-stage build para otimizar tamanho da imagem
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY [Link] .
COPY src ./src
RUN ./mvnw clean package -DskipTests
# Imagem final — apenas JRE (menor)
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
# Usuário não-root por segurança
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
COPY --from=builder /app/target/*.jar [Link]
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/[Link]"]
10.2 Docker Compose
version: '3.8'
services:
app:
build: .
container_name: gmasystem-api
ports:
- '8080:8080'
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/gmasystem
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=senha123
- JWT_SECRET=chave-super-secreta-de-256-bits-minimo
depends_on:
db:
condition: service_healthy
networks:
- gmasystem-net
© 2025 GMASystem Tecnologia | Página 34 de 43
Spring Boot & Java | GMASystem Tecnologia
db:
image: postgres:16-alpine
container_name: gmasystem-db
environment:
POSTGRES_DB: gmasystem
POSTGRES_USER: postgres
POSTGRES_PASSWORD: senha123
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- gmasystem-net
volumes:
postgres-data:
networks:
gmasystem-net:
driver: bridge
10.3 Comandos Docker Essenciais
# Build da imagem
docker build -t gmasystem-api:1.0 .
# Subir toda a stack
docker-compose up -d
# Ver logs em tempo real
docker-compose logs -f app
# Parar e remover containers
docker-compose down
# Remover tudo incluindo volumes
docker-compose down -v
# Verificar containers rodando
docker ps
# Acessar shell do container
docker exec -it gmasystem-api sh
10.4 Health Check e Actuator
<!-- Dependência Actuator -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
© 2025 GMASystem Tecnologia | Página 35 de 43
Spring Boot & Java | GMASystem Tecnologia
</dependency>
# [Link]
[Link]=health,info,metrics
[Link]-details=when_authorized
[Link]=true
[Link]=GMASystem API
[Link]=1.0.0
[Link]=GMASystem Tecnologia
# Endpoints disponíveis:
# GET /actuator/health -> Status da aplicação
# GET /actuator/info -> Informações da aplicação
# GET /actuator/metrics -> Métricas de performance
© 2025 GMASystem Tecnologia | Página 36 de 43
Spring Boot & Java | GMASystem Tecnologia
Capítulo 11
Projeto Final — Sistema de E-Commerce
Neste capítulo final, você colocará em prática todos os conceitos aprendidos construindo um
sistema de e-commerce completo com Spring Boot. Este projeto integra: autenticação JWT,
CRUD completo, relacionamentos JPA, validação, testes e Docker.
11.1 Visão Geral do Sistema
✅ Este projeto é o portfólio ideal para apresentar em entrevistas de emprego!
O sistema GMAShop possui as seguintes funcionalidades:
• Autenticação e autorização com JWT e roles (ADMIN, USER)
• Catálogo de produtos com categorias, imagens e busca
• Carrinho de compras por usuário
• Processamento de pedidos com itens e histórico
• Painel administrativo para gestão de produtos e pedidos
• Relatórios de vendas e estoque
11.2 Arquitetura do Sistema
Camadas da Aplicação:
┌─────────────────────────────────────────┐
│ CLIENT (Postman/Frontend) │
└─────────────────┬───────────────────────┘
│ HTTP/JSON
┌─────────────────▼───────────────────────┐
│ CONTROLLER LAYER │
│ AuthController │ ProdutoController │
│ PedidoController │ CarrinhoController │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ SERVICE LAYER │
│ Lógica de negócio, validações, │
│ transformações DTO <-> Entity │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ REPOSITORY LAYER │
│ JpaRepository, queries customizadas │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ PostgreSQL DATABASE │
│ usuarios │ produtos │ pedidos │ itens │
└─────────────────────────────────────────┘
© 2025 GMASystem Tecnologia | Página 37 de 43
Spring Boot & Java | GMASystem Tecnologia
11.3 Modelo de Dados Completo
-- Tabela de usuários
CREATE TABLE usuarios (
id BIGSERIAL PRIMARY KEY,
nome VARCHAR(150) NOT NULL,
email VARCHAR(150) NOT NULL UNIQUE,
senha VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'USER',
ativo BOOLEAN DEFAULT TRUE,
criado_em TIMESTAMP DEFAULT NOW()
);
-- Tabela de categorias
CREATE TABLE categorias (
id BIGSERIAL PRIMARY KEY,
nome VARCHAR(100) NOT NULL UNIQUE,
slug VARCHAR(100) NOT NULL UNIQUE
);
-- Tabela de produtos
CREATE TABLE produtos (
id BIGSERIAL PRIMARY KEY,
nome VARCHAR(200) NOT NULL,
descricao TEXT,
preco NUMERIC(10,2) NOT NULL,
estoque INT NOT NULL DEFAULT 0,
categoria_id BIGINT REFERENCES categorias(id),
ativo BOOLEAN DEFAULT TRUE,
criado_em TIMESTAMP DEFAULT NOW()
);
-- Tabela de pedidos
CREATE TABLE pedidos (
id BIGSERIAL PRIMARY KEY,
usuario_id BIGINT REFERENCES usuarios(id),
status VARCHAR(20) DEFAULT 'PENDENTE',
total NUMERIC(10,2) NOT NULL,
criado_em TIMESTAMP DEFAULT NOW()
);
-- Itens do pedido
CREATE TABLE itens_pedido (
id BIGSERIAL PRIMARY KEY,
pedido_id BIGINT REFERENCES pedidos(id),
produto_id BIGINT REFERENCES produtos(id),
quantidade INT NOT NULL,
preco_unit NUMERIC(10,2) NOT NULL
);
11.4 Serviço de Pedidos Completo
@Service @Transactional @RequiredArgsConstructor
public class PedidoService {
© 2025 GMASystem Tecnologia | Página 38 de 43
Spring Boot & Java | GMASystem Tecnologia
private final PedidoRepository pedidoRepo;
private final ProdutoRepository produtoRepo;
private final UsuarioRepository usuarioRepo;
public Pedido criarPedido(Long usuarioId, List<ItemPedidoRequest> itens) {
Usuario usuario = [Link](usuarioId)
.orElseThrow(() -> new ResourceNotFoundException("Usuário não
encontrado"));
Pedido pedido = new Pedido();
[Link](usuario);
[Link]([Link]);
BigDecimal total = [Link];
List<ItemPedido> itensPedido = new ArrayList<>();
for (ItemPedidoRequest itemReq : itens) {
Produto produto = [Link]([Link]())
.orElseThrow(() -> new ResourceNotFoundException(
"Produto " + [Link]() + " não encontrado"));
if ([Link]() < [Link]()) {
throw new BusinessException(
"Estoque insuficiente para: " + [Link]());
}
ItemPedido item = [Link]()
.produto(produto)
.quantidade([Link]())
.precoUnitario([Link]())
.build();
[Link](item);
total = [Link]([Link]()
.multiply([Link]([Link]())));
// Decrementar estoque
[Link]([Link]() - [Link]());
[Link](produto);
}
[Link](itensPedido);
[Link](total);
return [Link](pedido);
}
public Pedido atualizarStatus(Long pedidoId, StatusPedido novoStatus) {
Pedido pedido = [Link](pedidoId)
.orElseThrow(() -> new ResourceNotFoundException("Pedido não
encontrado"));
[Link](novoStatus);
return [Link](pedido);
}
}
© 2025 GMASystem Tecnologia | Página 39 de 43
Spring Boot & Java | GMASystem Tecnologia
11.5 Documentação com Swagger/OpenAPI
<!-- Dependência SpringDoc -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
// Configuração da documentação
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.info(new Info()
.title("GMASystem API")
.description("API de E-Commerce - GMASystem Tecnologia")
.version("1.0.0")
.contact(new Contact()
.name("GMASystem Tecnologia")
.url("[Link]
.addSecurityItem(new SecurityRequirement().addList("bearerAuth"))
.components(new Components()
.addSecuritySchemes("bearerAuth",
new SecurityScheme().type([Link])
.scheme("bearer").bearerFormat("JWT")));
}
}
// Acessar: [Link]
📝 Atividade 8: Projeto Final — GMAShop
Construa o sistema de e-commerce completo:
34. Configure o projeto com todas as dependências: Web, JPA, Security, Flyway, Actuator,
SpringDoc.
35. Implemente todas as entidades (Usuario, Produto, Categoria, Pedido, ItemPedido) com JPA.
36. Crie as migrations Flyway para estrutura completa do banco de dados.
37. Implemente autenticação JWT completa com registro e login.
38. Desenvolva todos os controllers REST com documentação Swagger.
39. Escreva testes unitários e de integração para PedidoService e PedidoController.
40. Crie o Dockerfile e [Link] e execute a aplicação completa em container.
41. Documente a API no Swagger e exporte a collection para Postman.
© 2025 GMASystem Tecnologia | Página 40 de 43
Spring Boot & Java | GMASystem Tecnologia
Apêndice — Referência Rápida
HTTP Status Codes
• 200 OK — Requisição bem-sucedida
• 201 Created — Recurso criado com sucesso
• 204 No Content — Operação concluída sem corpo na resposta
• 400 Bad Request — Dados inválidos na requisição
• 401 Unauthorized — Não autenticado
• 403 Forbidden — Autenticado mas sem permissão
• 404 Not Found — Recurso não encontrado
• 409 Conflict — Conflito com estado atual (duplicata)
• 422 Unprocessable Entity — Erro de validação de negócio
• 500 Internal Server Error — Erro interno do servidor
Anotações Spring Boot Mais Usadas
// CLASSES
@SpringBootApplication // Ponto de entrada da aplicação
@RestController // Controller REST
@Service // Camada de serviço
@Repository // Camada de repositório
@Entity // Entidade JPA
@Configuration // Classe de configuração
@Component // Componente genérico Spring
// MAPEAMENTO WEB
@RequestMapping("/api") // Mapeamento base
@GetMapping("/") // GET
@PostMapping("/") // POST
@PutMapping("/{id}") // PUT
@PatchMapping("/{id}") // PATCH
@DeleteMapping("/{id}") // DELETE
@PathVariable // Variável da URL
@RequestParam // Parâmetro de query string
@RequestBody // Corpo da requisição JSON
@Valid // Ativar validação
// INJEÇÃO DE DEPENDÊNCIAS
@Autowired // Injeção automática
@Value("${prop}") // Injetar propriedade
@Bean // Declarar bean
// JPA
@Id // Chave primária
@GeneratedValue // Auto increment
@Column // Configurar coluna
@OneToMany // Relacionamento 1:N
@ManyToOne // Relacionamento N:1
@ManyToMany // Relacionamento N:N
@Transactional // Controle de transação
@Query // JPQL customizado
© 2025 GMASystem Tecnologia | Página 41 de 43
Spring Boot & Java | GMASystem Tecnologia
Ferramentas Recomendadas
• IntelliJ IDEA — IDE mais completa para Spring Boot
• Postman / Insomnia — Testar APIs REST
• DBeaver — Cliente gráfico para banco de dados
• Docker Desktop — Gerenciar containers
• Git + GitHub — Controle de versão
• Maven / Gradle — Gerenciamento de dependências
Recursos de Aprendizado
• [Link]/guides — Guias oficiais do Spring
• [Link] — Tutoriais avançados Spring/Java
• [Link] — Documentação oficial
• [Link] — Comunidade de dúvidas
• [Link]/spring-projects — Projetos de exemplo
© 2025 GMASystem Tecnologia | Página 42 de 43
Spring Boot & Java | GMASystem Tecnologia
GMASystem Tecnologia
Transformando ideias em soluções tecnológicas
© 2025 GMASystem Tecnologia. Todos os direitos reservados.
© 2025 GMASystem Tecnologia | Página 43 de 43