Spring Rest使用@RequestParam传递对象列表失败如何解决?
Spring GET请求传递自定义对象列表的解决方案
之前写法失败原因
- 写法1:
@RequestParam仅支持基础类型、String及对应集合的绑定,无法直接转换为自定义FilterDTO对象,触发参数类型转换异常报500 - 写法2:去掉
@RequestParam后,Spring会将List类型参数当做请求体对象处理,但GET请求没有请求体,触发java.lang.IllegalArgumentException异常 - 写法3:前端没有按Spring对象绑定的下标格式传参,导致属性无法注入,最终listFiltre为null
可选解决方案
方案1:JSON序列化传递(改造成本最低)
适用于不想改动参数结构的场景
- 前端AngularJS代码:将FilterDTO列表序列化为JSON字符串作为参数值传递
$resource('/your/api/path', {}, { getList: { method: 'GET' } }).getList({ filtres: JSON.stringify(yourFilterList) // 序列化为JSON字符串 })
- 后端代码:先用String接收参数,再反序列化为
List<FilterDTO>
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { private final ObjectMapper objectMapper = new ObjectMapper(); @GetMapping("/your/api/path") public Object api( @RequestParam(value = "filtres", required = false) String filtresStr ) throws Exception { List<FilterDTO> filtres = null; if (filtresStr != null && !filtresStr.isEmpty()) { filtres = objectMapper.readValue(filtresStr, new TypeReference<List<FilterDTO>>() {}); } // 后续业务逻辑 return null; } }
方案2:@ModelAttribute绑定封装对象
适用于不想做序列化/反序列化手动处理的场景
- 后端保持封装类不变,必须为所有属性添加getter、setter方法
public class FilterDTOList { private List<FilterDTO> listFiltre; // getter public List<FilterDTO> getListFiltre() { return listFiltre; } // setter public void setListFiltre(List<FilterDTO> listFiltre) { this.listFiltre = listFiltre; } } // FilterDTO也必须为所有属性添加getter、setter public class FilterDTO { private String field; private String value; // 省略getter、setter }
- 接口参数用
@ModelAttribute修饰
@GetMapping("/your/api/path") public Object api(@ModelAttribute FilterDTOList filterDTOList) { List<FilterDTO> filtres = filterDTOList.getListFiltre(); // 后续业务逻辑 return null; }
- 前端直接传递对应结构的对象即可,AngularJS的$resource会自动按照Spring要求的格式拼接参数
const params = { listFiltre: [ {field: 'username', value: 'zhang'}, {field: 'age', value: '20'} ] } $resource('/your/api/path').getList(params)
最终生成的请求参数格式为:?listFiltre[0].field=username&listFiltre[0].value=zhang&listFiltre[1].field=age&listFiltre[1].value=20,Spring可自动完成属性绑定。
方案3:改为POST请求传递(推荐长列表场景使用)
如果列表长度过长,会超出GET请求的URL长度限制,直接改用POST请求传递JSON请求体
- 后端接口调整:
@PostMapping("/your/api/path") public Object api(@RequestBody List<FilterDTO> filtres) { // 直接使用filtres即可 return null; }
- 前端AngularJS调整请求方法为POST:
$resource('/your/api/path', {}, { getList: { method: 'POST' } }).getList(yourFilterList) // 直接传递FilterDTO数组即可
内容的提问来源于stack exchange,提问作者thomas
相关产品推荐
相关产品推荐

