Exemplos Práticos com Spring MVC

Neste artigo, exploramos três aplicações web construídas com Spring MVC, demonstrando a interação entre o cliente e o servidor e a organização do código em camadas.

Definição da Interface entre Cliente e Servidor

Definir uma interface de comunicação (API) clara é fundamental no desenvolvimento web moderno. Ela descreve como o cliente (frontend) deve fazer requisições ao servidor (backend) e quais respostas esperar. Em ambientes com times de desenvolvimento separados, essa especificação é documentada em um documento de API, que serve como manual de operação e normalmente é fornecido pelo time de backend.

1. Calculadora Simples

Análise do Requisito

Desenvolver uma calculadora de adição que receba dois números inteiros do cliente e retorne o resultado da soma.

Definição da API

  • Caminho: /calculadora/soma
  • Método: POST
  • Parâmetros: valorA, valorB (no corpo da requisição como formulário)
  • Resposta (Content-Type: text/html): Uma página HTML simples com o cálculo.

Código do Frontend (calc.html)

<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>Calculadora Web</title>
</head>
<body>
    <h2>Calculadora de Soma</h2>
    <form action="/calculadora/soma" method="post">
        Primeiro Número: <input name="valorA" type="number" required><br><br>
        Segundo Número: <input name="valorB" type="number" required><br><br>
        <input type="submit" value="Calcular Soma">
    </form>
</body>
</html>

Código do Backend

package com.exemplo.demo.controlador;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/calculadora")
public class ControladorCalculadora {

    @PostMapping("/soma")
    public String calcularSoma(@RequestParam int valorA, @RequestParam int valorB) {
        int resultado = valorA + valorB;
        return "<h3>O resultado de " + valorA + " + " + valorB + " é: <strong>" + resultado + "</strong></h3>";
    }
}

Ao iniciar a aplicação, a calculadora pode ser acessada em http://localhost:8080/calc.html.

2. Sistema de Login de Usuário

Definição do Requisito

Um sistema onde o usuário insere credenciais. O backend as valida; se corretas, armazena o estado da sessão e redireciona para uma página inicial que exibe o nome do usuário logado.

Definição das APIs

Endpoint de Autenticação
  • Caminho: /api/autenticacao
  • Método: POST
  • Corpo: {"login": "usuario", "senha": "senha123"}
  • Resposta: true ou false (boolean).
Endpoint para Obter Usuário Logado
  • Caminho: /api/usuario-logado
  • Método: GET
  • Resposta: O login do usuário autenticado ou uma string vazia.

Código do Backend

package com.exemplo.demo.controlador;

import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.*;
import java.util.Objects;

@RestController
@RequestMapping("/api")
public class ControladorAutenticacao {

    // Simulação de banco de dados
    private static final String USUARIO_VALIDO = "admin";
    private static final String SENHA_VALIDA = "admin123";

    @PostMapping("/autenticacao")
    public boolean autenticar(@RequestParam String login,
                              @RequestParam String senha,
                              HttpSession sessao) {
        if (Objects.equals(login, USUARIO_VALIDO) && Objects.equals(senha, SENHA_VALIDA)) {
            sessao.setAttribute("usuarioLogado", login);
            return true;
        }
        return false;
    }

    @GetMapping("/usuario-logado")
    public String obterUsuarioLogado(HttpSession sessao) {
        String usuario = (String) sessao.getAttribute("usuarioLogado");
        return usuario != null ? usuario : "";
    }
}

Código do Frontend (login.html)

<script>
    function enviarLogin() {
        fetch('/api/autenticacao', {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: new URLSearchParams({
                login: document.getElementById('campoLogin').value,
                senha: document.getElementById('campoSenha').value
            })
        })
        .then(resposta => resposta.json())
        .then(sucesso => {
            if (sucesso) {
                window.location.href = '/painel.html';
            } else {
                alert('Credenciais inválidas!');
            }
        });
    }
</script>

O arquivo painel.html faria uma requisição GET para /api/usuario-logado ao carregar para exibir o nome do usuário.

3. Livro de Visitas (留言板)

Definição do Requisito

Uma aplicação onde os usuários podem postar mensagens curtas (de, para, mensagem) e visualizar todas as posatgens em ordem cronológica.

Definição das APIs

Endpoint para Postar Mensagem
  • Caminho: /api/mensagens
  • Método: POST
  • Corpo (JSON): {"remetente": "Ana", "destinatario": "Beto", "conteudo": "Olá!"}
  • Resposta: Status HTTP 201 Created.
Endpoint para Listar Mensagens
  • Caminho: /api/mensagens
  • Método: GET
  • Resposta: Um array JSON com todas as mensagens.

Código do Backend

Modelo de Dados (DTO)
package com.exemplo.demo.modelo;

public class RegistroMensagem {
    private String remetente;
    private String destinatario;
    private String conteudo;
    // Construtores, Getters e Setters podem ser gerados pelo Lombok com @Data
}
Controlador
package com.exemplo.demo.controlador;

import com.exemplo.demo.modelo.RegistroMensagem;
import com.exemplo.demo.servico.ServicoMensagens;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/api/mensagens")
public class ControladorMensagens {

    private final ServicoMensagens servico;

    public ControladorMensagens(ServicoMensagens servico) {
        this.servico = servico;
    }

    @GetMapping
    public List<RegistroMensagem> listarTodas() {
        return servico.obterTodasMensagens();
    }

    @PostMapping
    public ResponseEntity<Void> criar(@RequestBody RegistroMensagem novaMensagem) {
        servico.adicionarMensagem(novaMensagem);
        return ResponseEntity.status(201).build();
    }
}
Serviço (Camada de Lógica)
package com.exemplo.demo.servico;

import com.exemplo.demo.modelo.RegistroMensagem;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Service
public class ServicoMensagens {
    private final List<RegistroMensagem> armazenamento = new ArrayList<>();

    public List<RegistroMensagem> obterTodasMensagens() {
        return new ArrayList<>(armazenamento); // Retorna cópia
    }

    public void adicionarMensagem(RegistroMensagem mensagem) {
        // Validação simples
        if (mensagem.getRemetente() == null || mensagem.getConteudo() == null) {
            throw new IllegalArgumentException("Campos obrigatórios não preenchidos");
        }
        armazenamento.add(mensagem);
    }
}

Esta implementação simples utiliza uma lista em memória. Para persistência real, seria necessário integrar um repositório (como Spring Data JPA).

Simplificando com Lombok

No exemplo acima, a classe RegistroMensagem precisaria manualmente de getters, setters, construtores, etc. A biblioteca Lombok automatiza isso via anotações, reduzindo drasticamente o código boilerplate.

Principais Anotações

  • @Data: Gera getters, setters, toString, equals, hashCode e um construtor obrigatório para campos finais.
  • @Getter / @Setter: Gera apenas os respectivos métodos.
  • @AllArgsConstructor / @NoArgsConstructor: Gera construtores com todos ou nenhum argumento.

Configuração no Projeto

Adicione a dependência ao seu pom.xml (Maven):

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

Para o IDE reconhecer as anotações, geralmente é necessário instalar o plugin do Lombok.

Como Fucniona

O Lombok é um processador de anotações em tempo de compilação. Ele lê as anotações no código fonte e gera automaticamente os métodos adicionais nos arquivos .class durante a compilação. O código final no bytecode é idêntico ao que você escreveria manualmente, sem nenhum impacto na performance em tempo de execução.

Exemplo com Lombok

import lombok.Data;

@Data
public class RegistroMensagem {
    private String remetente;
    private String destinatario;
    private String conteudo;
}
// A classe agora automaticamente tem todos os getters, setters, etc.

Tags: Spring MVC java Lombok desenvolvimento web API REST

Publicado em 6-6 17:10 por Thomas