Spring @RequestParam Annotation

Spring @RequestParam Annotation

1. Vue d'ensemble

Dans ce rapide tutoriel, nous allons explorer l'annotation@RequestParam de Spring.

En termes simples, nous pouvons utiliser@RequestParam pour extraire des paramètres de requête, des paramètres de formulaire et même des fichiers de la requête.

Nous verrons comment utiliser@RequestParam et ses attributs. Nous discuterons également des différences entre@RequestParam et@PathVariable.

Lectures complémentaires:

Spring @RequestMapping Nouvelles annotations de raccourcis

Dans cet article, nous introduisons différents types de raccourcis @RequestMapping pour un développement Web rapide à l'aide du framework Spring MVC traditionnel.

Read more

Les annotations Spring @Controller et @RestController

Découvrez les différences entre les annotations @Controller et @RestController dans Spring MVC.

Read more

2. Une cartographie simple

Disons que nous avons un point de terminaison/api/foos qui prend un paramètre de requête appeléid:

@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam String id) {
    return "ID: " + id;
}

Dans cet exemple, nous avons utilisé@RequestParam pour extraire le paramètre de requêteid.

Une simple requête GET invoqueraitgetFoos:

http://localhost:8080/api/foos?id=abc

ID: abc

Next, *let's have a look at the annotation's attributes: _name,_ _value, required_ and _defaultValue._*

== *3. Specifying the Request Parameter Name*

In the previous example, both variable name and the parameter name are the same.

*Sometimes we want these to be different, though.* Or, if we aren't using Spring Boot, we may need to do special compile-time configuration or the parameter names won't actually be in the bytecode.

*But what's nice is that we can configure the _@RequestParam_ name using the _name_ attribute:*

[source,java,gutter:,true]

@PostMapping("/api/foos") @ResponseBody public String addFoo(@RequestParam(name = "id") String fooId, @RequestParam String name) { return "ID: " + fooId + " Name: " + name; }

We can also do _@RequestParam(value = “id”)_ or just _@RequestParam(“id”)._

== *4. Making an Optional Request Parameter*

Method parameters annotated with _@RequestParam_ are required by default.

This means that if the parameter isn’t present in the request, we'll get an error:

[source,bash,gutter:,true]

GET / api / foos HTTP / 1.1

400 Bad Request
Required String parameter 'id' is not present
----

We can configure our _@RequestParam_ to be optional, though, with the __required __attribute:

[source,java,gutter:,true]
----
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false) String id) {
    return "ID: " + id;
}
----

In this case, both:

[source,bash,gutter:,true]
----
http://localhost:8080/api/foos?id=abc
----
ID: abc
----

and

[source,bash,gutter:,true]
----
http://localhost:8080/api/foos
----
ID: null
----

will correctly invoke the method.

*When the parameter isn't specified, the method parameter is bound to _null_.*

== *5. A Default Value for the Request Parameter*

We can also set a default value to the _@RequestParam_ by using the _defaultValue_ attribute:

[source,java,gutter:,true]
----
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(defaultValue = "test") String id) {
    return "ID: " + id;
}
----

*This is like __required=false, __in that the user no longer needs to supply the parameter:*

[source,bash,gutter:,true]
----
http://localhost:8080/api/foos
----
ID: test
----

Though, we are still okay to provide it:

[source,bash,gutter:,true]
----
http://localhost:8080/api/foos?id=abc
----
ID: abc
----

Note that when we set the __defaultValue __attribute, _required_ is, indeed, set to false.

== *6. Mapping All Parameters*

*We can also have multiple parameters without defining their names* or count by just using _Map:_

[source,java,gutter:,true]
----
@PostMapping("/api/foos")
@ResponseBody
public String updateFoos(@RequestParam Map allParams) {
    return "Parameters are " + allParams.entrySet();
}
----

Which will then reflect back any parameters sent:

[source,bash,gutter:,true]
----
curl -X POST -F 'name=abc' -F 'id=123' http://localhost:8080/api/foos

Les paramètres sont {[name = abc], [id = 123]}

== *7. Mapping a Multi-Value Parameter*

A single _@RequestParam_ can have multiple values:

[source,java,gutter:,true]

@GetMapping("/api/foos") @ResponseBody public String getFoos(@RequestParam List id) { return "IDs are " + id; }

*And Spring MVC will map a comma-delimited __id __parameter:*

[source,bash,gutter:,true]
IDs are [1,2,3]

Ou une liste de paramètresid séparés:

http://localhost:8080/api/foos?id=1&id=2

Les identifiants sont [1,2]

== *8. _@RequestParam_ vs _@PathVariable_*

_@RequestParam_ and _@PathVariable_ can both be used to extract values from the request URI, but they are a bit different.

=== *8.1. Query Parameter vs URI Path*

While __@RequestParam__s extract values from the query string, _@PathVariables_ extract values from the URI path:

[source,java,gutter:,true]

@GetMapping("/foos/{id}") @ResponseBody public String getFooById(@PathVariable String id) { return "ID: " + id; }

Then, we can map based on the path:

[source,bash,gutter:,true]
ID: abc

Et pour@RequestParam, ce sera:

@GetMapping("/foos")
@ResponseBody
public String getFooByIdUsingQueryParam(@RequestParam String id) {
    return "ID: " + id;
}

Ce qui nous donnerait la même réponse, juste un autre URI:

http://localhost:8080/foos?id=abc

ID: abc

=== *8.2. Encoded vs Exact Value*

Because _@PathVariable_ is extracting values from the URI path, it’s not encoded. On the other hand, _@RequestParam_ is.

Using the previous example, _ab+c_ will return as-is:

[source,bash,gutter:,true]
ID: ab+c

Mais pour la requêtea @RequestParam, le paramètre est décodé en URL:

http://localhost:8080/foos?id=ab+c

ID: ab c

=== *8.3. Optional Values*

*Both _@RequestParam_ and _@PathVariable_ can be optional.*

We can make _@PathVariable_ optional by using the _required_ attribute starting with Spring 4.3.3:

[source,java,gutter:,true]

@GetMapping({"/myfoos/optional", "/myfoos/optional/{id}"}) @ResponseBody public String getFooByOptionalId(@PathVariable(required = false) String id){ return "ID: " + id; }

Which, then, we can do either:

[source,bash,gutter:,true]
ID: abc

or:

http://localhost:8080/myfoos/optional

ID: null

For @RequestParam, we can also use the _required_ attribute as we saw in a previous section.

Note that *we should be careful when making _@PathVariable_ optional, to avoid conflicts in paths.*

== *9. Conclusion*

In this article, we learned how to use _@RequestParam_ and the difference between _@RequestParam_ and _@PathVariable_.

The full source code for the examples can be found in the https://github.com/eugenp/tutorials/tree/master/spring-mvc-simple[GitHub project].