web-dev-qa-db-fra.com

Liaison d'une liste dans @RequestParam

J'envoie des paramètres d'un formulaire de cette façon:

myparam[0]     : 'myValue1'
myparam[1]     : 'myValue2'
myparam[2]     : 'myValue3'
otherParam     : 'otherValue'
anotherParam   : 'anotherValue' 
...

Je sais que je peux obtenir tous les paramètres de la méthode du contrôleur en ajoutant un paramètre tel que

public String controllerMethod(@RequestParam Map<String, String> params){
    ....
}

Je veux lier les paramètres myParam [] (pas les autres) à une liste ou un tableau (tout ce qui garde l'ordre des index), j'ai donc essayé avec une syntaxe comme celle-ci:

public String controllerMethod(@RequestParam(value="myParam") List<String> myParams){
    ....
}

et

public String controllerMethod(@RequestParam(value="myParam") String[] myParams){
    ....
}

mais aucun d'entre eux ne lie les myParams. Même lorsque j'ajoute une valeur à la carte, il n'est pas possible de lier les paramètres:

public String controllerMethod(@RequestParam(value="myParam") Map<String, String> params){
    ....
}

Existe-t-il une syntaxe permettant de lier certains paramètres à une liste ou à un tableau sans avoir à créer un objet en tant que @ModelAttribute contenant un attribut de liste?

Merci

106
Javi

Les tableaux dans @RequestParam permettent de lier plusieurs paramètres du même nom:

myparam=myValue1&myparam=myValue2&myparam=myValue3

Si vous devez lier des paramètres indexés de style @ModelAttribute-, je suppose que vous avez quand même besoin de @ModelAttribute.

66
axtavt

Ou vous pouvez simplement le faire de cette façon:

public String controllerMethod(@RequestParam(value="myParam[]") String[] myParams){
    ....
}

Cela fonctionne par exemple pour des formes comme celle-ci:

<input type="checkbox" name="myParam[]" value="myVal1" />
<input type="checkbox" name="myParam[]" value="myVal2" />

C'est la solution la plus simple :)

103
Bernhard

Pour compléter simplement ce que Donal Fellows a dit, vous pouvez utiliser List avec @RequestParam

public String controllerMethod(@RequestParam(value="myParam") List<ObjectToParse> myParam){
....
}

J'espère que ça aide!

12
Jorge Peres

Une façon de procéder (de manière fictive) est de créer une classe wrapper pour List. Comme ça: 

class ListWrapper {
     List<String> myList; 
     // getters and setters
}

La signature de votre méthode de contrôleur ressemblerait alors à ceci:

public String controllerMethod(ListWrapper wrapper) {
    ....
}

Il n'est pas nécessaire d'utiliser l'annotation @RequestParam ou @ModelAttribute si le nom de la collection que vous transmettez dans la demande correspond au nom du champ de collection de la classe wrapper. Dans mon exemple, les paramètres de votre demande devraient ressembler à ceci:

myList[0]     : 'myValue1'
myList[1]     : 'myValue2'
myList[2]     : 'myValue3'
otherParam    : 'otherValue'
anotherParam  : 'anotherValue'
9
ggreiner

En abonnant ce que basilic a dit dans un commentaire à la question même, si method = RequestMethod.GET, vous pouvez utiliser @RequestParam List<String> groupVal.

Ensuite, appeler le service avec la liste des paramètres est aussi simple que:

API_URL?groupVal=kkk,ccc,mmm
3
Juangui Jordán

Il n’était pas évident pour moi que, bien que vous puissiez accepter une collection en tant que paramètre de demande, mais côté consommateur vous devez toujours transmettre les éléments de la collection sous forme de valeurs séparées par des virgules 

Par exemple, si l'API côté serveur ressemble à ceci:

@PostMapping("/post-topics")
public void handleSubscriptions(@RequestParam("topics") Collection<String> topicStrings) {

    topicStrings.forEach(topic -> System.out.println(topic));
}

Passer directement une collection à RestTemplate en tant que RequestParam comme ci-dessous entraînera une corruption des données

public void subscribeToTopics() {

    List<String> topics = Arrays.asList("first-topic", "second-topic", "third-topic");

    RestTemplate restTemplate = new RestTemplate();
    restTemplate.postForEntity(
            "http://localhost:8088/post-topics?topics={topics}",
            null,
            ResponseEntity.class,
            topics);
}

Au lieu de cela, vous pouvez utiliser

public void subscribeToTopics() {

    List<String> topicStrings = Arrays.asList("first-topic", "second-topic", "third-topic");
    String topics = String.join(",",topicStrings);

    RestTemplate restTemplate = new RestTemplate();
    restTemplate.postForEntity(
            "http://localhost:8088/post-topics?topics={topics}",
            null,
            ResponseEntity.class,
            topics);
}

L'exemple complet peut être trouvé ici , espérons qu'il sauve le mal de tête à quelqu'un :)

0
Péter Veres