Binden einer Liste in @RequestParam


126

Ich sende einige Parameter aus einem Formular auf folgende Weise:

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

Ich weiß, dass ich alle Parameter in der Controller-Methode durch Hinzufügen eines Parameters wie erhalten kann

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 wie der folgenden versucht:

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

und

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

aber keiner von ihnen bindet die myParams. Selbst wenn ich der Karte einen Wert hinzufüge, können die Parameter nicht gebunden werden:

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 erstellen zu müssen?

Vielen Dank


Ich denke nicht, dass das möglich ist. Der Code in HandlerMethodInvoker.resolveRequestParambekommt immer nur den ersten Wert
Skaffman

6
( Spring Boot ): Geht es um method = RequestMethod.GEToder method = RequestMethod.POST? Wenn erfolgreich .GET @RequestParam List<String> groupValerfüllt ?groupVal=kkk,ccc,mmm( Spring Boot )
Basilikum

Antworten:


76

Arrays in @RequestParamwerden zum Binden mehrerer gleichnamiger Parameter verwendet:

myparam=myValue1&myparam=myValue2&myparam=myValue3

Wenn Sie @ModelAttributeindizierte Parameter im Stil binden müssen, brauchen Sie diese wahrscheinlich @ModelAttributetrotzdem.


1
Es kann Probleme mit der Reihenfolge geben (was in meinem Fall sehr wichtig ist), da ich die Parameter sende, indem ich ein Formular serialisiere und i mit Ajax sende. Ich werde den "traditionellen" @ ModelAttribute-Weg verwenden.
Javi

Würdest du zufällig wissen, wie man einen URI mit dieser Sortierzuordnung mit UriTemplate oder auf andere Weise erstellt? (für einen Kunden dieser Art von Ressource).
Chomeh

Wenn ich meine eigene Frage beantworte, scheint es, dass UriTemplate im Frühjahr RFC6570 nicht unterstützt. Verwenden Sie die verdammt gute Implementierung: stackoverflow.com/questions/14153036/…
Chomeh

110

Oder Sie könnten es einfach so machen:

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

Das funktioniert zum Beispiel bei solchen Formularen:

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

Dies ist die einfachste Lösung :)


4
Bewahrt das die Ordnung?
Andrew Cooke

7
Ich konnte also im Frühjahr 3.0 nur den Namen anstelle des [] verwenden: @RequestParam (value = "myParam") String [] myParams
M Smith

3
Ich teile die Ergebnisse von @MSmith jedoch nicht.
Droope

2
Ist es möglich, dadurch zu erhalten List<String>. Es ist auch möglich, eine Java-Bohne wieList<MyBean>
Juzer Ali

3
Ich denke, Sie können die Klammern aus dem Parameternamen entfernen.
Theblang

19

Als Ergänzung zu den Aussagen von Donal Fellows können Sie List mit @RequestParam verwenden

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

Ich hoffe es hilft!


12

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

Das Aufrufen des Dienstes mit der Liste der Parameter ist dann so einfach wie:

API_URL?groupVal=kkk,ccc,mmm

11

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

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

Dann würde Ihre Controller-Methodensignatur folgendermaßen aussehen:

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

Sie müssen die Annotation @RequestParamoder nicht verwenden, @ModelAttributewenn der Sammlungsname, den Sie in der Anforderung übergeben, 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'

Dies entspricht fast der Verwendung von @ModelAttribute. Der einzige Unterschied besteht darin, dass der Parameter nicht mit Anmerkungen versehen ist. Ich wollte @ModelAttribute vermeiden, nur weil ich keinen Wrapper erstellen wollte. Ich habe irgendwo im Stackoverflow gelesen (ich kann mich nicht genau erinnern, wo), dass das Framework es behandelt, wenn Sie der Controller-Methode einen Parameter ohne @ ModelAttribute-Annotation hinzufügen (und es war kein spezielles Objekt wie HttpRequest, HttpResponse ...) wenn es mit @ModelAttribute kommentiert wäre. Wenn das wahr wäre, wäre dies genau so, als hätte man @ModelAttribute. Aber danke für deine Antwort.
Javi

4

Mir war nicht klar, dass Sie zwar eine Sammlung als Anforderungsparameter akzeptieren können, aber auf der Verbraucherseite die Sammlungselemente dennoch als durch Kommas getrennte Werte übergeben müssen .

Zum Beispiel, wenn die serverseitige API so aussieht:

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

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

Die direkte Übergabe einer Sammlung an das RestTemplate als RequestParam wie unten führt zu einer Beschädigung der Daten

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 finden Sie hier , hoffe, es erspart jemandem die Kopfschmerzen :)


-7

Ändern Sie den Wert für versteckte Felder mit dem Kontrollkästchen wie unten umschalten ...

HTML:

<input type='hidden' value='Unchecked' id="deleteAll" name='anyName'>
<input type="checkbox"  onclick="toggle(this)"/> Delete All

Skript:

function toggle(obj) {`var $input = $(obj);
    if ($input.prop('checked')) {

    $('#deleteAll').attr( 'value','Checked');

    } else {

    $('#deleteAll').attr( 'value','Unchecked');

    }

}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.