it-roy-ru.com

Привязка списка в @RequestParam

Я отправляю некоторые параметры из формы следующим образом:

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

Спасибо

106
Javi

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

myparam=myValue1&myparam=myValue2&myparam=myValue3

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

66
axtavt

Или вы можете просто сделать это так:

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

Это работает, например, для таких форм:

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

Это самое простое решение :)

103
Bernhard

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

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

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

12
Jorge Peres

Один из способов сделать это (хакерским способом) - создать класс-оболочку для 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'
9
ggreiner

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

Затем вызвать службу со списком параметров так же просто, как:

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

Для меня не было очевидным, что, хотя вы можете принять коллекцию в качестве параметра запроса, но на стороне потребителя вам все равно придется передавать элементы коллекции в виде значений, разделенных запятыми

Например, если 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);
}

Полный пример можно найти здесь , надеюсь, это спасет кого-то от головной боли :)

0
Péter Veres