A comunicação entre o frontend e o backend em arquiteturas modernas, como as baseadas em Spring Boot, depende fundamentalmente da correta extração dos dados enviados pelo cliente. O framework oferece diversas estratégias para mapear requisições HTTP em métodos Java, variando desde a captura simples de strings até a desserialização complexa de objetos JSON ou arquivos binários.
1. Extração de Segmentos da URL (Path Variibles)
Quando os identificadores de recursos fazem parte da estrutura hierárquica do endpoint, utiliza-se o padrão RESTful. A anotação @PathVariable permite extrair valores diretamente dos placeholders definidos na rota.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.stereotype.Controller;
@Controller
public class ResourceController {
@GetMapping("/api/v1/products/{productId}")
public String getProductDetails(@PathVariable("productId") Integer id) {
// O valor de 'id' será preenchido automaticamente com o segmento da URL
return "Produto ID: " + id;
}
}
Neste exemplo, uma requisição para GET /api/v1/products/50 resultará no parâmetro id recebendo o valor inteiro 50.
2. Captura de Query Strings Simples
Para parâmetros não obrigatórios ou filtros simples, o Spring pode vincular automaticamente os nomes dos argumentos do método aos nomes das chaves presentes na query string, sem necessidade de anotações explícitas se os nomes coincidirem.
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/search")
public class SearchController {
@RequestMapping(method = RequestMethod.GET)
public String searchResults(String keyword, Integer page) {
// Se a URL for /search?keyword=spring&page=2
// keyword recebe "spring" e page recebe 2
return String.format("Busca por '%s', página %d", keyword, page);
}
}
3. Mapeamento Automático via Data Binding (POJOs)
Em cenários onde múltiplos parâmetros formam um objeto lógico, é mais eficiente criar uma classe Plain Old Java Object (POJO) e deixar o Spring realizar o binding automático. Isso reduz a verbosidade do código do controlador.
import lombok.Data;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@Data
class UserProfile {
private String fullName;
private String email;
private Integer age;
}
@RestController
public class UserController {
@PostMapping("/users/register")
public String registerUser(UserProfile profile) {
// Os campos do objeto 'profile' são populados a partir dos parâmetros da requisição
// Ex: ?fullName=John&email=john@example.com&age=30
System.out.println("Registrando usuário: " + profile.getFullName());
return "Sucesso";
}
}
4. Acesso Direto ao HttpServletRequest
Embora menos comum em APIs REST puras devido à acoplamento à Servlet API, acessar o HttpServletRequest oferece controle granular sobre a obtenção de parâmetros, permitindo lógica customizada de validação antes do mapeamento formal.
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LegacyEndpointController {
@PostMapping("/legacy/process")
public String processLegacyData(HttpServletRequest request) {
String category = request.getParameter("cat");
String subCategory = request.getParameter("sub");
if (category == null) {
return "Erro: Categoria não especificada";
}
return "Processando categoria: " + category;
}
}
5. Controle Explícito com @RequestParam
A anotação @RequestParam é ideal quando o nome do argumento Java difere do nome do parâmetro na requisição, ou quando se deseja definir valores padrão e obrigatoriedade.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConfigController {
@GetMapping("/config")
public String getConfig(
@RequestParam(name = "env", defaultValue = "dev") String environment,
@RequestParam(required = true) String token
) {
// 'environment' terá valor "dev" se não for enviado na query string
// 'token' deve estar presente, caso contrário retorna erro 400
return "Ambiente: " + environment;
}
}
6. Desserialização de Corpo JSON (@RequestBody)
Para operações POST ou PUT que enviam payloads estruturados (JSON ou XML), o uso de @RequestBody delega a conversão do corpo da requisição para o tipo de retorno Java utiliznado o HttpMessageConverter configurado (geralemnte Jackson).
import lombok.Data;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Data
class OrderItem {
private Long itemId;
private Double price;
}
@RestController
public class OrderController {
@PostMapping("/orders/create")
public List<orderitem> createOrder(@RequestBody List<orderitem> items) {
// Recebe um array JSON no corpo da requisição
// Ex: [{"itemId": 1, "price": 10.5}, {"itemId": 2, "price": 20.0}]
System.out.println("Total de itens: " + items.size());
return items;
}
}
</orderitem></orderitem>
7. Manipulação de Uploads de Arquivos (MultipartFile)
O tratamento de uploads exige o uso da interface MultipartFile, geralmente combinada com @RequestParam. É crucial verificar se o arquivo foi realmente enviado antes de tentar acessá-lo.
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@RestController
public class FileUploadController {
private static final Path UPLOAD_DIR = Paths.get("/tmp/uploads");
@PostMapping("/upload/document")
public String uploadDocument(@RequestParam("docFile") MultipartFile file) throws IOException {
if (file.isEmpty()) {
return "Falha: Nenhum conteúdo detectado no arquivo.";
}
// Garante que o diretório de destino exista
if (!UPLOAD_DIR.toFile().exists()) {
UPLOAD_DIR.toFile().mkdirs();
}
String fileName = file.getOriginalFilename();
Path destination = UPLOAD_DIR.resolve(fileName);
// Transfere o conteúdo do multipart para o sistema de arquivos
file.transferTo(destination.toFile());
return "Arquivo salvo com sucesso em: " + destination.toString();
}
}