绑定@RequestParam中的列表


126

我以这种方式从表单发送一些参数:

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){
    ....
}

但它们都没有绑定myParam。即使将值添加到地图,它也无法绑定参数:

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

是否有任何语法可以将某些参数绑定到列表或数组,而不必将对象创建为带有列表属性的@ModelAttribute?

谢谢


我认为这是不可能的。HandlerMethodInvoker.resolveRequestParam仅在代码中获得第一个值
skaffman 2011年

6
Spring Boot):大约method = RequestMethod.GET还是method = RequestMethod.POST?如果.GET @RequestParam List<String> groupVal从实现?groupVal=kkk,ccc,mmm成功(春季启动
罗勒

Answers:


76

中的数组@RequestParam用于绑定多个相同名称的参数:

myparam=myValue1&myparam=myValue2&myparam=myValue3

如果您需要绑定@ModelAttribute样式索引的参数,我想您@ModelAttribute还是需要。


1
顺序可能存在问题(对于我而言,这很重要),因为我通过序列化表单并使用ajax发送i来发送参数。我将使用“传统的” @ModelAttribute方法。
哈维

您是否会偶然知道如何使用UriTemplate或其他方式使用此排序映射构造URI?(针对此类资源的客户)。
Chomeh

回答我的问题,它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
这样可以保留订单吗?
安德鲁·库克

7
这样我就可以只使用名称,而不能使用Spring 3.0中的[]:@RequestParam(value =“ myParam”)String [] myParams
M Smith

3
不过,我不同意@MSmith的发现。
droope 2012年

2
是否有可能List<String>通过此获得。也有可能获得Java Bean,例如List<MyBean>
Juzer Ali 2013年

3
我认为您可以从参数名称中删除方括号。
theblang

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

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

对我来说,不是很明显,尽管您可以接受Collection作为请求参数,但是在消费者方面,您仍然必须以逗号分隔的值形式传递Collection项目

例如,如果服务器端api如下所示:

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

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

下面这样将集合作为RequestParam直接传递给RestTemplate 会导致数据损坏

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

    }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.