📚 Pré-requisitos Teóricos: este projeto aplica conceitos ensinados em Especialização em Backend com Java e Spring Boot. Recomendado revisar antes de começar.
v2.0`
Neste projeto, construiremos um sistema completo de “Lista de Tarefas” (To-Do List), demonstrando como diferentes aplicações cliente podem consumir uma única fonte de dados central (API). A arquitetura final será:
flowchart TD
subgraph "🎛️ Gerenciamento e Automação"
Script["🛠️ Painel de Controle<br>(listadetarefas-painel.ps1)"]
end
subgraph "📱 Clientes (Frontends)"
Web["💻 Frontend Web<br>(Angular)"]
Desktop["🖥️ Frontend Desktop<br>(JavaFX)"]
Mobile["📱 Frontend Mobile<br>(Android)"]
end
subgraph "⚙️ Serviços (Backend)"
API["🔌 Backend API<br>(Spring Boot)"]
DB[("🗄️ Banco de Dados<br>Em Memória H2")]
end
%% Conexões de Dados
Web -->|HTTP/JSON| API
Desktop -->|HTTP/JSON| API
Mobile -->|HTTP/JSON| API
API --- DB
%% Conexões de Gerenciamento
Script -.->|Gerencia| API
Script -.->|Gerencia| Web
Script -.->|Gerencia| Desktop
Script -.->|Gerencia| Mobile
%% Estilização
style Script fill:#f9f,stroke:#333,stroke-width:2px
style API fill:#dfd,stroke:#333,stroke-width:2px
style DB fill:#def,stroke:#333,stroke-width:2px
style Web fill:#ffe,stroke:#333,stroke-width:2px
—–`
listadetarefas-api)Objetivo: Criar o serviço central que irá gerenciar os dados das tarefas, servindo como a única fonte de verdade para todos os clientes.
MavenJavabr.com.cursolistadetarefas-apibr.com.curso.listadetarefas.apiDependencies):
Spring Web, Spring Data JPA, H2 Database, Lombok.Após criar o projeto, sua estrutura de pastas principal será:
listadetarefas-api/
├── src/
│ └── main/
│ ├── java/
│ │ └── br/com/curso/listadetarefas/api/
│ │ └── ListadetarefasApiApplication.java
│ └── resources/
│ └── application.properties
└── pom.xml
Abra o arquivo src/main/resources/application.properties e substitua seu conteúdo por este:
# Permite que o servidor aceite conexões de qualquer endereço de rede da máquina.
server.address=0.0.0.0
# Habilita o console web do H2
spring.h2.console.enabled=true
# Define o caminho para acessar o console
spring.h2.console.path=/h2-console
# Configurações do Datasource para H2
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
Vamos definir a estrutura da nossa tabela de tarefas.
erDiagram
TB_TAREFAS {
BIGINT id PK "Auto-incremento"
VARCHAR descricao "Descrição da tarefa"
BOOLEAN concluida "Status de conclusão"
}
src/main/java/br/com/curso/listadetarefas/api, crie um novo pacote chamado tarefa.tarefa, crie a classe Tarefa.java.// src/main/java/br/com/curso/listadetarefas/api/tarefa/Tarefa.java
package br.com.curso.listadetarefas.api.tarefa;
import jakarta.persistence.*;
import lombok.Data;
@Data
@Entity
@Table(name = "tb_tarefas")
public class Tarefa {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String descricao;
private boolean concluida;
}
api/
└── src/main/java/br/com/curso/listadetarefas/api/
├── tarefa/
│ └── Tarefa.java # <- Arquivo criado
└── ListadetarefasApiApplication.java
Agora, criaremos as classes que formam a arquitetura da nossa API: Repository (acesso a dados), Service (regras de negócio) e Controller (endpoints HTTP).
classDiagram
direction LR
TarefaController ..> TarefaService : Usa
TarefaService ..> TarefaRepository : Usa
TarefaRepository ..> Tarefa : Gerencia
class TarefaController {
+List~Tarefa~ listarTarefas()
+Tarefa criarTarefa(Tarefa tarefa)
+ResponseEntity~Tarefa~ atualizarTarefa(Long id, Tarefa tarefa)
+ResponseEntity~Void~ deletarTarefa(Long id)
}
class TarefaService {
+List~Tarefa~ listarTodas()
+Tarefa criar(Tarefa tarefa)
+Tarefa atualizar(Long id, Tarefa tarefa)
+void deletar(Long id)
}
class TarefaRepository {
<<Interface>>
}
class Tarefa {
+Long id
+String descricao
+boolean concluida
}
tarefa, crie as seguintes classes e interfaces:TarefaRepository.java
package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TarefaRepository extends JpaRepository<Tarefa, Long> {
}
TarefaService.java
package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TarefaService {
@Autowired
private TarefaRepository tarefaRepository;
public List<Tarefa> listarTodas() { return tarefaRepository.findAll(); }
public Tarefa criar(Tarefa tarefa) { return tarefaRepository.save(tarefa); }
public Tarefa atualizar(Long id, Tarefa tarefaAtualizada) {
return tarefaRepository.findById(id)
.map(tarefaExistente -> {
tarefaExistente.setDescricao(tarefaAtualizada.getDescricao());
tarefaExistente.setConcluida(tarefaAtualizada.isConcluida());
return tarefaRepository.save(tarefaExistente);
}).orElseThrow(() -> new RuntimeException("Tarefa não encontrada com o id: " + id));
}
public void deletar(Long id) {
if (!tarefaRepository.existsById(id)) {
throw new RuntimeException("Tarefa não encontrada com o id: " + id);
}
tarefaRepository.deleteById(id);
}
}
TarefaController.java
package br.com.curso.listadetarefas.api.tarefa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/tarefas")
@CrossOrigin(origins = "*")
public class TarefaController {
@Autowired
private TarefaService tarefaService;
@GetMapping
public List<Tarefa> listarTarefas() { return tarefaService.listarTodas(); }
@PostMapping
public Tarefa criarTarefa(@RequestBody Tarefa tarefa) { return tarefaService.criar(tarefa); }
@PutMapping("/{id}")
public ResponseEntity<Tarefa> atualizarTarefa(@PathVariable Long id, @RequestBody Tarefa tarefa) {
try {
Tarefa atualizada = tarefaService.atualizar(id, tarefa);
return ResponseEntity.ok(atualizada);
} catch (RuntimeException e) {
return ResponseEntity.notFound().build();
}
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deletarTarefa(@PathVariable Long id) {
try {
tarefaService.deletar(id);
return ResponseEntity.noContent().build();
} catch (RuntimeException e) {
return ResponseEntity.notFound().build();
}
}
}
api/
└── src/main/java/br/com/curso/listadetarefas/api/
├── tarefa/
│ ├── Tarefa.java
│ ├── TarefaController.java
│ ├── TarefaRepository.java
│ └── TarefaService.java
└── ListadetarefasApiApplication.java
flowchart LR
User(["👤 Usuário<br>(via Cliente)"])
subgraph Sistema_Tarefas ["⚙️ Sistema de Tarefas"]
UC1(("Listar Tarefas"))
UC2(("Adicionar Tarefa"))
UC3(("Atualizar Tarefa"))
UC4(("Deletar Tarefa"))
end
User --> UC1
User --> UC2
User --> UC3
User --> UC4
style User fill:#e1f5fe,stroke:#01579b,stroke-width:2px
style Sistema_Tarefas fill:#f5f5f5,stroke:#9e9e9e,stroke-dasharray: 5 5
Execute a Aplicação:
ListadetarefasApiApplication.java../mvnw spring-boot:runTeste com Cliente REST (ex: Postman):
http://localhost:8080/api/tarefas e verifique todas as operações de CRUD (GET, POST, PUT, DELETE) como detalhado no guia anterior.Teste com o Console H2:
http://localhost:8080/h2-console no navegador.jdbc:h2:mem:testdbsaSELECT * FROM TB_TAREFAS; para ver os dados diretamente no banco.—`
No seu editor/IDE, abra a pasta deste projeto (File > Open Folder) ou navegue via terminal:
cd javaweb_tarefas_01_rest
./mvnw spring-boot:run
./mvnw test
[!TIP] Dica para execução a partir da raiz do repositório: Se você abriu o repositório completo no VS Code, basta navegar até a pasta antes de executar: cd proj_aplicacoes_full_stack/projetos/javaweb_tarefas_01_rest