Spring MVC @Requestparam – Binding request parameters

In this article we are going to see several examples on how to get request parameters with Spring MVC, how to bind them in different objects, how  to use @RequestParam annotation and when the annotation is not needed.

@RequestParam examples

@RequestParam is an annotation which indicates that a method parameter should be bound to a web request parameter.

1. Biding method parameter with web request parameter

Let’s say we have our /books url that requires a mandatory parameter named category:

we just need to add @RequestParam("parameterName") annotation before the method parameter that we will use for biding the web request parameter.
Let’s see an example:

In the snippet above we’ve captured value of request parameter “category” into String cat method argument and we put its value into a Model object so that we can easily test it.

In the test above we are using Spring MVC test library to perform an HTTP GET request to /books with a parameter – category – which has value “java”. Then we verify that the response status is OK (code: 200) and that the model contains an attribute named category and that its value is “java”.

For this test we’ve quickly setup a Spring Boot project, you can find the pom.xml at the end of this article.

Please note that category is considered a mandatory parameter, if we don’t pass category parameter in our call as in the test below we receive a 400: BadRequestException.

2. Request parameter match method parameter name

If both variable and request parameter name matches we don’t need to specify the parameter name in the @RequestParam annotation.

In the example above, since both variable and request parameter name is ‘category’, binding is performed automatically.

3. Auto type conversion

If the request parameter is not a String but – for example – a number we can bind it to the corresponding type. Let’s say we have a call like this:

In order to bind rate and maxprice respectively with an int and a BigDecimal, we just need to specify the target type after the annotation.

Similarly if we want to pass a date like:

We need to bind it with respective object:

Since dates have different formats, it’s necessary specify which one should be used in order to parse the value parameter correctly. In our example we’ve used @DateTimeFormat  to specify iso DateTimeFormat.ISO.DATE that is the most common ISO: yyyy-MM-dd.

All simple types such as int,long, Date, etc. are supported.

Conversion process can be configured and customized according to your needs using WebBinder or by registering Formatters

4. @RequestParam with not mandatory parameters

When we add@RequestParam annotation, as we’ve seen, by default we are assuming that request parameter is mandatory. In case we want to specify that is not, we can just add required=false.

In this case if we call just /books without parameter, we won’t receive a 400 as before. String category in this case will remain null.

5. @RequestParam with Default value 

It’s also possible specify a default value that will be applied if parameter is not sent. Let’s say our default value is “fantasy” we can add defaultValue = "fantasy" in the annotation as follow:

Let’s then perform our test in which we don’t pass category request parameter, expected value it’s gonna be “fantasy”.

When request parameter is sent, value should be, of course, the one sent and not our default.

6. @RequestParam with List or array

We can also perform a call in which we specify several values for a parameters, like:

In this case we can bind it using a List or an array – this is with a List:

and with array:

7. @RequestParam with Map

It’s also possible bind all request parameters in a Map just by adding a Map object after the annotation:

In this example we’ve added a Map<String,String>, the key is the request parameter name, so we just get the parameters from the Map using their name. I think it’s worth highlight that with this approach you can’t specify which parameters are mandatory and which not and that the code can be insidious to read, since might need to read it all in order to figure out which are the possible parameters used by this method.

In order to validate the snippet let’s perform a little test:

Note that if you have multiple values for the same parameter name, you should use MultiValueMapIn the example below we use@RequestParam with MultiValueMap<String,List<String>> so that we can store multiple values for same parameter in a List.

Let’s test it passing two authors and one category:

Examples without @RequestParam

Based on the list of HandlerMethodArgumentResolver configured in your application, @RequestParam can also be omitted. If you have a look at the code of method getDefaultArgumentResolvers() of RequestMappingHandlerAdapter there is the following piece of code at the end:

Basically it’s added to the resolvers a RequestParamMethodArgumentResolver with useDefaultResolution set to true. Looking at the documentation we can see that this means that method argument that is a simple type, as defined in BeanUtils.isSimpleProperty(java.lang.Class<?>), is treated as a request parameter even if it isn’t annotated. The request parameter name is derived from the method parameter name.

Let’s see in the next example what it means.

8. Binding without annotation

We define our controller without adding the usual @RequestParam annotation before the method argument String category. 

If we run our usual test we will see that it pass!

This happens because both variable and request parameter name is ‘category’ and in the list of default handlers we have RequestParamMethodArgumentResolver with useDefaultResolution set to true. 

Despite it might looks convenient, I prefer to always specify the annotation since it clearly states that the argument represents a request parameter. 

9. Bind with a field of an object

In a similar way if we pass as argument a simple pojo object that has a field – with getter and setter – named like the request parameter, value of the request parameter will be stored into this field.

Let’s define our pojo class:

then our Controller:

and we run our usual test, we will see that also in this case value of request parameter is correctly stored into myForm.getCategory().

pom.xml

For these test we’ve quickly setup a Spring Book project, you can find below the pom.xml.