Atividade MVC e Spring Boot (EstanteWeb)
Disciplina: Programação para Web 3
Assunto: Organização de aplicações Web (MVC, Spring Boot, Controllers e rotas)
Professor: Prof. Me. Danilo Bueno
Grupos: duplas
Duração: 4 aulas de 50 minutos (em sala)
Importante
Antes de começar, leia o material de apoio sobre MVC e Spring Boot. É imprescindível ler antes de codar: a atividade aplica exatamente os conceitos do material. Se tiver dúvidas, releia, pergunte ao professor ou aos colegas. Você também pode consultar os slides da aula.
Contextualização
A EstanteWeb é um sebo de bairro que vende livros usados. O acervo inteiro vive num caderno: quando um cliente telefona perguntando se determinado título existe, alguém folheia páginas à mão. A dona decidiu levar a loja para a Web e contratou você e sua dupla como a equipe de desenvolvimento.
O sistema será construído do jeito certo desde o início: organizado. Nesta primeira etapa, a missão da dupla é colocar o servidor da loja no ar e estruturar a aplicação em camadas: controllers atendendo rotas e um modelo guardando os primeiros livros do acervo.
Este é o começo de verdade: o projeto que vocês criam hoje é a fundação do sistema da EstanteWeb.
Como começar
Cada dupla precisa de uma máquina com:
- Java (JDK) 21: a versão da linguagem é fixa na disciplina. Se precisar instalar, use uma distribuição gratuita como o Eclipse Temurin 21.
- VS Code com a extensão Extension Pack for Java (instale pela aba de extensões).
- Acesso ao site
https://start.spring.io(Spring Initializr): é lá que o projeto nasce, na Missão 1.
Antes de começar, verifique as ferramentas. Abra o terminal e rode os comandos abaixo; cada um deve responder sem erro de “comando não encontrado”:
java -version # deve exibir a versão 21 (ex.: openjdk 21.x)
code --version # confirma o VS Code no PATH (ou abra pelo menu normalmente)
mvn -version # opcional: o projeto traz o Maven wrapper (mvnw), que dispensa o Maven instalado
Se java -version mostrar outra versão (8, 11, 17…), instale o JDK 21 antes de seguir. Chame o professor se travar aqui: nada da atividade funciona sem o Java certo.
Não há código para copiar: o projeto será gerado pelo Spring Initializr na Missão 1, com estas opções:
| Campo | Valor |
|---|---|
| Project | Maven |
| Language | Java |
| Spring Boot | versão estável sugerida |
| Group | br.com.estanteweb |
| Artifact | estanteweb |
| Package name | br.com.estanteweb |
| Java | 21 |
| Dependencies | Spring Web |
Guarde bem este projeto ao final da atividade (a pasta inteira): ele é o sistema da loja, e é sobre ele que o trabalho continua.
Como funciona
- A atividade é feita em dupla, mas as entregas no Moodle são individuais.
- As missões são incrementais: cada uma constrói sobre a anterior, siga na ordem.
- Ao final de cada missão, teste no navegador (e, quando indicado, no DevTools) antes de seguir.
- Responda, no caminho, às perguntas em destaque (marcadas com
>). Elas voltam no questionário do Moodle.
Cronograma
| Aula | Foco | Missões |
|---|---|---|
| 1 | Ambiente, Initializr e servidor no ar | Missão 1 |
| 2 | Primeiras rotas | Missão 2 |
| 3 | O modelo: os livros do acervo | Missão 3 |
| 4 | Separação em camadas + desafio | Missão 4 |
Missão 1: O servidor da loja no ar
Objetivo: gerar o projeto, abri-lo na IDE e ver o servidor respondendo.
1.1. Acesse https://start.spring.io e preencha exatamente as opções da tabela em “Como começar” (confira o Package name br.com.estanteweb, o Java 21 e a dependência Spring Web). Clique em Generate, descompacte o .zip numa pasta sua e abra a pasta do projeto no VS Code (File, Open Folder).
1.2. Localize a classe EstantewebApplication e execute a aplicação (botão Run que a extensão Java mostra sobre o método main, ou ./mvnw spring-boot:run no terminal, na pasta do projeto). No console, encontre e anote a linha que indica em qual porta o servidor subiu.
1.3. Acesse http://localhost:8080 no navegador. Você verá a Whitelabel Error Page. Abra o DevTools (F12 → Network), recarregue e registre o código de status dessa resposta.
O servidor acabou de subir e a página inicial mostra um erro 404. Isso significa que a aplicação está quebrada? Explique o que esse 404 diz sobre o servidor e sobre a rota
/.
Missão 2: As primeiras rotas
Objetivo: criar o primeiro controller e ensinar o servidor a responder.
2.1. No pacote br.com.estanteweb (ao lado da classe EstantewebApplication), crie a classe PaginaController anotada com @RestController, com um método mapeado em / (via @GetMapping) retornando uma mensagem de boas-vindas da loja, por exemplo: "EstanteWeb: livros usados com história". Reinicie a aplicação e confira no navegador que o 404 da Missão 1 virou 200 com a sua mensagem (abra novamente o devtools para checar o código).
2.2. No mesmo controller, crie a rota /sobre, retornando uma frase que descreva a loja. Teste no navegador.
2.3. Experimente o erro clássico: crie temporariamente um segundo método também mapeado em /sobre e tente rodar a aplicação. Observe o que acontece no console, registre a mensagem de erro e então desfaça (apague o método duplicado).
O que aconteceu quando duas rotas iguais existiram ao mesmo tempo: o erro apareceu ao acessar a página ou ao subir a aplicação? Por que esse comportamento é melhor do que descobrir o problema só quando um cliente acessasse?
Missão 3: Os livros entram em cena
Objetivo: criar o modelo do acervo e exibi-lo numa rota.
3.1. Crie a classe Livro (o modelo), com os atributos titulo, autor, ano e preco, construtor e getters. Ela não deve ter nada de HTTP: nenhuma anotação de rota.
3.2. Crie a classe LivroController com a rota /livros. Por enquanto, dentro do controller, monte uma List<Livro> com os 5 primeiros livros do acervo (invente títulos de livros usados) e retorne uma String listando título, autor e preço de cada um, percorrendo a lista com um laço.
Ao acessar http://localhost:8080/livros, a resposta deve seguir este formato (os títulos serão os que sua dupla inventou, não estes):
Acervo EstanteWeb: Dom Casmurro, de Machado de Assis (R$ 24.9) | A Hora da Estrela, de Clarice Lispector (R$ 22.0) | ...
3.3. Acrescente a rota /livros/total, que retorna quantos livros existem no acervo (use o tamanho da lista; cuidado para não escrever o número “na mão”).
Ao acessar http://localhost:8080/livros/total, a resposta deve seguir este formato (o número deve bater com a quantidade de livros que você colocou na lista):
O acervo tem 5 livros.
A classe
Livroficou sem nenhuma anotação do Spring. O que ela representa no MVC, e por que ela não deve saber nada sobre rotas ou HTTP?
Missão 4: Separando as camadas
Objetivo: tirar os dados de dentro do controller e concluir a organização MVC da semana.
4.1. Crie a classe LivroRepository, com a lista de livros da Missão 3 movida para dentro dela e um método listarTodos() que a retorna. O LivroController passa a criar um LivroRepository e a usá-lo; nenhuma lista de livros pode sobrar no controller.
4.2. Adicione ao repositório o método contarLivros() e faça a rota /livros/total usá-lo. Confira no navegador que as duas rotas continuam funcionando exatamente como antes da mudança.
4.3. Adicione ao acervo um livro cujo título contenha uma tag HTML, por exemplo O <b>Grande</b> Gatsby, e observe como ele aparece na rota /livros.
4.4. Desafio (opcional): crie a rota /livros/html com produces = "text/html", retornando o acervo como uma lista HTML (<ul>/<li>). Compare no navegador com a rota /livros e, no DevTools, compare o Content-Type das duas respostas.
Na rota
/livros(texto puro), a tag<b>do título apareceu escrita na tela; na/livros/html, o navegador a interpretou. Qual header da resposta explica essa diferença de comportamento?
Entrega individual
Cada integrante da dupla deve, individualmente, no Moodle:
- Responder o questionário da semana (perguntas de reflexão sobre a atividade).
- Enviar o projeto compactado em
.zip(a pasta do projeto sem a subpastatarget/, que é gerada na compilação e pesa à toa).