@RequestParam
Binds a query string or form parameter to a method parameter, with defaults, optional values and type conversion.
@RequestParam(name = "page", defaultValue = "0") int page- Added in Spring Boot Spring Framework 2.5
Parameters
| Parameter | Type | Description |
|---|---|---|
$valueoptional | String= "" | Alias for name. |
$nameoptional | String= "" | The parameter name in the request. Defaults to the Java parameter name (needs -parameters, which Spring Boot's build plugins enable). |
$requiredoptional | boolean= true | Whether the parameter must be present. Missing required parameters give 400. Optional<T> parameters are treated as not required. |
$defaultValueoptional | String= none | Value used when the parameter is missing or empty. Setting it implicitly makes the parameter not required. |
Return value
n/aBinds a request parameter (query string or form field) to the parameter, converting it to the parameter type. Lists receive repeated values; Map and MultiValueMap receive every parameter.
Errors
Missing required parameter gives 400 (MissingServletRequestParameterException); a value that cannot be converted gives 400 (MethodArgumentTypeMismatchException).
@RequestParam reads a named parameter from the query string (?city=York) or from a URL-encoded form body. Use it for things that shape a response rather than identify a resource: filters, search terms, sorting, page number and size.
Required, optional and defaults
A plain @RequestParam String city is required: if the client leaves it out, Spring answers 400 before your method runs. There are three ways to make it optional, and they behave differently:
defaultValue = "20": missing or empty values become 20. Best for page sizes and flags.Optional<String>: you getOptional.empty()and decide in code.required = false: you getnull. This fails on primitives such asint, because null cannot be assigned; use a wrapper type or a default.
@GetMapping("/api/hotels")
List<Hotel> search(@RequestParam String city,
@RequestParam(defaultValue = "1") int minStars,
@RequestParam Optional<String> sort,
@RequestParam(name = "amenity", required = false) List<String> amenities)Types
Values are converted with the same conversion service as path variables. Repeated parameters (?amenity=pool&amenity=spa) bind to a List; Spring also splits a single comma-separated value into a list. Dates need @DateTimeFormat or a global spring.mvc.format.date setting so everyone agrees on the format; ISO yyyy-MM-dd is the safe choice.
Validation
Put Bean Validation constraints such as @Min and @Max directly on the parameter. With the validation starter present, Spring MVC's built-in method validation checks them and answers 400 with the violations. Always cap page sizes: ?size=1000000 is a cheap way to knock over a database.
Mistakes people make
- Using
@RequestParamfor JSON bodies. It reads query and form parameters only; JSON needs@RequestBody. - Passing secrets or tokens in the query string. They end up in access logs and browser history.
- Binding a
Map<String, String>for filters and losing repeated values. UseMultiValueMap.
Example
import java.util.List;
import java.util.Optional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
record Hotel(long id, String city, int stars) {}
public class HotelSearchController {
private final List<Hotel> hotels = List.of(
new Hotel(1, "York", 4), new Hotel(2, "York", 3), new Hotel(3, "Bath", 5));
// GET /api/hotels?city=York&minStars=4&amenity=pool&amenity=spa
("/api/hotels")
List<Hotel> search( String city, // required: missing gives 400
(defaultValue = "1") int minStars, // optional with a default
Optional<String> sort, // optional, no default
(name = "amenity", required = false) List<String> amenities) {
return hotels.stream()
.filter(h -> h.city().equalsIgnoreCase(city))
.filter(h -> h.stars() >= minStars)
.toList();
}
}
When to use it
- Searching hotels by city with an optional minimum star rating
- Paging through events with a capped page size
- Filtering a product list by several colours at once
Frequently asked questions
What is the difference between @RequestParam and @PathVariable?
@PathVariable reads a segment of the path and usually identifies a resource. @RequestParam reads the query string or form data and usually filters or shapes the result.
Does defaultValue apply to an empty value like ?size=?
Yes. An empty value is treated like a missing one when a defaultValue is set.
More examples
Validating page and size
Constraint annotations on @RequestParam parameters are checked by Spring MVC's built-in method validation. Violations raise HandlerMethodValidationException, which becomes a 400 response.
import java.util.List;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
record Event(long id, String name) {}
@RestController
public class EventController {
// Constraints directly on parameters trigger Spring's built-in method
// validation: size=5000 gives 400 before the method runs.
@GetMapping("/api/events")
List<Event> list(@RequestParam(defaultValue = "0") @Min(0) int page,
@RequestParam(defaultValue = "20") @Min(1) @Max(100) int size) {
return List.of(new Event((long) page * size + 1, "Meetup"));
}
}
Dates in the query string
@DateTimeFormat(iso = DATE) pins the format to yyyy-MM-dd. Without it, the accepted format depends on configuration and clients guess.
import java.time.LocalDate;
import java.util.Map;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AvailabilityController {
// GET /api/availability?from=2026-11-02&to=2026-11-05
@GetMapping("/api/availability")
Map<String, Object> availability(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to) {
return Map.of("from", from, "to", to, "nights", to.toEpochDay() - from.toEpochDay());
}
}
All parameters at once
A MultiValueMap<String, String> receives every query parameter with all of its values. It suits dynamic filter screens where the allowed names come from data rather than code; check each name against that list before it reaches a query, and never build SQL from the names or values.
import java.util.List;
import java.util.Map;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FilterController {
// Every parameter, for dynamic filters such as ?colour=red&colour=blue&size=M.
// A plain Map keeps only the first value of each name; MultiValueMap keeps all.
@GetMapping("/api/products/filter")
Map<String, List<String>> filter(@RequestParam MultiValueMap<String, String> params) {
return Map.copyOf(params);
}
}
Discussion