配置Spring Data分页从1开始后,API返回页码仍为0的问题
问题分析
你配置的spring.data.web.pageable.one-indexed-parameters=true仅作用于请求参数解析阶段:当客户端传入page=1时,Spring会自动将其转换为Spring Data内部使用的0基页码(即pageNumber=0),但这个配置不会自动修改响应中Page对象的页码输出逻辑——PageImpl默认序列化时仍会输出内部的0基页码,这就是你看到响应中pageNumber为0的原因。
解决方案
要让响应返回1基页码,需要手动调整Page对象中的页码信息,以下是两种可行方案:
方案1:构造PageImpl时替换为1基的Pageable
在创建返回的PageImpl对象时,基于原pageable构造一个页码+1的新Pageable,替换掉原有的0基pageable:
@GetMapping(value = "/alluser", produces = MediaType.APPLICATION_JSON_VALUE) public Page<User> getUserinfo(Pageable pageable) { Page<User> userPage = userService.getAllUserInfo(pageable); // 用Page自带的map方法简化DTO转换(替代stream操作) List<User> userResultList = userPage.map(converterService::convertToDto).getContent(); // 构造1基的Pageable:页码+1,保留原分页大小和排序规则 Pageable oneIndexedPageable = PageRequest.of( pageable.getPageNumber() + 1, pageable.getPageSize(), pageable.getSort() ); // 用新的1基Pageable创建返回的Page对象 Page<User> userDtoPage = new PageImpl<>(userResultList, oneIndexedPageable, userPage.getTotalElements()); return userDtoPage; }
方案2:自定义Jackson序列化规则(全局生效)
如果希望所有Page对象的响应都自动输出1基页码,可以自定义Jackson序列化器,修改number(对应响应中的pageNumber)的输出值:
- 创建自定义序列化器:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import org.springframework.data.domain.Page; import java.io.IOException; public class OneIndexedPageSerializer extends JsonSerializer<Page<?>> { @Override public void serialize(Page<?> page, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartObject(); // 序列化内容列表 gen.writeObjectField("content", page.getContent()); // 序列化1基页码 gen.writeNumberField("number", page.getNumber() + 1); gen.writeNumberField("pageNumber", page.getNumber() + 1); // 序列化其他分页属性 gen.writeNumberField("size", page.getSize()); gen.writeNumberField("totalElements", page.getTotalElements()); gen.writeNumberField("totalPages", page.getTotalPages()); gen.writeBooleanField("first", page.isFirst()); gen.writeBooleanField("last", page.isLast()); gen.writeNumberField("numberOfElements", page.getNumberOfElements()); gen.writeBooleanField("empty", page.isEmpty()); // 序列化pageable和sort对象(调整pageable内的页码) gen.writeObjectField("sort", page.getSort()); gen.writeStartObjectField("pageable"); gen.writeObjectField("sort", page.getSort()); gen.writeNumberField("offset", page.getOffset()); gen.writeNumberField("pageNumber", page.getNumber() + 1); gen.writeNumberField("pageSize", page.getSize()); gen.writeBooleanField("paged", true); gen.writeBooleanField("unpaged", false); gen.writeEndObject(); gen.writeEndObject(); } }
- 注册序列化器到Spring:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.domain.Page; import com.fasterxml.jackson.databind.module.SimpleModule; @Configuration public class JacksonConfig { @Bean public SimpleModule oneIndexedPageModule() { SimpleModule module = new SimpleModule(); module.addSerializer(Page.class, new OneIndexedPageSerializer()); return module; } }
这种方案无需修改业务代码,全局生效,适合所有分页接口统一返回1基页码的场景。
额外优化:简化DTO转换
你当前的stream().map()可以替换为Spring Data Page自带的map()方法,代码更简洁:
// 替代原有stream操作 Page<User> userDtoPage = userPage.map(userObj -> converterService.convertToDto(userObj));
内容的提问来源于stack exchange,提问作者sundar saba
相关产品推荐
相关产品推荐

