Métodos de Vinculação de Parâmetros em Controladores Spring Boot

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();
    }
}

Tags: Spring Boot REST API @PathVariable @RequestBody MultipartFile

Publicado em 10-11 05:29