Пов’язування списку в @RequestParam


127

Я надсилаю деякі параметри з форми таким чином:

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

Я знаю, що я можу отримати всі параметри в методі контролера, додавши параметр типу

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

Я хочу прив’язати параметри myParam [] (не інші) до списку чи масиву (все, що підтримує порядок індексу), тому я спробував із синтаксисом, як:

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

і

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

але жодна з них не зв'язує myParams. Навіть коли я додаю значення до карти, він не може прив’язати парами:

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

Чи є синтаксис, який прив'язує деякі параметри до списку чи масиву, не створюючи об’єкт як @ModelAttribute з атрибутом списку в ньому?

Дякую


Я не думаю, що це можливо. Код HandlerMethodInvoker.resolveRequestParamлише коли-небудь отримує перше значення
— skaffman

6
( Весняний черевик ): Це близько method = RequestMethod.GETчи method = RequestMethod.POST? Якщо .GET @RequestParam List<String> groupValвиконано з ?groupVal=kkk,ccc,mmmуспіху ( Весняний черевик )
— базилік

Відповіді:


77

Масиви в @RequestParamвикористовуються для прив'язки кількох однойменних параметрів:

myparam=myValue1&myparam=myValue2&myparam=myValue3

Якщо вам потрібно прив’язати @ModelAttributeпараметри, індексовані в стилі, я думаю, вам це @ModelAttributeвсе одно потрібно .


1
можуть бути проблеми з замовленням (що дуже важливо зберегти в моєму випадку), оскільки я надсилаю параметри шляхом серіалізації форми та надсилання i з ajax. Я буду використовувати "традиційний" @ModelAttribute спосіб.
— Хаві

Чи трапляється вам знати, як побудувати URI за допомогою подібного зіставлення за допомогою UriTemplate або іншим способом? (для клієнта такого роду ресурсів).
— Хоме

Відповідаючи на мій власний питання, apears пружини UriTemplate не підтримує RFC6570, використовуйте damnhandy реалізації: stackoverflow.com/questions/14153036 / ...
— Chomeh

110

Або ви могли просто так:

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

Це працює, наприклад, для таких форм:

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

Це найпростіше рішення :)


4
це зберігає порядок?
— andrew cooke

7
Я зміг використовувати лише ім’я, а не [] у Spring 3.0 таким чином: @RequestParam (value = "myParam") String [] myParams
— M Smith

3
Я не поділяю висновки @MSmith.
— droope

2
Чи можна отримати List<String>через це. Також можна отримати квасоля java на зразокList<MyBean>
— Juzer Ali

3
Я думаю, ви можете зняти дужки з назви парам.
— theblang

19

Щойно доповнюючи те, що сказали стипендіати, ви можете скористатися списком за допомогою @RequestParam

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

Сподіваюся, це допомагає!


12

Підписавшись, що сказав Василь у коментарі до самого питання, якщо method = RequestMethod.GETви можете використовувати @RequestParam List<String> groupVal.

Тоді викликати службу зі списком парам так само просто:

API_URL?groupVal=kkk,ccc,mmm

11

Один із способів, який ви могли б досягти цього (хакітським способом) - створити клас обгортки для List. Подобається це:

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

Тоді ваш підпис методу контролера виглядатиме так:

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

Не потрібно використовувати @RequestParamабо @ModelAttributeпримітку, якщо ім'я колекції, яке ви передаєте в запиті, відповідає назві поля колекції класу обгортки, у моєму прикладі параметри запиту повинні виглядати так:

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

Ну, це майже те саме, що використовувати @ModelAttribute, різниця лише в тому, що параметр не коментується. Я хотів уникати @ModelAttribute лише тому, що не хотів створювати обгортку. Я читав десь у stackoverflow (я не пам'ятаю, де саме), що якщо ви додасте парам у методі контролера без анотації @ModelAttribute (а це не був спеціальний об'єкт, як HttpRequest, HttpResponse ...), рамки трактують це як якби це було помічено за допомогою @ModelAttribute. Тож якщо це було правдою, це точно так, як мати @ModelAttribute. Але дякую за вашу відповідь.
— Хаві

4

Мені не було очевидно, що хоч ви можете прийняти колекцію як параметр запиту, але з боку споживача вам все одно потрібно передавати елементи колекції у вигляді розділених комами значень .

Наприклад, якщо api на сервері виглядає так:

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

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

Безпосереднє передання колекції до RestTemplate як RequestParam, як показано нижче, призведе до пошкодження даних

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

Натомість ви можете використовувати

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

Повний приклад можна знайти тут , сподіваюсь, що хтось вбереже головний біль :)


-7

Змініть значення прихованого поля за допомогою перемикача поля, як нижче ...

HTML:

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

Сценарій:

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

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

    } else {

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

    }

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.