it-swarm.com.de

Eine Liste in @RequestParam binden

Ich schicke einige Parameter aus einem Formular auf diese Weise:

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

Ich weiß, dass ich alle Parameter in der Controller-Methode erhalten kann, indem Sie einen Parameter wie hinzufügen

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

Ich möchte die Parameter myParam [] (nicht die anderen) an eine Liste oder ein Array binden (alles, was die Indexreihenfolge beibehält), also habe ich es mit einer Syntax versucht:

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

und

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

aber keine bindet die myParams. Selbst wenn ich einen Wert zur Karte hinzufüge, kann er die Parameter nicht binden:

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

Gibt es eine Syntax, um einige Parameter an eine Liste oder ein Array zu binden, ohne ein Objekt als @ModelAttribute mit einem Listenattribut darin erstellen zu müssen?

Vielen Dank

106
Javi

Arrays in @RequestParam werden zum Binden mehrerer gleichnamiger Parameter verwendet:

myparam=myValue1&myparam=myValue2&myparam=myValue3

Wenn Sie @ModelAttribute-style indizierte Parameter binden müssen, benötigen Sie @ModelAttribute trotzdem.

66
axtavt

Oder Sie könnten es einfach so machen:

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

Das funktioniert zum Beispiel für solche Formulare:

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

Dies ist die einfachste Lösung :)

103
Bernhard

Sie können das, was Donal Fellows gesagt haben, einfach mit @RequestParam verwenden

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

Ich hoffe es hilft!

12
Jorge Peres

Eine Möglichkeit, dies auf hackhafte Weise zu erreichen, besteht darin, eine Wrapper-Klasse für List zu erstellen. So was: 

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

Dann würde die Signatur Ihrer Controller-Methode folgendermaßen aussehen:

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

Sie müssen die Annotation @RequestParam oder @ModelAttribute nicht verwenden, wenn der in der Anforderung übergebene Sammlungsname mit dem Sammlungsfeldnamen der Wrapper-Klasse übereinstimmt. In meinem Beispiel sollten Ihre Anforderungsparameter folgendermaßen aussehen:

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

Abonnieren, was Basilikum in einem Kommentar zu der Frage selbst gesagt hat, wenn method = RequestMethod.GET Sie @RequestParam List<String> groupVal verwenden können.

Dann ist das Aufrufen des Dienstes mit der Liste der Parameter so einfach wie:

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

Für mich war es nicht offensichtlich, dass Sie eine Collection zwar als Request-Parameter akzeptieren können, aber auf der Verbraucherseite müssen Sie die Collection-Elemente immer noch als durch Kommas getrennte Werte übergeben. 

Wenn zum Beispiel das serverseitige API so aussieht:

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

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

Das direkte Übergeben einer Auflistung an das RestTemplate als RequestParam wie unter führt zu Datenbeschädigung.

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);
}

Stattdessen können Sie verwenden

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);
}

Das vollständige Beispiel kann hier gefunden werden , hoffe es erspart jemandem die Kopfschmerzen :)

0
Péter Veres