Skip to content

自定义Pagehelper分页注解

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1、新增注解

java
package com.xx.page.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/8 15:54
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedPage {
}

2、新增统一返回类型

java
package com.xx.result;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.xx.page.context.PageData;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;

import java.io.Serializable;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/8 16:01
 */
@Data
@Tag(name = "接口返回对象")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result<T> implements Serializable {

    private final static int SUCCESS_CODE = 200;

    /**
     * 成功标志
     */
    @Schema(description = "成功标志")
    private boolean success = true;

    /**
     * 返回处理消息
     */
    @Schema(description = "返回处理消息")
    private String message = "";

    /**
     * 返回代码
     */
    @Schema(description = "返回代码")
    private Integer code = 200;

    /**
     * 返回数据对象 data
     */
    @Schema(description = "返回数据对象")
    private T result;

    /**
     * 时间戳
     */
    @Schema(description = "时间戳")
    private long timestamp = System.currentTimeMillis();

    @Schema(description = "分页信息")
    private PageData pageData;

    public Result() {
    }


    public static <T> Result<T> ok(T data) {
        Result<T> r = new Result<T>();
        r.setSuccess(true);
        r.setCode(SUCCESS_CODE);
        r.setResult(data);
        return r;
    }

    public Result(T data) {
        this.success = true;
        this.result = data;
    }
}

3、PageData

java
package com.xx.page.context;

import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/8 15:56
 */
@Data
@Tag(name = "分页信息")
public class PageData {

    @Schema(description = "当前页")
    private int pageNum;

    @Schema(description = "每页的数量")
    private int pageSize;

    @Schema(description = "总条数")
    private long total;

    @Schema(description = "当前页的数量")
    private int size;

    @Schema(description = "当前页面第一个元素在数据库中的行号")
    private long startRow;

    @Schema(description = "当前页面最后一个元素在数据库中的行号")
    private long endRow;

    @Schema(description = "总页数")
    private int pages;

    @Schema(description = "前一页")
    private int prePage;

    @Schema(description = "下一页")
    private int nextPage;

    @Schema(description = "是否为第一页")
    private boolean isFirstPage;

    @Schema(description = "是否为最后一页")
    private boolean isLastPage;

    @Schema(description = "是否有前一页")
    private boolean hasPreviousPage;

    @Schema(description = "是否有下一页")
    private boolean hasNextPage;

    @Schema(description = "导航页码数")
    private int navigatePages;

    @Schema(description = "所有导航页号")
    private int[] navigatepageNums;

    @Schema(description = "导航条上的第一页")
    private int navigateFirstPage;

    @Schema(description = "导航条上的最后一页")
    private int navigateLastPage;
}

4、PageBean

java
package com.xx.page.context;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/8 15:55
 */
@Data
public class PageBean implements Serializable {

    private static final long serialVersionUID = 1756299910204595855L;

    // 当前页
    private Integer currentPage;
    // 每页显示的总条数
    private Integer pageSize;
    // 总条数
    private Integer totalNum;
    // 是否有下一页
    private Integer isMore;
    // 总页数
    private Integer totalPage;
    // 开始索引
    private Integer startIndex;
    // 分页结果
    private List<Object> items;
}

5、PageDataUtil

java
package com.xx.utils;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/8 16:06
 */
public class PageDataUtil {

    public static final String PAGE_TOTAL_ROWS_STR = "totalRows";

    public static final String PAGE_CURRENT_PAGE_NO_STR = "pageNo";

    public static final String PAGE_SIZE_STR = "pageSize";

    public static final String ORDER_BY_STR = "orderBy";

    public static final String ORDER_TYPE_STR = "orderType";

    public static final String ATTR_PAGE_INFO_STR = "queryPageInfo";

    public static final String JUST_ORDER_BY_STR = "justOrderBy";
}

6、ServletUtil

java
package com.xx.utils;

import cn.hutool.core.convert.Convert;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/8 16:05
 */
public class ServletUtil {

    /**
     * 获取String参数
     */
    public static String getParameter(String name) {
        return getHttpRequest().getParameter(name);
    }

    /**
     * 获取String参数
     */
    public static String getParameter(String name, String defaultValue) {
        return Convert.toStr(getHttpRequest().getParameter(name), defaultValue);
    }

    /**
     * 获取Integer参数
     */
    public static Integer getParameterToInt(String name) {
        return Convert.toInt(getHttpRequest().getParameter(name));
    }

    /**
     * 获取Integer参数
     */
    public static Integer getParameterToInt(String name, Integer defaultValue) {
        return Convert.toInt(getHttpRequest().getParameter(name), defaultValue);
    }

    /**
     * get the http servlet request
     *
     * @return
     */
    public static HttpServletRequest getHttpRequest() {
        RequestAttributes ra = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)ra).getRequest();
        return request;
    }
}

7、PageDataInterceptor

java
package com.xx.page.interceptor;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xx.page.annotation.NeedPage;
import com.xx.page.context.PageBean;
import com.xx.page.context.PageData;
import com.xx.result.Result;
import com.xx.utils.PageDataUtil;
import com.xx.utils.ServletUtil;
import com.xx.utils.ValidationUtil;
import com.xx.utils.ValueUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/8 15:58
 */
@Component
@Aspect
public class PageDataInterceptor {

    public Logger log = LoggerFactory.getLogger(PageDataInterceptor.class);

    @Pointcut("@annotation(com.xx.page.annotation.NeedPage)")
    public void controllerAspect() {
    }

    @Around("controllerAspect()")
    public Result controllerAop(ProceedingJoinPoint proJoinPoint) throws Throwable {
        log.info("==========> controller正在执行PageHelperAop");
        HttpServletRequest request = ServletUtil.getHttpRequest();
        int currentPage = getIntParameter(request, PageDataUtil.PAGE_CURRENT_PAGE_NO_STR, 1);
        int pageSize = getIntParameter(request, PageDataUtil.PAGE_SIZE_STR, 10);
        PageBean pageBean = new PageBean();
        pageBean.setCurrentPage(currentPage);
        pageBean.setPageSize(pageSize);
        Page<Object> page = PageHelper.startPage(pageBean.getCurrentPage(), pageBean.getPageSize());
        return handlePage(proJoinPoint, page);
    }

    private static int getIntParameter(HttpServletRequest request, String paramName, Integer defaultVal) {
        String paramValue = request.getParameter(paramName);
        if (ValidationUtil.isEmpty(paramValue)) {
            return defaultVal;
        }
        return Integer.parseInt(paramValue);
    }

    private Result handlePage(ProceedingJoinPoint proJoinPoint, Page<Object> page) throws Throwable {
        MethodSignature methodSign = (MethodSignature) proJoinPoint.getSignature();
        NeedPage needPageAnno = methodSign.getMethod().getAnnotation(NeedPage.class);
        Object retVal = proJoinPoint.proceed();
        if (ValidationUtil.isEmpty(needPageAnno) ||
                retVal == null || !(retVal instanceof Result)
                || !((Result) retVal).isSuccess()) {
            return Result.ok(retVal);
        }
        Result returnResult = (Result) retVal;
        if (!(returnResult.getResult() instanceof List)) {
            return returnResult;
        }
        //List resultList = (List) returnResult.getData();
        //if(ValidationUtil.isEmpty(resultList)){
        //    return new ResultData(resultList);
        //}
        PageInfo pageInfo = new PageInfo<>(page);
        PageData pageData = ValueUtil.copyFieldValue(pageInfo, PageData.class);
        returnResult.setPageData(pageData);
        return returnResult;
    }

}
java
@GetMapping("/listPage3")
@Operation(summary = "分页查询3")
@Parameters({
        @Parameter(name = "pageNo", description = "页数", required = true, in = ParameterIn.QUERY),
        @Parameter(name = "pageSize", description = "每页条数", required = true, in = ParameterIn.QUERY),
})
@NeedPage
public Result listPage3() {
    List<GradeModel> list = gradeService.list();
    return Result.ok(list);
}

9、项目配置

1、pom.xml

xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>dtx_test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.0</version>
        <relativePath/>
    </parent>

    <properties>
        <!--  依赖版本号 -->
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--  组件版本号 -->
        <hutool.version>5.8.16</hutool.version>
        <druid.version>1.1.18</druid.version>
        <persistence-api.version>1.0.2</persistence-api.version>
        <mysql.version>8.0.27</mysql.version>
        <swagger3.version>3.0.0</swagger3.version>
        <mybatis-plus.spring.version>3.5.3</mybatis-plus.spring.version>
        <lombok.version>1.18.26</lombok.version>
        <boottest.version>3.0.5</boottest.version>
    </properties>

    <dependencies>
        <!--web + actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--swagger3-->
        <!--<dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.1.0</version>
        </dependency>-->

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.spring.version}</version>
        </dependency>

        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>

        <!--persistence-->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>${persistence-api.version}</version>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--boot-test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--hutool-all-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
        </dependency>

        <dependency>
            <groupId>com.xx</groupId>
            <artifactId>xx-common-core</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2、application.yml

properties
server:
  port: 7777
  servlet:
    context-path: /dtx-test
spring:
  application:
    name: dtx_test
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/xx_db2023?connectTimeout=6000&socketTimeout=6000&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: mac_root
#  main:
#    allow-circular-references: true

# mybatis-plus相关配置
mybatis-plus:
#  global-config:
#    db-config:
#      id-type: auto
  # xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
  mapper-locations: classpath:mapper/*Mapper.xml
  # type-enums-package: com.xx.enums
  configuration:
    # 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
    map-underscore-to-camel-case: true
    # 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
    call-setters-on-nulls: true
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    cache-enabled: true

    db-config:
      logic-delete-field: del_flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

#Mybatis输出sql日志
logging:
  level:
    com.xx.mapper: info

#xxl-job配置
xxl:
  job:
    admin:
      addresses: http://127.0.0.1:8080/xxl-job-admin
    accessToken: default_token
    executor:
      appname: xxl-job-executor-dtx
      address:
      ip:
      port: 9988
      logpath: ./xxl-job/jobhandler
      logretentiondays: 30

写在最后

也许此刻的你还在为技术难题而苦恼,也许你正面临个人项目中的重重挑战,但请记住,每一次的努力都不会白费,每一滴汗水都将浇灌出成功的花朵。就像那破土而出的春笋,即使在黑暗的土壤中历经磨难,最终也能在阳光下茁壮成长。