Spring Boot中@GetMapping接收复杂对象列表参数的问题咨询
你好,我看了你的问题,这是Spring MVC处理GET请求复杂对象列表参数时常见的绑定问题,我来帮你分析解决~
先梳理下你的问题场景:你有一个带分页和过滤条件的GET接口,想用List<FilterCriterion>接收过滤参数,但直接用List会报构造器异常,换成ArrayList后参数又为空,请求用的是filters[0].column=xxx这种格式。
下面给你两种可行的解决方案:
方案一:用DTO包装请求参数(最推荐,代码更清晰)
创建一个专门的请求DTO类,把分页参数和过滤列表都封装进去,Spring MVC能更顺畅地完成参数绑定:
public class DepartmentSearchRequest { private Pageable pageable; // 保留校验注解确保参数合法 private @Valid List<FilterCriterion> filters; // 生成对应的getter、setter方法 }
然后修改Controller方法:
@GetMapping public Page<Department> search(@Valid DepartmentSearchRequest searchRequest) { // 这里就能正常获取到pageable和filters参数了 return Page.empty(); }
请求URL还是你原来的格式即可:http://localhost:8080/departments?page=0&size=10&sort=name,asc&filters[0].column=name&filters[0].operation=EQUALS&filters[0].value=foo
方案二:直接调整Controller方法参数(无需新增DTO)
如果不想新增DTO,可以给List参数加上@ModelAttribute注解,同时保持List类型(不用换成ArrayList),让Spring MVC正确触发数据绑定逻辑:
@GetMapping public Page<Department> search(Pageable pageable, @Valid @ModelAttribute List<FilterCriterion> filters) { return Page.empty(); }
这里要注意:Spring MVC默认支持filters[0].xxx这种索引式的参数绑定,但如果你的Spring Boot版本较旧,可能需要确保相关参数绑定配置(比如spring.mvc.allow-circular-references)是开启的,新版本默认已经开启。
为什么原来的写法有问题?
- 直接用
List<FilterCriterion>作为参数时,Spring MVC无法实例化List接口(它是接口,没有公共构造器),所以会抛出No primary or single unique constructor found for interface java.util.List异常; - 换成
ArrayList后,虽然能实例化对象,但Spring MVC默认不会自动把filters[0].xxx这种参数绑定到ArrayList中,需要通过@ModelAttribute或者DTO来触发正确的绑定逻辑。
另外要确认你的FilterCriterion类有无参构造器和getter/setter方法(你已经提到有了,这点没问题),Spring MVC参数绑定依赖这些方法。
备注:内容来源于stack exchange,提问作者aslary

