Associare un elenco in @RequestParam


126

Sto inviando alcuni parametri da un modulo in questo modo:

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

So di poter ottenere tutti i parametri nel metodo controller aggiungendo un parametro come

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

Voglio associare i parametri myParam [] (non gli altri) a un elenco o array (tutto ciò che mantiene l'ordine dell'indice), quindi ho provato con una sintassi come:

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

e

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

ma nessuno di loro sta vincolando myParams. Anche quando aggiungo un valore alla mappa non è in grado di associare i parametri:

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

Esiste una sintassi per associare alcuni parametri a un elenco o a una matrice senza dover creare un oggetto come @ModelAttribute con un attributo elenco in esso?

Grazie


Non penso sia possibile. Il codice HandlerMethodInvoker.resolveRequestParamottiene solo il primo valore
skaffman il

6
( Spring Boot ): è circa method = RequestMethod.GETo method = RequestMethod.POST? Se .GET @RequestParam List<String> groupValcompletato con ?groupVal=kkk,ccc,mmmsuccesso ( Spring Boot )
basil

Risposte:


76

Le matrici in @RequestParamvengono utilizzate per associare diversi parametri con lo stesso nome:

myparam=myValue1&myparam=myValue2&myparam=myValue3

Se hai bisogno di associare @ModelAttributeparametri indicizzati in stile, immagino che ti servano @ModelAttributecomunque.


1
potrebbero esserci problemi con l'ordine (che è molto importante tenere nel mio caso) perché invio i parametri serializzando un modulo e inviando i con ajax. Userò il modo "tradizionale" di @ModelAttribute.
Javi il

Ti capita di sapere come costruire un URI con questo tipo di mappatura con UriTemplate o in qualche altro modo? (per un cliente di questo tipo di risorsa).
Chomeh,

Rispondendo alla mia domanda, è apears la molla UriTemplate non supporta RFC6570, utilizzare l'attuazione damnhandy: stackoverflow.com/questions/14153036/...
Chomeh

110

O potresti semplicemente farlo in questo modo:

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

Funziona ad esempio per moduli come questo:

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

Questa è la soluzione più semplice :)


4
questo preserva l'ordine?
Andrew Cooke,

7
Sono stato in grado di utilizzare solo il nome anziché [] nella primavera 3.0: @RequestParam (value = "myParam") String [] myParams
M Smith

3
Tuttavia, non condivido i risultati di @MSmith.
droope il

2
È possibile ottenere List<String>attraverso questo. Inoltre è possibile ottenere un java bean comeList<MyBean>
Juzer Ali,

3
Penso che puoi rimuovere le parentesi dal nome param.
theblang

19

A complemento di ciò che ha detto Donal Fellows, puoi usare List con @RequestParam

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

Spero che sia d'aiuto!


12

Sottoscrivendo ciò che Basil ha detto in un commento alla domanda stessa, se method = RequestMethod.GETè possibile utilizzare @RequestParam List<String> groupVal.

Quindi chiamare il servizio con l'elenco dei parametri è semplice come:

API_URL?groupVal=kkk,ccc,mmm

11

Un modo in cui potresti ottenere questo (in un modo hacker) è creare una classe wrapper per il List. Come questo:

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

Quindi la firma del metodo del controller sarà simile al seguente:

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

Non è necessario utilizzare l' annotazione @RequestParamo @ModelAttributese il nome della raccolta passato nella richiesta corrisponde al nome del campo di raccolta della classe wrapper, nel mio esempio i parametri della richiesta dovrebbero apparire così:

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

Bene, questo è quasi uguale all'utilizzo di @ModelAttribute, l'unica differenza è che il parametro non è annotato. Volevo evitare @ModelAttribute solo perché non volevo creare un wrapper. Ho letto da qualche parte in StackOverflow (non ricordo esattamente dove) che se aggiungi un parametro nel metodo controller senza l'annotazione @ModelAttribute (e non era un oggetto speciale come HttpRequest, HttpResponse ...) il framework lo tratta come se fosse stato annotato con @ModelAttribute. Quindi, se fosse vero, è esattamente come avere @ModelAttribute. Ma grazie per la tua risposta.
Javi,

4

Per me non era ovvio che sebbene tu possa accettare una Collezione come parametro di richiesta, ma dal lato consumatore devi comunque passare gli elementi della raccolta come valori separati da virgola .

Ad esempio, se l'API lato server è simile al seguente:

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

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

Il passaggio diretto di una raccolta a RestTemplate come RequestParam come di seguito comporterà il danneggiamento dei dati

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

Invece puoi usare

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'esempio completo può essere trovato qui , spero che salvi il mal di testa a qualcuno :)


-7

Cambia il valore del campo nascosto con la casella di controllo attiva come di seguito ...

HTML:

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

script:

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

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

    } else {

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

    }

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.