Linguagem e Técnica de Programação II – Aula 05
Backend com Node.js e Express — do servidor mínimo ao CRUD completo
Apresentação
Esta aula dá continuidade ao estudo do backend iniciado com o servidor “Hello World”. Aqui o estudante evolui do conceito de rota simples para a construção de uma API funcional com operações de Criar, Ler, Atualizar e Remover dados (CRUD) — o padrão mais comum de backend usado na indústria.
Objetivos da aula
Ao final desta aula, o estudante deve ser capaz de:
- explicar a relação entre os métodos HTTP e as operações CRUD;
- ler e interpretar um servidor Express com múltiplas rotas;
- entender o papel do middleware
express.json(); - entender o uso de
req.paramsereq.body; - reconhecer códigos de status HTTP (200, 201, 404) e por que eles importam;
- (opcional) executar e testar as rotas usando um navegador ou uma ferramenta como Insomnia/Postman/Thunder Client.
Metodologia
Aula expositivo-demonstrativa, com o professor codificando ao vivo. Recomenda-se testar cada rota logo após criá-la, para que o efeito seja visível imediatamente — isso ajuda a manter a atenção de turmas mais dispersas.
Recursos necessários
- Node.js instalado;
- Editor de código (VS Code);
- Extensão ou aplicativo para testar rotas (Thunder Client no VS Code, Postman, Insomnia, ou até o próprio navegador para rotas GET).
1. Relembrando o essencial
Backend é a parte do sistema que recebe requisições, processa dados e devolve respostas. Node.js permite escrever esse backend em JavaScript; Express simplifica a criação das rotas.
2. HTTP e a relação com CRUD
CRUD é a sigla para as quatro operações básicas que qualquer sistema realiza sobre dados: Create (criar), Read (ler), Update (atualizar), Delete (remover). No mundo das APIs Web, cada uma dessas operações costuma ser associada a um método HTTP:
| Operação CRUD | Método HTTP | Finalidade |
| Create | POST | Criar um novo recurso |
| Read | GET | Ler um ou mais recursos |
| Update | PUT | Atualizar um recurso existente |
| Delete | DELETE | Remover um recurso |
Explicação detalhada: essa é a convenção usada por APIs no padrão REST, e é a mais encontrada no mercado. O MDN Web Docs (Mozilla) define GET como o método usado para solicitar uma representação de um recurso, sem alterá-lo, e POST como o método usado para enviar dados a serem processados pelo servidor — geralmente criando um novo recurso.
3. Preparando o projeto
mkdir backend-alunos
cd backend-alunos
npm init -y
npm install express
Arquivo server.js (usado em todos os exemplos seguintes).
4. Middleware: o que é e por que precisamos dele agora
Middleware é uma função que “intercepta” a requisição antes dela chegar à rota final. Para que o Express consiga ler dados enviados no corpo da requisição (por exemplo, um novo aluno enviado via POST), é preciso ativar o middleware embutido express.json().
const express = require('express');
const app = express();
app.use(express.json()); // permite ler JSON enviado no corpo da requisição
app.listen(3000, () => {
console.log('Servidor rodando em http://localhost:3000');
});
Explicação detalhada: sem essa linha, req.body chegaria undefined nas rotas POST e PUT. Esse é um erro comum e um bom ponto de atenção para a turma.
5. Nossa “base de dados” (simplificada)
Para não depender de banco de dados nesta aula, usamos um array em memória. Ele existe apenas enquanto o servidor está rodando; ao reiniciar, os dados voltam ao estado inicial. Essa limitação deve ser dita claramente aos alunos, para não gerar a falsa ideia de que isso é o que se usa em produção.
let alunos = [
{ id: 1, nome: "Maria Silva", turma: "3º Ano" },
{ id: 2, nome: "João Souza", turma: "3º Ano" }
];
6. CRUD completo — passo a passo
6.1 READ (listar todos) — GET /alunos
app.get('/alunos', (req, res) => {
res.json(alunos);
});
Explicação: essa rota apenas devolve o array inteiro em formato JSON. É a operação mais simples do CRUD.
6.2 READ (buscar um específico) — GET /alunos/:id
app.get('/alunos/:id', (req, res) => {
const id = Number(req.params.id);
const aluno = alunos.find(a => a.id === id);
if (!aluno) {
return res.status(404).json({ erro: "Aluno não encontrado" });
}
res.json(aluno);
});
Explicação detalhada:
:idna rota é um parâmetro de rota; o valor digitado na URL fica disponível emreq.params.id;- como tudo que vem da URL chega como texto, convertemos para número com
Number(...); - o status
404(Not Found) é devolvido quando o aluno não existe — devolver sempre200mesmo em caso de erro é uma prática ruim e vale a pena mostrar isso à turma.
6.3 CREATE — POST /alunos
app.post('/alunos', (req, res) => {
const novoAluno = {
id: alunos.length + 1,
nome: req.body.nome,
turma: req.body.turma
};
alunos.push(novoAluno);
res.status(201).json(novoAluno);
});
Explicação detalhada:
req.bodycontém os dados enviados pelo cliente (graças ao middlewareexpress.json()configurado antes);- o status
201(Created) indica que um novo recurso foi criado com sucesso — diferente do200genérico; - a geração de
idaqui é simplificada (length + 1), o que é aceitável para fins didáticos, mas não é seguro em sistemas reais (pode gerar IDs duplicados após exclusões). Vale comentar essa limitação com a turma.
6.4 UPDATE — PUT /alunos/:id
app.put('/alunos/:id', (req, res) => {
const id = Number(req.params.id);
const aluno = alunos.find(a => a.id === id);
if (!aluno) {
return res.status(404).json({ erro: "Aluno não encontrado" });
}
aluno.nome = req.body.nome;
aluno.turma = req.body.turma;
res.json(aluno);
});
Explicação detalhada: a lógica combina duas coisas já vistas: buscar por id (como no GET individual) e sobrescrever os dados usando req.body (como no POST).
6.5 DELETE — DELETE /alunos/:id
app.delete('/alunos/:id', (req, res) => {
const id = Number(req.params.id);
const existe = alunos.some(a => a.id === id);
if (!existe) {
return res.status(404).json({ erro: "Aluno não encontrado" });
}
alunos = alunos.filter(a => a.id !== id);
res.status(204).send();
});
Explicação detalhada: o status 204 (No Content) é o padrão para exclusões bem-sucedidas — o servidor confirma a ação, mas não precisa devolver nenhum dado.
7. Arquivo completo (server.js)
const express = require('express');
const app = express();
app.use(express.json());
let alunos = [
{ id: 1, nome: "Maria Silva", turma: "3º Ano" },
{ id: 2, nome: "João Souza", turma: "3º Ano" }
];
// READ - listar todos
app.get('/alunos', (req, res) => {
res.json(alunos);
});
// READ - buscar um
app.get('/alunos/:id', (req, res) => {
const id = Number(req.params.id);
const aluno = alunos.find(a => a.id === id);
if (!aluno) return res.status(404).json({ erro: "Aluno não encontrado" });
res.json(aluno);
});
// CREATE
app.post('/alunos', (req, res) => {
const novoAluno = {
id: alunos.length + 1,
nome: req.body.nome,
turma: req.body.turma
};
alunos.push(novoAluno);
res.status(201).json(novoAluno);
});
// UPDATE
app.put('/alunos/:id', (req, res) => {
const id = Number(req.params.id);
const aluno = alunos.find(a => a.id === id);
if (!aluno) return res.status(404).json({ erro: "Aluno não encontrado" });
aluno.nome = req.body.nome;
aluno.turma = req.body.turma;
res.json(aluno);
});
// DELETE
app.delete('/alunos/:id', (req, res) => {
const id = Number(req.params.id);
const existe = alunos.some(a => a.id === id);
if (!existe) return res.status(404).json({ erro: "Aluno não encontrado" });
alunos = alunos.filter(a => a.id !== id);
res.status(204).send();
});
app.listen(3000, () => {
console.log('Servidor rodando em http://localhost:3000');
});
8. Testando as rotas
Como rotas POST, PUT e DELETE não podem ser testadas digitando a URL no navegador, é preciso uma ferramenta de teste de API. Sugestões simples: Thunder Client (extensão do VS Code) ou Postman.
Exemplos de teste:
| Ação | Método | URL | Corpo (JSON) |
| Listar alunos | GET | /alunos | — |
| Buscar aluno 1 | GET | /alunos/1 | — |
| Criar aluno | POST | /alunos | { "nome": "Ana", "turma": "3º Ano" } |
| Atualizar aluno 1 | PUT | /alunos/1 | { "nome": "Maria Editada", "turma": "3º Ano" } |
| Remover aluno 2 | DELETE | /alunos/2 | — |
9. Exemplo extra — Middleware personalizado (log de requisições)
Além do middleware pronto (express.json()), é possível criar o próprio. Este exemplo registra no console todas as requisições recebidas:
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
Explicação detalhada: next() é essencial — sem ele, a requisição fica “presa” nesse middleware e nunca chega até a rota. Esse exemplo é opcional, mas ajuda a mostrar visualmente, no console, cada requisição chegando ao servidor conforme a turma testa as rotas.
10. Exemplo extra — Nodemon (conveniência, não obrigatório)
Por padrão, é preciso reiniciar o servidor manualmente (Ctrl+C e node server.js de novo) a cada alteração no código. O pacote nodemon reinicia automaticamente:
npm install -D nodemon
npx nodemon server.js
Vantagens do modelo apresentado
- reaproveita a mesma linguagem (JavaScript) já usada no front-end;
- Express reduz drasticamente a quantidade de código necessária;
- a lógica de CRUD é a mesma usada, em essência, em sistemas reais de mercado.
Desvantagens / limitações do exemplo didático
- os dados não são persistidos (somem ao reiniciar o servidor) — em um sistema real, isso seria feito com um banco de dados (fora do escopo desta aula);
- não há validação de dados nem tratamento de erros mais robusto;
- não há autenticação — qualquer pessoa poderia chamar qualquer rota.
Encerramento
Ao final desta aula, o estudante deve reconhecer que um backend, por mais simples que seja, geralmente gira em torno das mesmas quatro operações (CRUD), mapeadas para métodos HTTP padronizados. Esse entendimento é a base para qualquer tecnologia de backend que o estudante venha a usar no futuro, independentemente da linguagem.
Referências utilizadas
- Express (repositório oficial). Descrição do framework como minimalista e focado em rotas. Disponível em: github.com/expressjs/express.
- Node.js (site oficial). Descrição como runtime JavaScript baseado no motor V8. Disponível em: nodejs.org.
- MDN Web Docs (Mozilla). Definição dos métodos de requisição HTTP (GET, POST, entre outros). Disponível em: developer.mozilla.org/docs/Web/HTTP/Methods.
Fim da aula 05
