Home/Learn/Spring Boot/@PathVariable & @RequestParam

@PathVariable & @RequestParam

Beginner
Web / REST

@PathVariable extracts template variables from the URI path; @RequestParam binds query-string parameters, both support type conversion and defaulting.

Overview

@PathVariable and @RequestParam are the two primary mechanisms for extracting data from an HTTP request URL. @PathVariable maps URI template segments (e.g. /orders/{id}) to method parameters. @RequestParam binds query string parameters (e.g. ?page=2&size=20). Both support automatic type conversion to primitives, wrapped types, enums, and custom Converters. @RequestParam can be required or optional with a default value, and can bind to a Map<String, String> to capture all parameters at once.

@PathVariable

Curly-brace placeholders in the @GetMapping path are bound to @PathVariable parameters by name. Type conversion is automatic. Regex constraints (e.g. {id:[0-9]+}) restrict what the template matches.

Java — @PathVariable examples
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    // Simple path variable
    @GetMapping("/{id}")
    public OrderDTO getById(@PathVariable Long id) {
        return orderService.findById(id);
    }

    // Multiple path variables
    @GetMapping("/{year}/{month}")
    public List<OrderDTO> getByMonth(
            @PathVariable int year,
            @PathVariable int month) {
        return orderService.findByMonth(year, month);
    }

    // Rename if variable name differs from template
    @GetMapping("/{order-id}/items")
    public List<ItemDTO> getItems(
            @PathVariable("order-id") Long orderId) {  // hyphen not valid Java identifier
        return orderService.findItems(orderId);
    }

    // Regex constraint — only digits
    @GetMapping("/{id:[0-9]+}/invoice")
    public InvoiceDTO getInvoice(@PathVariable Long id) {
        return orderService.getInvoice(id);
    }
}

@RequestParam

@RequestParam binds query string or form-data parameters. It is required by default — set required=false or defaultValue to make it optional. It can bind to List<T> for multi-value params and to Map<String, String> for dynamic param sets.

Java — @RequestParam examples
@RestController
@RequestMapping("/api/products")
public class ProductController {

    // Required param — GET /api/products?category=electronics
    @GetMapping
    public List<ProductDTO> list(@RequestParam String category) { ... }

    // Optional with default — GET /api/products?page=0&size=20
    @GetMapping("/search")
    public Page<ProductDTO> search(
            @RequestParam String q,
            @RequestParam(defaultValue = "0")  int page,
            @RequestParam(defaultValue = "20") int size) {
        return productService.search(q, PageRequest.of(page, size));
    }

    // Multi-value — GET /api/products?tags=java&tags=spring
    @GetMapping("/by-tags")
    public List<ProductDTO> byTags(@RequestParam List<String> tags) { ... }

    // Capture all params dynamically
    @GetMapping("/filter")
    public List<ProductDTO> filter(@RequestParam Map<String, String> params) {
        return productService.filter(params);
    }
}

Type Conversion & Validation

Spring converts String query params to the declared Java type automatically. Register a custom Converter<String, MyType> for domain types. Add Bean Validation annotations (@Min, @Max, @Pattern) along with @Validated on the controller for request param validation.

Java — custom Converter + @Validated params
// Custom converter for enum
@Component
public class OrderStatusConverter implements Converter<String, OrderStatus> {
    @Override
    public OrderStatus convert(String source) {
        return OrderStatus.valueOf(source.toUpperCase());
    }
}

// Controller with validation
@Validated
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @GetMapping
    public List<OrderDTO> list(
            @RequestParam OrderStatus status,            // auto-converted via Converter
            @RequestParam @Min(0) int page,              // @Validated enables JSR-303 here
            @RequestParam @Max(100) int size) {
        return orderService.findByStatus(status, PageRequest.of(page, size));
    }
}

// Handle ConstraintViolationException from @Validated params
@RestControllerAdvice
public class ControllerExceptionHandler {
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleConstraintViolation(ConstraintViolationException ex) {
        return new ErrorResponse("VALIDATION_ERROR", ex.getMessage());
    }
}

Key Points to Remember

  • 1@PathVariable binds {template} segments; name defaults to parameter name, override with value().
  • 2@RequestParam is required=true by default; use required=false or defaultValue for optional params.
  • 3Both support automatic type conversion: String → int, Long, enum, LocalDate, etc.
  • 4List<T> on @RequestParam captures repeated query params (?tags=a&tags=b).
  • 5Map<String, String> on @RequestParam captures all query params dynamically.
  • 6Add @Validated on the controller class to enable JSR-303 validation on @RequestParam values.

Interview Questions

Sign in to ask Aria
1

What is the difference between @PathVariable and @RequestParam?

EasyWipro
2

How do you make a @RequestParam optional with a default value?

EasyTCS
3

How does Spring Boot convert a String query parameter to a custom enum type?

MediumAmazon
4

How would you validate that a @RequestParam integer is within a valid range?

MediumGoogle
5

What exception is thrown when a required @RequestParam is missing and how do you handle it?

MediumInfosys

Ask Aria about @PathVariable & @RequestParam

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…