This guide covers mapping the request query string parameters to Spring Controller method arguments using @RequestParam annotation.
Tutorial Contents
Overview
Spring Web provides the @RequestParam annotation for extracting and mapping query string parameters of a request into Spring Controller’s method arguments. Without that, we’ll have to pull the parameter values manually from the HttpServletRequest and cast them to variables of the desired types.
Spring, along with the annotation, saves us from manual work. It also provides flexible ways of reading single-value, multi-value, or optional parameters and makes them available as method arguments.
Spring @RequestParam Annotation
Before we see the @RequestParam in action, we will look at the annotation itself.
Spring’s @RequestParam annotation maps request parameters to the arguments of a request handler method in Spring Controllers. We can use this annotation on method parameters to bind request parameters by their names.
Interestingly, this annotation is available in Spring Web and Spring WebFlux annotation-based controllers.
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}
Code language: Java (java)
There are only three attributes in this annotation. The name attribute denotes the name of the request param, and we can omit it if the method and request parameters have the same name. The required attribute represents if the request parameter is mandatory, which is true by default. Lastly, the default attribute can specify a fall-back value of a request parameter, which will be used only when the request parameter isn’t present.
Using @RequestParam
To see the @RequestParam in action, we’ll write a @GetMapping method in a Spring @RestController and execute the endpoint with requests contenting query parameters.
Reading Single Query String Parameter
We want to read a single query string parameter from a request and map it to the controller method argument.
@GetMapping("/data1")
public String singleParam(@RequestParam String id) {
return "id: " + id;
}
Code language: Java (java)
Behind the scenes, Spring looks for a query string parameter ‘id‘ and extracts its value from the request. Then it invokes the request handler singleParam(Id) and passes the param value as an argument.
To test this controller, let’s execute the GET /data endpoint with the id request parameter.
~ curl 'http://localhost:8080/data1?id=112'
--
id: 112
Code language: Bash (bash)
Reading Multiple Query String Parameters
Similarly, if the request has more than one query string parameter, we can use @RequestParam annotation individually on the respective method arguments.
@GetMapping("/data2")
public String multiParam(
@RequestParam String id,
@RequestParam String name) {
return "id: " + id + ", name: " + name;
}
Code language: Java (java)
Our controller reads the id and name parameters from the request.
~ curl 'http://localhost:8080/data2?id=112&name=Jon'
--
id: 112, name: Jon
Code language: Bash (bash)
Executing the respective GET request, we see that both request parameters are mapped correctly.
Mapping Query String Parameters with Specific Type
By default, all the request query string parameters are represented as String. However, our method argument can describe the variable to a specific data type. Interestingly, Spring takes care of this type-casting internally.
For example, our Spring Controller reads a request parameter as a Long value.
@GetMapping("/data3")
public String typedParam(@RequestParam Long id) {
return "id: " + id;
}
Code language: Java (java)
If Spring cannot cast the param value, it returns HTTP Status 400 (BAD_REQUEST), as shown.
~ curl -i 'http://localhost:8080/data3?id=abc'
--
HTTP/1.1 400
...
Code language: Bash (bash)
Reading MultiValue Query String Parameters
Any query string parameter in a request can have multiple values. That means they can appear multiple times in the URL or have comma-separated values. Spring @RequestParam annotation maps such request parameters to a collection- for example, List.
@GetMapping("/data4")
public String multiValueParams(@RequestParam List<String> id) {
return "id: " + id;
}
Code language: Java (java)
Alternatively, we can also use an Array type or a Set type. Using the parameter of Set type ensures that the query string has unique values.
Let’s execute a request with a comma-separated multi-value parameter.
~ curl 'http://localhost:8080/data4?id=12,13,15,16'
--
id: [12, 13, 15, 16]
Code language: Bash (bash)
Or a request having the same parameter multiple times with different values.
~ curl 'http://localhost:8080/data4?id=12&id=13&id=15'
--
id: [12, 13, 15]
Code language: Bash (bash)
Making Query String Parameters Optional
By default, all the request parameters annotated with the @RequestParam are mandatory. Thus in the previous examples, if we skip a query string parameter from a request, we get a Bad Request response.
~ curl -i 'http://localhost:8080/data4'
--
HTTP/1.1 400
...
Code language: Bash (bash)
Now, let’s see the three ways of using @RequestParam annotation on optional request parameters.
Using @RequestParam required=false
To support optional query string parameters in a Spring controller, we can use the @RequestParam with the required=false flag.
@GetMapping("/data5")
public String optionalParams
(@RequestParam(required = false) Long id) {
return "id: " + id;
}
Code language: Java (java)
Now, we can omit the id parameter from our request.
~ curl 'http://localhost:8080/data5'
--
id: null
Code language: JavaScript (javascript)
Using @RequestParam with Java Optional
Alternatively, we can use the Java Optional to make a particular query string parameter in a request optional. We can also provide a default value for a missing query string using Java Optional.
@GetMapping("/data6")
public String javaOptionalParams
(@RequestParam Optional<String> id) {
return "id: " + id.orElseGet(() -> "Unknown");
}
Code language: Java (java)
The example shows how to use Java Optional to make a Spring Controller request parameter not mandatory.
~ curl 'http://localhost:8080/data6'
--
id: Unknown
Code language: Bash (bash)
Using @RequestParam defaultValue
Lastly, we can use the defaultValue attribute of the @RequestParam annotation to specify a default value of a request parameter. Spring uses the provided defaultValue only when the actual parameter in the request is absent or empty.
@GetMapping("/data7")
public String defaultParams
(@RequestParam(defaultValue = "Unknown") String id) {
return "id: " + id;
}
Code language: Java (java)
Let’s test this by executing a GET request without any parameters.
~ curl 'http://localhost:8080/data7'
--
id: Unknown
Code language: Bash (bash)
Mapping Query String Parameters by Name
In the previous examples, the controller method argument and a request’s respective query string parameter had the same name. Thankfully, we can use the name attribute of Spring @RequestParam when the query string parameter name is different than that of the method argument.
@GetMapping("/data8")
public String namedParams
(@RequestParam(name = "id") String dataId) {
return "dataId: " + dataId;
}
Code language: Java (java)
Reading Query String Parameters as Java Map
With the Spring @RequestParam annotation, we can collect all the request query string parameters as a HashMap. That is useful when we want to read all the query string parameters and their values together.
@GetMapping("/data9")
public String mappedParams
(@RequestParam Map<String, String> dataQuery) {
return dataQuery.toString();
}
Code language: Java (java)
~ curl 'http://localhost:8080/data9?id=12&year=2034'
--
{id=12, year=2034}
Code language: Bash (bash)
Summary
We have covered using Spring @RequestParam annotation to map query string parameters to controller method arguments. This annotation is available for both Spring MVC and Spring WebFlux.
In this tutorial, we had a detailed overview of the @RequestParam annotation and covered various scenarios of mapping request parameters to controller method arguments.
Please refer to our GitHub Repository for the complete source code of the examples used here.
Related Posts:
- Spring @PathVariable Examples
- Return Specific HTTP Response Status in Spring
- Read HTTP Headers in Spring REST Controller
- Custom Error Messages in Spring REST API
- Custom Media Types in Spring REST API