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