@PathVariable & @RequestParam
Beginner@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.
@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.
@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.
// 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 AriaWhat is the difference between @PathVariable and @RequestParam?
How do you make a @RequestParam optional with a default value?
How does Spring Boot convert a String query parameter to a custom enum type?
How would you validate that a @RequestParam integer is within a valid range?
What exception is thrown when a required @RequestParam is missing and how do you handle it?
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.