easy-paging¶
Annotation-driven pagination for Spring Boot + MyBatis. Offset (PageHelper) and keyset/cursor in one starter.
Get Started GitHub Maven Central
At a glance¶
Drop one annotation on a controller method and get a JSON-ready paginated response. With the standard Controller → Service → Mapper layering, the controller stays thin:
@RestController
class ReportController {
private final ReportService reports;
ReportController(ReportService reports) {
this.reports = reports;
}
@GetMapping("/reports")
@AutoPaginate(maxSize = 50) // (1)!
public PageResponse<Report> list(Pageable pageable) {
return PageResponse.from(reports.findAll(), pageable);
}
}
- The aspect sets up PageHelper's per-thread state, validates the sort parameter, clamps the page size, then cleans up after the mapper call returns.
A request to GET /reports?page=0&size=20&sort=createdAt,desc returns:
{
"content": [ /* 20 rows */ ],
"page": 0,
"size": 20,
"totalElements": 137,
"totalPages": 7,
"first": true,
"last": false,
"empty": false
}
No PageHelper.startPage(...) calls scattered through your codebase, no ThreadLocal cleanup to remember, no per-controller boilerplate.
What you get¶
-
Safe by default
?sort=name;DROP TABLErejected with HTTP 400 before reaching the database. Page size clamped at endpoint + global level. -
Spring Data shaped
JSON response matches Spring Data
Pagefor client compatibility. Drop-in for teams already usingPageable. -
Offset and keyset
@AutoPaginatefor traditional lists,@KeysetPaginatefor time-series and unbounded tables whereOFFSET/COUNT(*)start to hurt. -
0-based, consistent
Spring Data convention throughout — request, response, and internal
Pageable. PageHelper's 1-based indexing handled transparently. -
Pluggable response shape
Replace the default envelope with your company's standard response type via
PageResponseFactory, or just define your own type with a staticfrom()method. -
Virtual Threads safe
Internal state cleaned up on every request, regardless of exception path. No
ThreadLocalleaks. -
Reactive: WebFlux + R2DBC
Optional
…-starter-reactiveartifact:Mono<PageResponse<T>>fromR2dbcEntityTemplate, keyset helper for cursor scrolls, and a WebFluxKeysetRequestargument resolver. Same envelope as the MyBatis side.
Quick install¶
dependencies {
// Spring Boot 4 line (current — main branch):
implementation("kr.devslab:easy-paging-spring-boot-starter:4.0.0")
// Optional — native R2DBC + WebFlux helpers:
// implementation("kr.devslab:easy-paging-spring-boot-starter-reactive:4.0.0")
// Spring Boot 3.3–3.5 maintenance line (use this if you're not on SB4 yet):
// implementation("kr.devslab:easy-paging-spring-boot-starter:3.0.0")
}
See Installation for the release-line picker, prerequisites, and full setup, or jump to the Tutorial for a 5-minute walkthrough.