Spring GET请求传递Pageable参数反序列化异常解决方案
问题根因
抛出类型转换异常的核心原因有两点:
- 你错误地将整个
Pageable实例作为独立查询参数拼入URL,RestTemplate做URI变量替换时,会直接调用toString()方法将Pageable对象转为字符串,而服务端默认没有提供字符串到Pageable类型的转换器,自然无法完成参数绑定。 - 你手写的sort参数拼接逻辑不符合Spring Data的参数约定:多字段排序场景下,需要传递多个同名sort参数,而非将所有排序字段、方向拼接为单个sort参数值,单值拼接的写法遇到多字段排序时会直接解析失败。
正确实现方案
服务端接口调整
Spring Data Web模块自带PageableHandlerMethodArgumentResolver解析器,会自动从请求查询参数中提取分页、排序信息组装为Pageable对象,不需要手动接收page、pageSize、sort参数再自行组装,也不需要额外接收名为pageable的查询参数。
修正后的接口代码如下:
@GetMapping("/") @PageableAsQueryParam public ResponseEntity<Page<Result>> getAll( @RequestHeader("Authorization") String token, // 直接声明Pageable参数即可,框架自动完成解析 Pageable pageable ) { // 业务逻辑 }
注意:Spring Data默认的分页大小参数名为size,如果你要兼容之前用的pageSize参数名,可以在application配置中添加如下配置:
spring.data.web.pageable.size-parameter=pageSize
如果不做该配置,客户端传递的pageSize参数无法被分页解析器识别。
客户端请求代码修正
不要手动拼接URI模板和参数Map,直接使用UriComponentsBuilder构造请求地址,同时修正sort参数的拼接逻辑,每个排序规则单独追加一个sort参数,格式为字段名,排序方向。
首先修正你写的分页参数拼接工具方法:
UriComponentsBuilder withPageable(UriComponentsBuilder builder, Pageable pageable) { // 如果服务端配置了size参数名为pageSize,这里把"size"替换为"pageSize"即可 builder.queryParam("page", pageable.getPageNumber()) .queryParam("size", pageable.getPageSize()); if (pageable.getSort().isSorted()) { pageable.getSort().forEach(order -> { // 每个排序规则单独添加一个sort查询参数 builder.queryParam("sort", order.getProperty() + "," + order.getDirection()); }); } return builder; }
修正后的请求发送逻辑如下,删除多余的pageable查询参数传递:
public ResponseEntity<RestResponsePage<Result>> readDocs(Pageable pageable) { HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.add("Authorization", getToken()); // 构造带分页、排序参数的完整请求URI UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(baseAppUrl + "/api/k"); URI requestUri = withPageable(uriBuilder, pageable).build().encode().toUri(); HttpEntity<Void> requestEntity = new HttpEntity<>(requestHeaders); ResponseEntity<RestResponsePage<Result>> response = restTemplate.exchange( requestUri, HttpMethod.GET, requestEntity, new ParameterizedTypeReference<RestResponsePage<Result>>() {} ); return response; }
补充说明
- 如果你坚持要在服务端单独接收page、pageSize、sort参数,必须删掉方法签名中
@RequestParam("pageable") Pageable pageable这段声明,该参数是触发本次类型转换报错的直接原因,属于完全多余的错误写法。 - 多字段排序的请求格式示例为:
/api/k?page=0&size=10&sort=createTime,desc&sort=id,asc,框架会自动解析为「先按创建时间倒序,再按id正序」的排序规则;如果把多个排序规则拼接为单个sort参数值(比如sort=createTime,desc,id,asc),框架无法正确解析排序逻辑。
内容的提问来源于stack exchange,提问作者tryingHard
相关产品推荐
相关产品推荐

