SpringBoot分页Pageable最大size的自定义配置

  • 起因

在工作中,涉及到导出的功能,由于导出和搜索的结果是相同的,所以导出和搜索是同一接口。但由于搜索的分页是每页10条,而导出却是没有条数限制的,所以引出下面的问题

  • controller方法如下:

    @PostMapping("/orders/search")
    public Page<SearchOrderOut> getOrders(@RequestBody @Valid Search search,
                                          @PageableDefault(
                                                  sort = {"modifiedDate", "createdDate"},
                                                  direction = Sort.Direction.DESC
                                          ) Pageable pageable) {
    
        return preOrderService.getOrders(search, pageable);
    }

    通过前端传递的pagesize来设定分页的大小,在使用中发现无论page的size修改为多大,导出最多只能2000条,于是怀疑源码中可能有最大值的限制,于是跟踪源码发现果真如此,源码如下(仅相关代码):

    /**
    * Extracts paging information from web requests and thus allows injecting {@link Pageable} instances into controller
    * methods. Request properties to be parsed can be configured. Default configuration uses request parameters beginning
    * with {@link #DEFAULT_PAGE_PARAMETER}{@link #DEFAULT_QUALIFIER_DELIMITER}.
    * 
    * 从Web请求中提取分页信息,从而允许将Pageable实例注入controller方法
    * 可以配置要解析的请求属性,默认配置使用以DEFAULT_PAGE_PARAMETER,DEFAULT_QUALIFIER_DELIMITER开头的请求参数
    *
    * @since 1.6
    * @author Oliver Gierke
    * @author Nick Williams
    * @author Mark Paluch
    */
    public class PageableHandlerMethodArgumentResolver implements PageableArgumentResolver {
    
        private static final String DEFAULT_PAGE_PARAMETER = "page";
        private static final String DEFAULT_SIZE_PARAMETER = "size";
        private static final String DEFAULT_PREFIX = "";
        private static final String DEFAULT_QUALIFIER_DELIMITER = "_";
        // 默认page size最大2000
        private static final int DEFAULT_MAX_PAGE_SIZE = 2000;
        static final Pageable DEFAULT_PAGE_REQUEST = new PageRequest(0, 20);
    
        private Pageable fallbackPageable = DEFAULT_PAGE_REQUEST;
        private SortArgumentResolver sortResolver;
        private String pageParameterName = DEFAULT_PAGE_PARAMETER;
        private String sizeParameterName = DEFAULT_SIZE_PARAMETER;
        private String prefix = DEFAULT_PREFIX;
        private String qualifierDelimiter = DEFAULT_QUALIFIER_DELIMITER;
        // maxPageSize 最大2000
        private int maxPageSize = DEFAULT_MAX_PAGE_SIZE;
    
        @Override
        public Pageable resolveArgument(MethodParameter methodParameter, ModelAndViewContainer mavContainer,
                NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
    
            assertPageableUniqueness(methodParameter);
    
            Pageable defaultOrFallback = getDefaultFromAnnotationOrFallback(methodParameter);
    
            String pageString = webRequest.getParameter(getParameterNameToUse(pageParameterName, methodParameter));
            // sizeParameterName="size",从请求中拿到size值
            String pageSizeString = webRequest.getParameter(getParameterNameToUse(sizeParameterName, methodParameter));
    
            boolean pageAndSizeGiven = StringUtils.hasText(pageString) && StringUtils.hasText(pageSizeString);
    
            if (!pageAndSizeGiven && defaultOrFallback == null) {
                return null;
            }
    
            int page = StringUtils.hasText(pageString) ? parseAndApplyBoundaries(pageString, Integer.MAX_VALUE, true)
                    : defaultOrFallback.getPageNumber();
            int pageSize = StringUtils.hasText(pageSizeString) ? parseAndApplyBoundaries(pageSizeString, maxPageSize, false)
                    : defaultOrFallback.getPageSize();
    
            // Limit lower bound
            pageSize = pageSize < 1 ? defaultOrFallback.getPageSize() : pageSize;
            // Limit upper bound
            // 无论上面怎么处理,pageSize>2000的话,pageSize=2000,否则就是pageSize的值
            pageSize = pageSize > maxPageSize ? maxPageSize : pageSize;
    
            Sort sort = sortResolver.resolveArgument(methodParameter, mavContainer, webRequest, binderFactory);
    
            // Default if necessary and default configured
            sort = sort == null && defaultOrFallback != null ? defaultOrFallback.getSort() : sort;
    
            return new PageRequest(page, pageSize, sort);
        }
    }
  • 自定义page配置来解决

    自定义size最大为10000

import org.springframework.context.annotation.Configuration;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

@Configuration
public class PageConfig extends WebMvcConfigurerAdapter {

    private static final int PMP_MAX_PAGE_SIZE = 10000;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();

        resolver.setMaxPageSize(PMP_MAX_PAGE_SIZE);
        argumentResolvers.add(resolver);
        super.addArgumentResolvers(argumentResolvers);
    }
}

 


来源于:

https://blog.youkuaiyun.com/u010634897/article/details/81612124

### 如何在 Spring Boot 中实现分页功能 #### 使用 Pageable 接口实现分页 为了实现在页面上显示大量数据时的灵活性和效率,在 Java 应用程序中可以利用 `Pageable` 接口来简化分页逻辑。此接口封装了分页所需的参数,比如当前页码(page number)、每页大小(page size),以及排序条件(sort conditions)[^3]。 下面是一个基于 Spring Data JPA 的简单例子: ```java // 定义仓库层接口继承 JpaRepository 并指定实体类及其主键类型 public interface UserRepository extends JpaRepository<User, Long> { // 可选:定义自定义查询方法,支持通过姓名模糊匹配并返回分页结果 Page<User> findByNameContaining(String name, Pageable pageable); } ``` 控制器部分则负责接收来自客户端请求中的分页参数,并调用服务层的方法获取相应范围的数据集: ```java @RestController @RequestMapping("/users") public class UserController { @Autowired private UserService userService; @GetMapping("") public ResponseEntity<Page<User>> getUsers( @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size, @RequestParam(defaultValue = "id") String sortBy){ Pageable paging = PageRequest.of(page, size, Sort.by(sortBy)); Page<User> pagedResult = userService.findAllUsers(paging); return new ResponseEntity<>(pagedResult, HttpStatus.OK); } } ``` 对于前端展示方面,如果采用的是 Thymeleaf 模板引擎,则可以在 HTML 文件里这样写入循环结构以遍历分页后的列表项[^2]: ```html <div th:each="user : ${page.content}"> <p th:text="${user.name}"></p> </div> <!-- 显示导航链接 --> <ul> <!-- 如果不是第一页就显示前一页按钮 --> <li th:if="${!page.first}" > <a href="#" th:href="@{/users(page=${page.number - 1})}">Previous</a> </li> <!-- 遍历总页数生成对应数字链接 --> <li th:each="i : ${#numbers.sequence(0, page.totalPages - 1)}"> <span th:class="${i == page.number} ? 'active' : ''"> <a href="#" th:href="@{/users(page=${i})}" th:text="${i + 1}"></a> </span> </li> <!-- 如果不是最后一页就显示下一页按钮 --> <li th:if="${!page.last}"> <a href="#" th:href="@{/users(page=${page.number + 1})}">Next</a> </li> </ul> ``` 以上就是使用 Spring Boot 结合其他框架和技术栈完成基本分页操作的方式之一。当然实际项目可能会更复杂一些,可能还会涉及到缓存机制优化性能等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值