当前位置: 首页 > article >正文

别再写重复的Controller了!Spring Boot 3.x + Pageable 实现分页查询的5个最佳实践

Spring Boot 3.x分页查询工程化实践从Controller优化到架构设计每次打开IDE看到那些重复的分页查询代码我都忍不住想重构。分页查询作为业务系统的高频操作却在大多数项目中以最原始的方式被复制粘贴。今天我们就来聊聊如何用Spring Boot 3.x和Pageable打造一套工程化的分页解决方案让你的代码摆脱CtrlC/V的诅咒。1. 分页参数处理的标准化改造传统分页代码最让人头疼的就是满屏的pageNum和pageSize参数校验。在Spring Boot 3.x中我们可以通过自定义参数解析器来统一处理这些重复逻辑。首先创建分页参数DTOpublic class PageParam { Min(1) private int page 1; Max(100) private int size 10; private String sort; // getters/setters }然后实现HandlerMethodArgumentResolverpublic class PageableArgumentResolver implements HandlerMethodArgumentResolver { Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType().equals(Pageable.class); } Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { HttpServletRequest request (HttpServletRequest) webRequest.getNativeRequest(); int page Integer.parseInt(request.getParameter(page)); int size Integer.parseInt(request.getParameter(size)); String sort request.getParameter(sort); return PageRequest.of(page - 1, size, Sort.by(sort)); } }注册解析器Configuration public class WebConfig implements WebMvcConfigurer { Override public void addArgumentResolvers(ListHandlerMethodArgumentResolver resolvers) { resolvers.add(new PageableArgumentResolver()); } }现在Controller可以简化为GetMapping(/users) public PageUser getUsers(Pageable pageable) { return userService.findAll(pageable); }2. 响应体的统一封装艺术直接返回Spring Data的Page对象会暴露过多实现细节我们需要自定义响应结构public class PageResultT { private ListT content; private Pagination pagination; public static T PageResultT of(PageT page) { PageResultT result new PageResult(); result.setContent(page.getContent()); Pagination pagination new Pagination(); pagination.setPage(page.getNumber() 1); pagination.setSize(page.getSize()); pagination.setTotalPages(page.getTotalPages()); pagination.setTotalElements(page.getTotalElements()); result.setPagination(pagination); return result; } // 省略getter/setter }配合全局响应处理器RestControllerAdvice public class ResponseAdvice implements ResponseBodyAdviceObject { Override public boolean supports(MethodParameter returnType, Class? extends HttpMessageConverter? converterType) { return true; } Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class? extends HttpMessageConverter? selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if (body instanceof Page) { return PageResult.of((Page?) body); } return body; } }3. 复杂查询条件的优雅处理当分页遇上多条件查询时代码很容易变得臃肿。我们可以使用Specification来保持代码整洁public class UserSpecifications { public static SpecificationUser nameLike(String name) { return (root, query, cb) - name null ? null : cb.like(root.get(name), % name %); } public static SpecificationUser ageBetween(Integer minAge, Integer maxAge) { return (root, query, cb) - { if (minAge null maxAge null) return null; if (minAge ! null maxAge ! null) { return cb.between(root.get(age), minAge, maxAge); } else if (minAge ! null) { return cb.greaterThanOrEqualTo(root.get(age), minAge); } else { return cb.lessThanOrEqualTo(root.get(age), maxAge); } }; } }Service层使用public PageResultUser searchUsers(String name, Integer minAge, Integer maxAge, Pageable pageable) { SpecificationUser spec Specification.where(UserSpecifications.nameLike(name)) .and(UserSpecifications.ageBetween(minAge, maxAge)); return PageResult.of(userRepository.findAll(spec, pageable)); }4. 分页逻辑的AOP抽象对于需要分页的Service方法我们可以用自定义注解实现声明式分页Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) public interface Paginate { String pageParam() default page; String sizeParam() default size; String sortParam() default sort; }实现切面逻辑Aspect Component public class PaginationAspect { Around(annotation(paginate)) public Object around(ProceedingJoinPoint joinPoint, Paginate paginate) throws Throwable { Object[] args joinPoint.getArgs(); // 从参数中提取分页信息 Pageable pageable extractPageable(args, paginate); // 执行原方法 Object result joinPoint.proceed(args); // 处理返回结果 if (result instanceof List) { return PageResult.of(new PageImpl((List?) result, pageable, ((List?) result).size())); } return result; } private Pageable extractPageable(Object[] args, Paginate paginate) { // 实现参数提取逻辑 } }使用示例Paginate public ListUser findActiveUsers() { return userRepository.findByActiveTrue(); }5. 性能优化与特殊场景处理分页查询在高并发场景下容易成为性能瓶颈这里有几个优化技巧COUNT查询优化Query(value SELECT u FROM User u LEFT JOIN FETCH u.department, countQuery SELECT COUNT(u.id) FROM User u) PageUser findAllWithDepartment(Pageable pageable);游标分页实现public interface UserRepository extends JpaRepositoryUser, Long { SliceUser findFirst10ByOrderByIdAsc(Long lastId); }批量ID查询优化Query(SELECT u FROM User u WHERE u.id IN :ids) ListUser findByIds(Param(ids) ListLong ids, Sort sort); public PageResultUser findUsers(Pageable pageable) { PageLong ids userRepository.findUserIds(pageable); ListUser content userRepository.findByIds(ids.getContent(), pageable.getSort()); return new PageResult(content, ids.getTotalElements()); }这些方案在数据量达到百万级时性能差异可以达到10倍以上。

相关文章:

别再写重复的Controller了!Spring Boot 3.x + Pageable 实现分页查询的5个最佳实践

Spring Boot 3.x分页查询工程化实践:从Controller优化到架构设计 每次打开IDE看到那些重复的分页查询代码,我都忍不住想重构。分页查询作为业务系统的高频操作,却在大多数项目中以最原始的方式被复制粘贴。今天我们就来聊聊如何用Spring Boot…...

告别Matlab!用C++和OpenCV手把手实现光学PSD分析(附完整代码与避坑指南)

告别Matlab!用C和OpenCV手把手实现光学PSD分析(附完整代码与避坑指南) 在光学测量领域,工程师们常常面临一个两难选择:是继续依赖Matlab的便捷生态,还是转向C的高性能世界?特别是在处理像功率谱…...

5分钟掌握StreamFX:让OBS直播画面瞬间升级电影级特效

5分钟掌握StreamFX:让OBS直播画面瞬间升级电影级特效 【免费下载链接】obs-StreamFX StreamFX is a plugin for OBS Studio which adds many new effects, filters, sources, transitions and encoders! Be it 3D Transform, Blur, complex Masking, or even custom…...

实战分享:用YOLOv5s+小目标检测头搞定红外图像里的‘小不点’(附数据集处理与模型改进)

实战分享:用YOLOv5s小目标检测头搞定红外图像里的‘小不点’(附数据集处理与模型改进) 红外图像中的小目标检测一直是计算机视觉领域的难点问题。与常规RGB图像相比,红外图像具有低对比度、高噪声等特点,这使得传统目标…...

【AI实战解析】从公式到应用:深入理解三元组损失(Triplet Loss)的优化之道

1. 为什么我们需要三元组损失? 想象一下你在教小朋友认识动物。如果每次只给小朋友看一张猫的图片,然后告诉他"这是猫",他可能很难真正理解猫的特征。但如果你同时展示一张猫(锚点)、另一张猫(正…...

CefFlashBrowser终极指南:如何让消失的Flash世界重现生机

CefFlashBrowser终极指南:如何让消失的Flash世界重现生机 【免费下载链接】CefFlashBrowser Flash浏览器 / Flash Browser 项目地址: https://gitcode.com/gh_mirrors/ce/CefFlashBrowser 你是否还记得那些经典的Flash游戏?那些曾经在4399、7K7K等…...

Stable Yogi Leather-Dress-Collection步骤详解:从下载镜像到生成首张皮衣图

Stable Yogi Leather-Dress-Collection步骤详解:从下载镜像到生成首张皮衣图 1. 工具简介 Stable Yogi Leather-Dress-Collection是一款基于Stable Diffusion v1.5和Anything V5动漫底座模型开发的2.5D皮衣穿搭生成工具。它能让你轻松创建各种风格的动漫皮衣穿搭图…...

游戏关卡设计难度曲线与玩家引导

游戏关卡设计难度曲线与玩家引导:打造流畅体验的艺术 在游戏设计中,关卡难度曲线与玩家引导是决定玩家体验的核心要素。一个合理的难度曲线能让玩家在挑战中收获成就感,而巧妙的引导则能帮助玩家自然掌握游戏机制。这两者的平衡直接影响玩家…...

sentence-transformers 3.3.1新特性解析:model.similarity()方法实战教程

sentence-transformers 3.3.1新特性深度解析:model.similarity()方法实战指南 自然语言处理领域的技术迭代总是令人兴奋。最近sentence-transformers 3.3.1版本带来的model.similarity()方法,为文本相似度计算提供了更优雅的解决方案。这个看似简单的API…...

Java的java.util.SequencedCollection序列集合与双向迭代的新增接口

Java 21引入的java.util.SequencedCollection接口为集合框架带来了革命性升级,它重新定义了有序集合的操作范式,同时通过双向迭代能力填补了Java集合API长期存在的功能空白。这一变化不仅简化了开发者的日常编码,更为处理序列化数据提供了标准…...

使用LaTeX与PDF-Extract-Kit-1.0构建学术写作工具链

使用LaTeX与PDF-Extract-Kit-1.0构建学术写作工具链 1. 学术写作的痛点与解决方案 写论文最头疼的是什么?对我来说,绝对是处理参考文献和公式。每次看到一篇好论文,想要引用里面的观点或者复用某个复杂的公式,都得手动一个个敲进…...

抖音无水印下载终极指南:douyin-downloader 完整实战教程

抖音无水印下载终极指南:douyin-downloader 完整实战教程 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback su…...

终极解决方案:在Windows 10/11中免费启用HEIC缩略图预览的完整指南

终极解决方案:在Windows 10/11中免费启用HEIC缩略图预览的完整指南 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC/HEIF files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails 你…...

构建百度网盘直链解析系统:从限速瓶颈到高速下载的技术实现

构建百度网盘直链解析系统:从限速瓶颈到高速下载的技术实现 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 在当今数字资源共享的时代,百度网盘作为国内…...

终极显卡驱动清理指南:如何用DDU彻底解决Windows驱动残留问题

终极显卡驱动清理指南:如何用DDU彻底解决Windows驱动残留问题 【免费下载链接】display-drivers-uninstaller Display Driver Uninstaller (DDU) a driver removal utility / cleaner utility 项目地址: https://gitcode.com/gh_mirrors/di/display-drivers-unins…...

eslint-plugin-simple-import-sort高级用法:处理类型导入与注释的最佳实践

eslint-plugin-simple-import-sort高级用法:处理类型导入与注释的最佳实践 【免费下载链接】eslint-plugin-simple-import-sort Easy autofixable import sorting. 项目地址: https://gitcode.com/gh_mirrors/es/eslint-plugin-simple-import-sort eslint-pl…...

题解:洛谷 P3371 【模板】单源最短路径(弱化版)

本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。 欢迎大家订阅我的专栏:算法…...

如何在3分钟内为Figma安装中文界面插件:设计师的完整指南

如何在3分钟内为Figma安装中文界面插件:设计师的完整指南 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 对于中文设计师来说,使用Figma时最大的障碍往往是英文界…...

矽力杰 SQ20953 高效率快响应同步降压转换器 规格书 佰祥电子

突破终端网络与消费电子供电 3 大核心痛点!SQ20953:宽压输入 大电流输出的五大核心优势作为设备供电的核心组件,电源管理芯片的稳压、能效控制、安全防护能力直接决定终端产品的稳定性、能效水平与小型化程度。作为矽力杰核心合作代理商&…...

深度解析roop-unleashed:开源AI视频换脸工具的技术架构与实战应用

深度解析roop-unleashed:开源AI视频换脸工具的技术架构与实战应用 【免费下载链接】roop-unleashed Evolved Fork of roop with Web Server and lots of additions 项目地址: https://gitcode.com/gh_mirrors/ro/roop-unleashed roop-unleashed是一个基于深度…...

终极指南:如何使用QMCDecode快速解锁QQ音乐加密音频文件

终极指南:如何使用QMCDecode快速解锁QQ音乐加密音频文件 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac,qmc0,qmc3转mp3, mflac,mflac0等转flac),仅支持macOS,可自动识别到QQ音乐下载目录,默认…...

AI人脸隐私卫士问题解决:小脸侧脸漏检优化方案

AI人脸隐私卫士问题解决:小脸侧脸漏检优化方案 1. 引言 1.1 人脸隐私保护的挑战 在当今数字时代,图像和视频内容大量传播的同时,人脸隐私保护问题日益突出。特别是在多人合照、远距离拍摄等场景中,传统人脸检测技术往往难以准确…...

别再只懂UserCF了!用Python手撸一个ItemCF电影推荐器(附完整代码与数据集)

从原理到实战:用Python构建ItemCF电影推荐系统的完整指南 推荐系统已经成为互联网产品的标配功能,从电商平台到流媒体服务,个性化推荐无处不在。在众多推荐算法中,基于物品的协同过滤(ItemCF)因其直观的解释…...

【含文档+PPT+源码】基于SpringBoot的线上动物园售票系统设计

项目介绍本课程演示的是一款 基于SpringBoot的线上动物园售票系统设计,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料2.带你从零开始部署运行本套系统3.该项目…...

Kook Zimage真实幻想Turbo效果展示:幻想风格人物眼神光/皮肤次表面散射/布料物理模拟

Kook Zimage真实幻想Turbo效果展示:幻想风格人物眼神光/皮肤次表面散射/布料物理模拟 1. 项目概述 Kook Zimage真实幻想Turbo是一款专门为个人GPU设计的轻量化幻想风格图像生成系统。这个项目基于Z-Image-Turbo的快速生成架构,深度融合了专属的幻想风格…...

ESP32构建多客户端TCP服务端:从基础配置到并发处理实战

1. ESP32多客户端TCP服务端入门指南 想象一下你家里有十几个智能设备——温湿度传感器、门窗磁感应器、智能灯泡,它们都需要把数据传到一个中央控制器。如果每个设备都单独连接,不仅效率低还容易混乱。ESP32的多客户端TCP服务端功能就是为解决这个问题而…...

ClawdBot新手入门:无需代码基础,快速搭建AI对话系统

ClawdBot新手入门:无需代码基础,快速搭建AI对话系统 1. 什么是ClawdBot:你的个人AI助手 ClawdBot是一个可以在本地设备上运行的AI对话系统,它让你无需依赖任何云服务就能拥有一个智能助手。想象一下,在你的电脑上安装…...

Windows热键侦探:揪出占用你快捷键的“隐身者“

Windows热键侦探:揪出占用你快捷键的"隐身者" 【免费下载链接】hotkey-detective A small program for investigating stolen key combinations under Windows 7 and later. 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 你是否…...

【AI应用不死协议】:从训练权重到推理缓存,全链路备份的6个隐性失效点与修复清单

第一章:生成式AI应用容灾备份方案 2026奇点智能技术大会(https://ml-summit.org) 生成式AI应用的高可用性不仅依赖模型推理服务的弹性伸缩,更取决于底层数据、权重、提示工程资产及用户交互历史的跨地域一致性保护。当大语言模型服务遭遇区域级中断&…...

LFM2.5-1.2B-Thinking-GGUF部署教程:Docker镜像定制与端口映射最佳实践

LFM2.5-1.2B-Thinking-GGUF部署教程:Docker镜像定制与端口映射最佳实践 1. 模型简介与部署价值 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型,专为低资源环境优化设计。相比传统大模型,它具有以下显著优势: …...