【问题标题】:Modify Spring MVC Request to List Parameter Binding to Not Separate on Commas修改 Spring MVC 请求以列出参数绑定以不以逗号分隔
【发布时间】:2020-12-16 23:52:29
【问题描述】:

我正在通过一个简单的网络表单发送names

<form action="test" method="GET">
  <select name="names" multiple="true">
    <option>Doe, Jane</option>
    <option>Doe, John</option>
  </select>
  <input type="submit"/>
</form>

names 绑定到控制器中的List

@GetMapping("/test")
public String test(@RequestParam List<String> names, Model m) {
  System.out.println(names.size());
  System.out.println(names);
  return "test";
}

但是因为我的名称值包含逗号 (,),所以 Spring 正在将应该是单个名称值的内容解析为两个字符串。

GET/test?names=Doe, John 的请求(将逗号的 URL 编码从 , 删除到 %2C 以提高可读性)会生成一个包含两个字符串值的列表,DoeJohn,而不是单个值Doe, John 随意。

但是,当发送多个值时,事情会按预期工作,例如:/test?names=Doe, Jane&amp;names=Doe, John。在这种情况下,我有一个包含两个项目的列表:Doe, JaneDoe, John

一种解决方法是简单地始终在表单中发送一个空的names 值,包括:

<input type="hidden" name="names"/>

然后从列表中删除空值。但我不想这样做。

如何将 Spring MVC 配置为不使用逗号解析字符串值,而是期望列表属性值像 ?name=Jon&amp;name=Sue&amp;name=Bob 一样简单地重复?

我正在使用 Spring Boot 2.3.2。谢谢!

【问题讨论】:

    标签: spring spring-boot spring-mvc


    【解决方案1】:

    转换似乎发生在:

    org.springframework.core.convert.support.StringToCollectionConverter

    必须是框架注册的默认转换器。

    您可以在控制器或控制器建议中使用@InitBinder 方法来注册转换器,但我不确定您如何覆盖或禁用此默认转换器。

    最简单的做法就是直接从 HttpServletRequest 访问参数:

     @Controller
    public class TestController {
    
        @RequestMapping("/test")
        public String test(@RequestParam("names") List<String> names, HttpServletRequest request) {
            
            //1
            System.out.println(request.getParameterValues("names").length);
            System.out.println(Arrays.toString(request.getParameterValues("names")));
            
            //2
            System.out.println(names.size());
            System.out.println(names);
    
            return null;
        }
    }
    

    经过额外的实验,您可以通过从GenericConversionService 中显式删除从String.classCollection.class 的转换来禁用Spring Boot 中框架的StringToCollectionConverter 的调用:

    @Autowired
    void conversionService(GenericConversionService genericConversionService) {
      List<String> names = genericConversionService.convert("Ed, Al", List.class);
      System.out.println(names.size()); // 2
    
      genericConversionService.removeConvertible(String.class, Collection.class);
    
      names = genericConversionService.convert("Ed, Al", List.class);
      System.out.println(names.size()); // 1
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 1970-01-01
      相关资源
      最近更新 更多