《Spring Boot 实战》6.2 复杂查询的三种写法
派生查询、@Query(JPQL / native)与 Criteria、Querydsl 各有适用边界。本节用图书借阅服务的多条件检索场景对比三种写法的可维护性与类型安全,给出动态条件查询的落地方式、原生 SQL 的方言锁定代价,以及 4.x 下 Hibernate 7.x 的相关口径。
tag
派生查询、@Query(JPQL / native)与 Criteria、Querydsl 各有适用边界。本节用图书借阅服务的多条件检索场景对比三种写法的可维护性与类型安全,给出动态条件查询的落地方式、原生 SQL 的方言锁定代价,以及 4.x 下 Hibernate 7.x 的相关口径。
实体直接出现在接口层会带来懒加载代理序列化失败、字段泄露与循环引用三类事故。本节给出投影(interface / DTO)的用法与边界、手写转换与 MapStruct 的取舍、Repository 与 Service 的职责划分,以及 readOnly 事务与转换时机的关系。
每个接口都要记日志、查登录,写进 Controller 太啰嗦。本节对比 Filter(Servlet 规范)与 HandlerInterceptor(Spring MVC)的执行时机,用真实日志证明 Filter → Interceptor → Controller 的顺序,演示两种 Filter 注册方式与拦截器路径匹配,并完整实现请求 ID 贯穿与登录校验。
讲清 POST 为什么需要幂等键、幂等键的三种实现(唯一索引 / Redis 去重 / 状态机)各自的可靠性边界、乐观锁与 If-Match/ETag 的条件请求写法、并发写冲突用 409 还是 412 的取舍与重试语义,以及限流与防重各自解决什么问题。
围绕借阅服务的列表接口,讲清 Pageable 与 Page/Slice 的取舍、count 查询的真实代价、偏移分页的深分页问题与 keyset 分页的写法、过滤参数的表达方式、排序字段白名单如何同时防注入与防全表扫描,以及分页元信息的响应信封该怎么定。
把「图书借阅管理服务」的动作式接口重写成资源式接口:讲清资源命名的判据、URL 层级与扁平化的取舍、HTTP 方法与状态码的语义,以及批量操作、自定义动作和统一错误响应该在什么条件下破例,并给出可直接复用的 Controller 与 ProblemDetail 代码。
前端从 5173 端口调用 8080 的图书接口,浏览器报跨域,可服务端日志里请求明明到了。本节讲清同源策略拦的到底是谁、简单请求与预检请求的区别,贴出真实的 OPTIONS 预检头,演示 @CrossOrigin、addCorsMappings、CorsFilter 三种配置,并说透 allowedOriginPatterns 与 allowCredentials 的坑。
本节区分契约测试与集成测试的边界,说明消费者驱动契约在 Spring Cloud Contract 与 Pact 之间的选型,并给出数据隔离三策略(事务回滚、@Sql、每测试独立 schema/容器)的对比、测试数据构造规范,以及 @DirtiesContext 的真实代价。
本节解释内嵌 H2 为何会掩盖 PostgreSQL 方言差异,给出 Testcontainers 2.0 在 Spring Boot 4.x 下的依赖坐标、@ServiceConnection 用法与共享容器模式,讲清容器复用、CI 里 Docker 的可用性前提,并附镜像拉取、端口、健康检查三类失败的排查清单。
本节用图书借阅服务的借阅流程,把单元、切片、集成、端到端四层测试的成本与收益逐项拆开,给出各层配比与 CI 分阶段执行命令,并对齐 Spring Boot 4.x 的测试注解口径(@MockitoBean、RestTestClient、@AutoConfigureMockMvc),最后讲清测试并行与上下文缓存的取舍。
图书服务要加一个管理页面,HTML、CSS、JS 与封面图该放哪、用什么 URL 访问?本节讲清 Spring Boot 四个默认静态资源目录及优先级、默认 /** 映射规则,区分 static-locations 与 static-path-pattern,并演示自定义映射、缓存控制与内容哈希指纹,最后说清静态资源与接口路径冲突时谁优先。
本节权衡配置中心的收益与代价,比较 Spring Cloud Config、Nacos、Apollo 的定位差异,讲清 @RefreshScope 与 @ConfigurationProperties 在刷新行为上的关键区别,并给出刷新风暴、灰度发布与配置中心不可用时的降级策略。
本节从口令泄露的真实路径讲起:Git 历史、镜像层、进程参数、/proc 与日志各是怎么漏的;再比较环境变量与挂载文件的取舍,划清 Jasypt 这类加密方案的适用边界,给出 Vault / KMS / K8s Secret 的接入方式与密钥轮换对连接池、签名校验的实际影响。
入门卷讲过 application.yml 与 profile,本节解决生产上真正棘手的问题:环境维度如何划分、profile 组合与 group 怎么用、jar 内基线与外部覆盖如何分层、12-Factor 下哪些值该进环境变量,以及 spring.config.import 的组合语法与 4.1 新增的 encoding 参数。
设计一个 ApiResponse<T> 包装体,用 ResponseBodyAdvice 自动包装成功响应并避开泛型擦除与 String 转换器的坑,同时讨论统一响应体的代价——与 HTTP 状态码语义重复、对第三方客户端不友好、文件下载与 204 的例外,给出该用与不该用的判断依据,并输出一套完整实现与 curl 实测响应。
本节讲 Maven 构建加速:先给出定位慢在哪里的步骤,再逐项拆解跳过无用阶段、按模块增量构建、并行构建、依赖预拉与离线、CI 缓存本地仓库、镜像源与增量编译等手段,重点说明 4.1 中 -DskipTests 不再跳过测试 AOT 处理这一语义变化及替代写法。
本节讲 Spring Boot 多模块工程的版本对齐:对比 spring-boot-starter-parent 与 spring-boot-dependencies BOM 的引入方式与取舍,说明 import scope 的生效规则、如何自建 BOM 统一内部组件版本、如何用 properties 或显式声明覆盖托管版本,并汇总 4.x 各依赖的大版本变化与 4.0 移除的依赖管理。
本节用图书借阅服务 book-loan 的五模块工程讲透 Maven 依赖冲突排查:从 NoSuchMethodError 等症状反查依赖树,读懂 dependency:tree 的 omitted 与 conflict 标记,掌握最短路径优先与先声明优先两条调解规则,并给出 exclusions、dependencyManagement 与 dependency:analyze 的用法。
把异常处理从各控制器集中一处,用 @ControllerAdvice 与 @RestControllerAdvice 做全局处理,并用 basePackages、assignableTypes 等限定范围。还会改写框架内置异常(校验、JSON 解析、405、404),用 @Order 排优先级,并借 ResponseEntityExceptionHandler 统一内置异常响应。
讲清按功能分包与按层分包的取舍,给出图书借阅服务「模块边界 + 模块内按层」的分包方案,演示用 package-private 收窄暴露面、约束模块间依赖方向,并用 ArchUnit 把「禁止循环依赖」「领域层保持纯净」等架构约束固化成会在 CI 上失败的测试。