Связывание списка в @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 с атрибутом списка в нем?

Спасибо

Javi
источник
Я не думаю, что это возможно. Код в HandlerMethodInvoker.resolveRequestParamвсегда получает только первое значение
skaffman
6
( Spring Boot ): о method = RequestMethod.GETили method = RequestMethod.POST? Если .GET @RequestParam List<String> groupValвыполнено ?groupVal=kkk,ccc,mmmуспешно ( Spring Boot )
Василий

Ответы:

77

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

myparam=myValue1&myparam=myValue2&myparam=myValue3

Если вам нужно привязать @ModelAttributeиндексированные параметры -style, я думаю, вам @ModelAttributeвсе равно нужно .

axtavt
источник
1
могут возникнуть проблемы с порядком (что очень важно в моем случае), потому что я отправляю параметры, сериализуя форму и отправляя i с помощью ajax. Я буду использовать «традиционный» способ @ModelAttribute.
Javi
Не знаете ли вы, как создать URI с этим сопоставлением сортировки с помощью UriTemplate или каким-либо другим способом? (для клиента такого рода ресурса).
Chomeh
Отвечая на мой собственный вопрос, похоже, что Spring UriTemplate не поддерживает RFC6570, используйте чертовски удобную реализацию: 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
это сохраняет порядок?
Эндрю Кук
7
Я смог использовать только имя, а не [] в Spring 3.0, таким образом: @RequestParam (value = "myParam") String [] myParams
M Smith
3
Однако я не разделяю выводы @MSmith.
droope
2
Можно ли получить List<String>через это. Также есть возможность получить Java Bean , какList<MyBean>
Juzer Ali
3
Думаю, вы можете убрать скобки с имени параметра.
theblang 08
19

Просто дополняя то, что сказал Donal Fellows, вы можете использовать List с @RequestParam

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

Надеюсь, поможет!

Хорхе Перес
источник
12

Подписка на то, что сказал базилик в комментарии к самому вопросу, если method = RequestMethod.GETможно @RequestParam List<String> groupVal.

Тогда вызвать сервис со списком параметров очень просто:

API_URL?groupVal=kkk,ccc,mmm
Хуанги Йордан
источник
10

Один из способов сделать это (хакерским способом) - создать класс-оболочку для 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'
driangle
источник
Это почти то же самое, что и использование @ModelAttribute, с той лишь разницей, что параметр не аннотирован. Я хотел избежать @ModelAttribute только потому, что не хотел создавать оболочку. Я где-то читал в stackoverflow (я не могу вспомнить, где именно), что если вы добавите параметр в метод контроллера без аннотации @ModelAttribute (и это не был специальный объект, такой как HttpRequest, HttpResponse ...), структура рассматривает его как если он был аннотирован @ModelAttribute. Итак, если это было правдой, это точно так же, как наличие @ModelAttribute. Но спасибо за ответ.
Javi
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');

    }

}
Хомейни
источник