在@RequestParam 中绑定一个列表

Posted

技术标签:

【中文标题】在@RequestParam 中绑定一个列表【英文标题】:Binding a list in @RequestParam 【发布时间】:2011-06-03 12:56:38 【问题描述】:

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

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 中的代码只获得第一个值 (Spring Boot): 是关于method = RequestMethod.GET 还是method = RequestMethod.POST?如果.GET @RequestParam List&lt;String&gt; groupVal?groupVal=kkk,ccc,mmm 成功实现(Spring Boot 【参考方案1】:

或者你可以这样做:

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

这适用于例如这样的表单:

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

这是最简单的解决方案:)

【讨论】:

这样会保留订单吗? 因此我能够在 Spring 3.0 中仅使用名称而不是 []:@RequestParam(value="myParam") String[] myParams 不过,我不分享@MSmith 的发现。 是否可以通过这个获取List&lt;String&gt;。也有可能获得像List&lt;MyBean&gt;这样的java bean 我认为您可以从参数名称中删除括号。【参考方案2】:

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

myparam=myValue1&myparam=myValue2&myparam=myValue3

如果你需要绑定@ModelAttribute风格的索引参数,我猜你还是需要@ModelAttribute

【讨论】:

订单可能有问题(这在我的情况下非常重要),因为我通过序列化表单并使用 ajax 发送 i 来发送参数。我将使用“传统”@ModelAttribute 方式。 您是否知道如何使用 UriTemplate 或其他方式使用这种排序映射构造 URI? (对于这种资源的客户)。 回答我自己的问题,春天 UriTemplate 不支持 RFC6570,请使用该死的实现:***.com/questions/14153036/…【参考方案3】:

订阅 basil 在对问题本身的评论中所说的话,如果 method = RequestMethod.GET 可以使用 @RequestParam List&lt;String&gt; groupVal

那么使用参数列表调用服务就很简单了:

API_URL?groupVal=kkk,ccc,mmm

【讨论】:

我有一个小问题。如果其中一个字符串元素包含“,”并且 url 将其解码为两个单独的字符串元素,我该怎么办。【参考方案4】:

只是补充 Donal Fellows 所说的,您可以将 List 与 @RequestParam 一起使用

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

希望对你有帮助!

【讨论】:

【参考方案5】:

您可以实现此目的的一种方法(以一种骇人听闻的方式)是为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 只是因为我不想创建包装器。我在***的某个地方读到(我不记得确切的位置)如果你在没有@ModelAttribute注释的控制器方法中添加一个参数(并且它不是像HttpRequest,HttpResponse这样的特殊对象......)框架将它视为如果它用@ModelAttribute 注释。因此,如果这是真的,这与拥有@ModelAttribute 完全一样。不过谢谢你的回答。【参考方案6】:

虽然您可以接受 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);

The complete example can be found here,希望它能省去一些人的头疼:)

【讨论】:

【参考方案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');

    


【讨论】:

以上是关于在@RequestParam 中绑定一个列表的主要内容,如果未能解决你的问题,请参考以下文章

如何在Spring中将@RequestParam绑定到对象

数据绑定-@RequestParam

@RequestParam @RequestBody @PathVariable 等参数绑定注解详解

(转)@RequestParam @RequestBody @PathVariable 等参数绑定注解详解

@RequestParam @RequestBody @PathVariable 等参数绑定注解详解(转)

@RequestParam @RequestBody @PathVariable 等参数绑定注解详解