分页使用可以说非常普遍了,有时候会需要非常灵活的方式去开启或关闭分页,尝试使用一下注解的方式来进行分页。

依赖安装

需要使用的依赖:

  • Mybatis-Plus
  • PageHelper
  • SpringBoot AOP

添加pom依赖

<!-- Mybatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
<!-- 分页 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.0</version>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.5.5</version>
</dependency>

添加公共返回实体类

需要两种实体类,一种是不分页直接返回数据的,另一种是分页返回数据和总数据条数的

普通实体类 AjaxResult

@Data
@NoArgsConstructor
@AllArgsConstructor
public class AjaxResult<T> { public static final int CODE_SUCCESS = 200;
public static final int CODE_UNAUTHORIZED = 401;
public static final int CODE_FORBIDDEN = 403;
public static final int CODE_ERROR = 500; public static final String MSG_SUCCESS = "操作成功";
public static final String MSG_FAILED = "操作失败";
public static final String MSG_NOT_PERMISSION = "用户权限不足";
public static final String MSG_UNAUTHORIZED = "用户未登录或身份已过期"; private int code;
private String msg;
private T data; public static <T> AjaxResult success(int code, T data) {
return new AjaxResult(code, MSG_SUCCESS, data);
} public static <T> AjaxResult success(T data) {
return success(CODE_SUCCESS, data);
} public static <T> AjaxResult success() {
return success(CODE_SUCCESS, null);
} public static AjaxResult error(int code, String msg) {
return new AjaxResult(code, msg, null);
} public static AjaxResult error(String msg) {
return error(CODE_ERROR, msg);
} public static AjaxResult error() {
return new AjaxResult(CODE_ERROR, MSG_FAILED, null);
} }

分页实体类 PageResult

继承AjaxResult,额外添加total、pageNo和pageSize等字段

@Data
public class PageResult extends AjaxResult { private long total;
private long pageNo;
private long pageSize; public PageResult() {
this.setCode(CODE_SUCCESS);
this.setMsg(MSG_SUCCESS);
} public PageResult(AjaxResult ajaxResult) {
this();
if (Objects.nonNull(ajaxResult)) {
setCode(ajaxResult.getCode());
setMsg(ajaxResult.getMsg());
}
}
}

注解处理

分页注解 Pagination

创建一个用于分页的注解Pagination

其实这里的pageNo和pageSize没什么需求的话可以去掉的

/**
* 分页注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Pagination { // 第几页的请求参数名称 通过获取参数名称获取真正的pageNo
String pageNo() default "pageNo";
// 分页大小的请求参数名称
String pageSize() default "pageSize"; }

使用AOP进行分页

创建一个类用于处理分页注解,切入点要根据自己注解进行修改

@Aspect
@Component
@Slf4j
public class PaginationAspect { /**
* 定义切入点
*/
@Pointcut("@annotation(cn.montaro.social.aspect.annotation.Pagination)")
public void access() { } @SneakyThrows
@Around("access()")
public Object around(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
Pagination pagination = getPaginationAnnotation(joinPoint);
startPage(pagination.pageNo(), pagination.pageSize());
// 调用原本方法的内容并获取返回值
Object result = joinPoint.proceed(args);
// 返回的数据类型要保证和注解方法上的一致
return pageResult(result);
} /**
* 获取Pagination注解
*
* @param joinPoint
* @return
*/
public Pagination getPaginationAnnotation(ProceedingJoinPoint joinPoint) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
Pagination pagination = method.getAnnotation(Pagination.class);
return pagination;
} /**
* 开始分页
*/
private void startPage(String pageNoParameterName, String pageSizeParameterName) {
// 获取pageNo和pageSize
int pageNo = ServletUtils.getParameterToInt(pageNoParameterName, 1);
int pageSize = ServletUtils.getParameterToInt(pageSizeParameterName, 10);
PageHelper.startPage(pageNo, pageSize);
} /**
* 对分页结果进行包装 如果分页成功则会返回PageResult
*
* @param result
*/
private Object pageResult(Object result) {
/**
* 如果分页成功,则查询返回的结应该是一个Page {@link com.github.pagehelper.Page}
* 进行一次强制转换就能获取到 total、pageNo、pageSize 这些字段
*/
PageInfo pageInfo = null;
AjaxResult ajaxResult = null;
// 列表数据 如果方法返回Page则直接使用 如果是AjaxResult则getData再封装
Object list = null;
if (result instanceof Page) {
list = result;
Page page = (Page) result;
pageInfo = new PageInfo(page);
} else if (result instanceof AjaxResult) {
ajaxResult = (AjaxResult) result;
Object data = ajaxResult.getData();
if (data instanceof List) {
list = data;
pageInfo = new PageInfo((List) data);
}
}
if (pageInfo != null) {
PageResult pageResult = new PageResult(ajaxResult);
pageResult.setData(list);
pageResult.setPageNo(pageInfo.getPageNum());
pageResult.setPageSize(pageInfo.getPageSize());
pageResult.setTotal(pageInfo.getTotal()); return pageResult;
}
return result;
}
}

还有注解中使用到的ServletUtils

public class ServletUtils {

    public static HttpServletRequest getRequest() {
ServletRequestAttributes requestAttributes = getRequestAttributes();
return requestAttributes.getRequest();
} public static ServletRequestAttributes getRequestAttributes() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) requestAttributes;
} public static Integer getParameterToInt(String parameterName, Integer defaultValue) {
HttpServletRequest request = getRequest();
String strValue = request.getParameter(parameterName);
Integer intValue = Convert.toInt(strValue, defaultValue);
return intValue;
} public static Integer getParameterToInt(String parameterName) {
return getParameterToInt(parameterName, null);
} }

使用注解

为了避免跑题,此处就省略mybatis-plus的使用了。

需要分页就加上@Pagination注解就行了,不需要就注释掉,代码完全不需要修改

分页的时候传入pageNo和pageSize参数就可以了,如果参数名需要更改,就修改@Pagination就可以了

编写Controller类

@RestController
@RequestMapping("/user")
public class UserController { @Autowired
private IUserService userService; /**
* 列出所有用户
* @return
*/
@Pagination
@GetMapping("/list")
public AjaxResult list(UserQueryReq query) {
List<User> userList = userService.selectUserListByQuery(query);
return AjaxResult.success(userList);
} }

测试

使用的PostMan,看看效果

使用注解的时候

把注解注释掉

效果可以说非常完美了!

博主也是菜鸟一枚,如果有什么问题欢迎留言互相讨论

SpringBoot使用注解进行分页的更多相关文章

  1. SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页

    SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页 **SpringBoot+Mybatis使用Pagehelper分页插件自动分页,非常好用,不用在自己去计算和组装了. ...

  2. SpringBoot+Mybatis+PageHelper实现分页

    SpringBoot+Mybatis+PageHelper实现分页 mybatis自己没有分页功能,我们可以通过PageHelper工具来实现分页,非常简单方便 第一步:添加依赖 <depend ...

  3. SpringBoot 常用注解(持续更新)

    SpringBoot 常用注解 @SpringBootApplication @Bean @ComponentScan @ControllerAdvice @ExceptionHandler @Res ...

  4. 常见的springmvc、SpringBoot的注解

    springMvc的常用注解 : @Controller :用于标记在一个类上,使用它标记的类就是一个springmcv Controller对象,分发处理器将会扫描使用了该注解 的类的方法,并检测该 ...

  5. 浅谈SpringBoot核心注解原理

    SpringBoot核心注解原理 今天跟大家来探讨下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot为什么不需要XML,达到零配置 ...

  6. SpringBoot的注解注入功能移植到.Net平台(开源)

    *:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !impor ...

  7. SpringBoot(14)—注解装配Bean

    SpringBoot(14)-注解装配Bean SpringBoot装配Bean方式主要有两种 通过Java配置文件@Bean的方式定义Bean. 通过注解扫描的方式@Component/@Compo ...

  8. SpringBoot 入门篇(二) SpringBoot常用注解以及自动配置

    一.SpringBoot常用注解二.SpringBoot自动配置机制SpringBoot版本:1.5.13.RELEASE 对应官方文档链接:https://docs.spring.io/spring ...

  9. [技术博客] SPRINGBOOT自定义注解

    SPRINGBOOT自定义注解 在springboot中,有各种各样的注解,这些注解能够简化我们的配置,提高开发效率.一般来说,springboot提供的注解已经佷丰富了,但如果我们想针对某个特定情景 ...

随机推荐

  1. Vivado实战—单周期CPU指令分析

    引言   不知道你是否和我有过同样的感受,<计算机组成原理>这门学科学起来如此的艰难:一节课下来,教室黑板上留下了满满的 "足迹",看上去也挺简单的,不就是 0 和 1 ...

  2. 备忘:Linux内核编程的几个注意事项

    虚拟地址转物理地址要用__pa 内核程序创建的一段地址连续的共享内存,通过内存映射可以让用户态进程存取.之前在RHEL/CentOS的x86_64架构上工作正常.后来在aarch64架构的银河麒麟(L ...

  3. Python:MySQL拒绝从远程访问的解决方法

    MySQL连接数据库 #!/usr/bin/python # -*- coding: UTF-8 -*- import pymysql # 打开数据库连接 db = pymysql.connect(& ...

  4. SpringBoot笔记(3)

    一.配置文件 1.文件类型 1.1.properties 同以前的properties用法 1.2.yaml 1.2.1.简介 YAML 是 "YAML Ain't Markup Langu ...

  5. python之数据库编程

    python之数据库编程 sqlite 1.前期准备工作 导入模块: import sqlite3 连接数据库 conn = sqlite3.connect("test.db") ...

  6. IO流学习笔记(一)之FileWriter与FileReader

    IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都在IO包中 流按照操作数据分为两种:字节流和字符流 流按流向分为:输入流和输出流 输入流和输出流是相对于 ...

  7. Python之requests模块-大文件分片上传

    最近在做接口测试时,拿到一个分片上传文件的接口,http接口请求头中的Content-Type为multipart/form-data.需要在客户端将大文件分片成数据块后,依次传给服务端,由服务端还原 ...

  8. 使用 Dockerfile 自定义 Nginx 镜像

    一般来说,自定义Nginx只需要把静态文件放到镜像里就可以了,不需要重写 CMD 与 ENTRYPOINT.但是,如果的确需要在 Nginx 启动前执行一些操作,就需要重写 CMD 了,如果写成下边就 ...

  9. Spring中使用@within与@target的一些区别

    目录 背景 模拟项目例子 看看使用@within和@target的区别 @within @target @target 看起来跟合理一点 通知方法中注解参数的值为什么是不一样的 想用@within,但 ...

  10. redis的集群安装

    1.创建安装目录 在master ,node1 ,node2中分别创建 mkdir /usr/local/soft/redis-cluster 2.将redis 复制到redis-cluster 目录 ...