springboot结合aop和pagehelper实现分页筛选排序功能

2023-11-18

一、前言

首先我们要知道什么是aop,什么是pagehelper

从而我们知道,pagehelper的实现其实是两行代码

 PageHelper.startPage(pageNum, pageSize);  // 开始分页 
 PageInfo pageInfo = new PageInfo(userList);  // 返回分页

实现思路:

在前置切面里面就开始PageHelper.startPage(pageNum, pageSize);
然后定义一个同一的返回类,然后在返回类里面定义一个分页结果的方法;

二、实现

一些工具类的使用,看文章

实现步骤:

  1. 定义一个BaseController,存放所有的controller通用的东西
  2. 定义一个分页工具类
  3. 定义一个分页实体类,存储分页信息
  4. 定义一个分页数据返回类,在BaseController里面指定返回的类
  5. 定义前置切面以及切入点注解,执行分页开始的操作

2.1.定义一个BaseController,存放所有的controller通用的东西

public class BaseController {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());



    protected Response response(){
        return IMediaCenterSpringController.responseFactory.createResponse();
    }

    /**
     * 统一封装 onComplete, 简化调用方代码
     * @param result
     * @return
     */
    protected Response onComplete(Object result){
        Response response = response();
        response.onComplete(result);
        return response;
    }
	
	/**
     * 分页返回
     * 
     * @param list
     * @return
     */
    public Response onCompleteWithPageResult(List<?> list){
        return onComplete(PageHelperUtil.getDataTable(list));
    }

    /**
     * 统一封装 onError, 简化调用方代码
     * @param e
     * @return
     */
    protected Response onError(Exception e){
        Response response = response();
        response.onError(e);
        return response;
    }

}

2.2.定义一个分页工具类

这儿可以实现排序和分页

public class PageHelperUtil {


	/**
     * 当前记录起始索引
     */
    public static final String PAGE_NUM = "pageNum";

    /**
     * 每页显示记录数
     */
    public static final String PAGE_SIZE = "pageSize";

    /**
     * 排序列
     */
    public static final String ORDER_BY_COLUMN = "orderByColumn";

    /**
     * 排序的方向 "desc" 或者 "asc".
     */
    public static final String IS_ASC = "isAsc";

    /**
     * 分页参数合理化
     */
    public static final String REASONABLE = "reasonable";
	
	/**
     * 封装分页对象(从请求头获取参数)
     */
    public static PageDomain getPageDomain()
    {
        PageDomain pageDomain = new PageDomain();
        pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM));
        pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE));
        pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
        pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
        pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
        return pageDomain;
    }

    /**
     * 响应请求分页数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static TableDataInfo getDataTable(List<?> list)
    {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setRows(list);
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }


    /**
     * 设置请求分页数据  -  从请求流里面获得请求的信息,注意只能取出来一次,只针对get接口有效
     */
    public static void startPage() {
        PageDomain pageDomain = this.getPageDomain();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            // 增加中文的特殊排序处理
            String orderByColumn = pageDomain.getOrderByColumn();
            if (StringUtils.isNotEmpty(orderByColumn)) {
                orderBy = "convert(" + StringUtils.toUnderScoreCase(orderByColumn) + " USING  gbk" + ") COLLATE gbk_chinese_ci" + " " + pageDomain.getIsAsc();
            }
            PageHelper.startPage(pageNum, pageSize, orderBy);
        }
    }

    /**
     * 设置请求分页数据
     */
    public static void startPage(PageDomain pageDomain) {
        // PageDomain pageDomain =  this.getPageDomain();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            // 增加中文的特殊排序处理
            String orderByColumn = pageDomain.getOrderByColumn();
            if (StringUtils.isNotEmpty(orderByColumn)) {
                orderBy = "convert(" + StringUtils.toUnderScoreCase(orderByColumn) + " USING  gbk" + ") COLLATE gbk_chinese_ci" + " " + pageDomain.getIsAsc();
            }
            PageHelper.startPage(pageNum, pageSize, orderBy);
        }
    }
}


2.3.定义一个分页实体类,存储分页信息,真正接受前端传参的实体类集成这个分页实体类

按照哪个字段排序,会自动把字段的驼峰转换成下划线写法;

**
 * 分页数据
 *
 * @author adbmonitor
 */
public class PageDomain {
    /**
     * 下划线
     */
    @TableField(exist = false)
    private static final char SEPARATOR = '_';
    /**
     * 当前记录起始索引
     */
    @TableField(exist = false)
    private Integer pageNum;

    /**
     * 每页显示记录数
     */
    @TableField(exist = false)
    private Integer pageSize;

    /**
     * 排序列
     */
    @TableField(exist = false)
    private String orderByColumn;

    /**
     * 排序的方向desc或者asc
     */
    @TableField(exist = false)
    private String isAsc = "asc";

    /**
     * 分页参数合理化
     */
    @TableField(exist = false)
    private Boolean reasonable = true;

    public String getOrderBy() {
        if (isEmpty(orderByColumn)) {
            return "";
        }
        return toUnderScoreCase(orderByColumn) + " " + isAsc;
    }

    public Integer getPageNum() {
        return pageNum;
    }

    public void setPageNum(Integer pageNum) {
        this.pageNum = pageNum;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public String getOrderByColumn() {
        return orderByColumn;
    }

    public void setOrderByColumn(String orderByColumn) {
        this.orderByColumn = orderByColumn;
    }

    public String getIsAsc() {
        return isAsc;
    }

    public void setIsAsc(String isAsc) {
        if (!isEmpty(isAsc)) {
            // 兼容前端排序类型
            if ("ascending".equals(isAsc)) {
                isAsc = "asc";
            } else if ("descending".equals(isAsc)) {
                isAsc = "desc";
            }
            this.isAsc = isAsc;
        }
    }

    public Boolean getReasonable() {
        if (reasonable == null) {
            return Boolean.TRUE;
        }
        return reasonable;
    }

    public void setReasonable(Boolean reasonable) {
        this.reasonable = reasonable;
    }

    /**
     * 驼峰转下划线命名
     */
    public static String toUnderScoreCase(String str) {
        if (str == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // 前置字符是否大写
        boolean preCharIsUpperCase = true;
        // 当前字符是否大写
        boolean curreCharIsUpperCase = true;
        // 下一字符是否大写
        boolean nexteCharIsUpperCase = true;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (i > 0) {
                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
            } else {
                preCharIsUpperCase = false;
            }

            curreCharIsUpperCase = Character.isUpperCase(c);

            if (i < (str.length() - 1)) {
                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
            }

            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
                sb.append(SEPARATOR);
            } else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
                sb.append(SEPARATOR);
            }
            sb.append(Character.toLowerCase(c));
        }

        return sb.toString();
    }

    public boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }
}

2.4.定义一个分页数据返回的格式类

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

/**
 * 表格分页数据对象
 * 
 * @author adbmonitor
 */
public class TableDataInfo implements Serializable
{
    private static final long serialVersionUID = 1L;

    /** 总记录数 */
    private long total;

    /** 列表数据 */
    private List<?> rows;

    /**
     * 表格数据对象
     */
    public TableDataInfo()
    {
    }

    /**
     * 分页
     * 
     * @param list 列表数据
     * @param total 总记录数
     */
    public TableDataInfo(List<?> list, int total)
    {
        this.rows = list;
        this.total = total;
    }

    public long getTotal()
    {
        return total;
    }

    public void setTotal(long total)
    {
        this.total = total;
    }

    public List<?> getRows()
    {
        return rows;
    }

    public void setRows(List<?> rows)
    {
        this.rows = rows;
    }

}

2.5. 定义前置切面,执行分页开始的操作

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import static net.facelib.eam.mediacenter.page.PageHelperUtil;


@Aspect
@Component
public class PagingQueryAspect {
	
	// 前置通知,所有被这个注解了的接口调用前这个切面被调用
    @Before("@annotation(net.facelib.eam.mediacenter.annotation.PagingQuery)")
    public void before() {
        PageHelperUtil.startPage();
    }

}
/**
 * @ClassName PagingQuery
 * @Description 分页注解
 * @Author Pathfinder
 * @Date 2022年06月09日 13时38分
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PagingQuery {

}

2.6 使用

controller的方法上加上这个注解

@RestController
@RequestMapping("/material")
@CrossOrigin
@Api(tags = "素材控制器")
public class MaterialController extends BaseController{
 	@PagingQuery
    public Response getMaterial(Material material){
        return onCompleteWithPageResult(materialService.getMaterialList(material));
    }
 }

在这里插入图片描述
在这里插入图片描述

service


 @Override
    @SetCreateUpdateByUserName
    public List<Material> getMaterialList(Material material) {
        QueryWrapper<Material> wrapper = new QueryWrapper<>(material);
        material.setDeptId(UserAccessor.getCurrentUserDeptId());
        assembleTimeQueryRule(material, wrapper.lambda());
        List<Material> materials = materialMapper.selectList(wrapper);
        return materials;
    }

/**
     * 时间搜索规则
     *
     * @param material
     * @param wrapper
     * @return
     */
    private LambdaQueryWrapper<Material> assembleTimeQueryRule(Material material, LambdaQueryWrapper<Material> wrapper) {
        Date searchStartTime = material.getSearchStartTime();
        Date searchEndTime = material.getSearchEndTime();
        if (searchStartTime != null) {
            searchStartTime = DateUtils.getStartTime(searchStartTime);
            if (searchEndTime != null) {
                searchEndTime = DateUtils.getEndTime(searchEndTime);
                return wrapper.between(Material::getCreateTime, searchStartTime, searchEndTime);
            }
            return wrapper.gt(Material::getCreateTime, searchStartTime);
        }
        return wrapper;
    }

/**
     * 创建者搜索
     *
     * @param material
     * @param wrapper
     * @return
     */
    private LambdaQueryWrapper<Material> assembleCreateByQueryRule(Material material, LambdaQueryWrapper<Material> wrapper) {
        Long createBy = material.getCreateBy();
        if (createBy != null) {
            return wrapper.eq(Material::getCreateBy, createBy);
        }
        return wrapper;
    }

从上面可以看到,接口的入参实体类会继承我们自定义的分页筛选类用来存放分页筛选信息,然后,把service返回的集合通过controller的分页返回方法onCompleteWithPageResult返回分页筛选后的数据;

三、注意事项

  1. 类别查询只能是get请求,且是单表的数据库操作;

  2. 定义的接收前端传参的实体类,假如要实现模糊搜索,需要在属性上面加注解;

@TableField(condition = SqlCondition.LIKE)
private String name;

  1. 排序的问题 ?
    orderByColumn 属性决定按照哪个字段排序,isAsc属性觉得升降序
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot结合aop和pagehelper实现分页筛选排序功能 的相关文章

  • 我需要在 Spring 中检查每个控制器中的有效会话吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 假设在 Spring Mvc 的 Web 应用程序中 我们是否需要检查每个控制器或 jsps 中的有效会话 我该如何解决 MVC 中的
  • 线程自动利用多个CPU核心?

    假设我的应用程序运行 2 个线程 例如渲染线程和游戏更新线程 如果它在具有多核 CPU 当今典型 的移动设备上运行 我是否可以期望线程在可能的情况下自动分配给不同的核心 我知道底层操作系统内核 Android linux内核 决定调度 我的
  • manifest.mf 文件的附加内容的约定?

    Java JAR 中的 MANIFEST MF 文件是否有任何超出 MANIFEST MF 约定的约定 JAR规范 http download oracle com javase 1 4 2 docs guide jar jar html
  • JNI 不满意链接错误

    我想创建一个简单的 JNI 层 我使用Visual studio 2008创建了一个dll Win 32控制台应用程序项目类型 带有DLL作为选项 当我调用本机方法时 出现此异常 Exception occurred during even
  • 如何查找 Android 设备中的所有文件并将它们放入列表中?

    我正在寻求帮助来列出 Android 外部存储设备中的所有文件 我想查找所有文件夹 包括主文件夹的子文件夹 有办法吗 我已经做了一个基本的工作 但我仍然没有得到想要的结果 这不起作用 这是我的代码 File files array file
  • 在数据流模板中调用 waitUntilFinish() 后可以运行代码吗?

    我有一个批处理 Apache Beam 作业 它从 GCS 获取文件作为输入 我的目标是根据执行后管道的状态将文件移动到两个 GCS 存储桶之一 如果管道执行成功 则将文件移动到存储桶 A 否则 如果管道在执行过程中出现任何未处理的异常 则
  • hibernate总是自己删除表中的所有数据

    您好 我正在开发一个 spring mvc 应用程序 它使用 hibernate 连接到存储文件的 mysql 数据库 我有两个方法 一个方法添加我选择的特定文件路径中的所有文件 另一种方法调用查询以返回从 mysql 存储的文件列表 问题
  • OnClick 事件中的 finish() 如何工作?

    我有一个Activity一键退出Activity 通过layout xml我必须设置OnClick事件至cmd exit调用 this finish 效果很好 public void cmd exit View editLayout thi
  • 请求位置更新参数

    这就是 requestLocationUpdates 的样子 我使用它的方式 requestLocationUpdates String provider long minTime float minDistance LocationLis
  • 在具有相同属性名称的不同数据类型上使用 ModelMapper

    我有两节课说Animal AnimalDto我想用ModelMapper将 Entity 转换为 DTO 反之亦然 但是对于具有相似名称的一些属性 这些类应该具有不同的数据类型 我该如何实现这一目标 动物 java public class
  • 反思 Groovy 脚本中声明的函数

    有没有一种方法可以获取 Groovy 脚本中声明的函数的反射数据 该脚本已通过GroovyShell目的 具体来说 我想枚举脚本中的函数并访问附加到它们的注释 Put this到 Groovy 脚本的最后一行 它将作为脚本的返回值 a la
  • 尝试使用 Ruby Java Bridge (RJB) gem 时出现错误“无法创建 Java VM”

    我正在尝试实现 Ruby Java Bridge RJB gem 来与 JVM 通信 以便我可以运行 Open NLP gem 我在 Windows 8 上安装并运行了 Java 所有迹象 至少我所知道的 都表明 Java 已安装并可运行
  • 使用 SAX 进行 XML 解析 |如何处理特殊字符?

    我们有一个 JAVA 应用程序 可以从 SAP 系统中提取数据 解析数据并呈现给用户 使用 SAP JCo 连接器提取数据 最近我们抛出了一个异常 org xml sax SAXParseException 字符引用 是无效的 XML 字符
  • 如何在 Maven 中显示消息

    如何在 Maven 中显示消息 在ant中 我们确实有 echo 来显示消息 但是在maven中 我该怎么做呢 您可以使用 antrun 插件
  • Netbeans 8 不会重新加载静态 Thymeleaf 文件

    我通过 Maven 使用 Spring Boot 和 Thymeleaf 当我进行更改时 我似乎无法让 Netbeans 自动重新部署我的任何 Thymeleaf 模板文件 为了看到更改 我需要进行完整的清理 构建 运行 这需要太长的时间
  • android Accessibility-service 突然停止触发事件

    我有一个 AccessibilityService 工作正常 但由于开发过程中的某些原因它停止工作 我似乎找不到这个原因 请看一下我的代码并告诉我为什么它不起作用 public class MyServicee extends Access
  • 使用SpringApplication时加载applicationcontext.xml

    谁能提供加载 applicationContext xml 文件的 SpringApplication 示例 我正在尝试使用以下方法将我的 GWT RPC 应用程序移动到 RESTful Web 服务春天的例子 https spring i
  • com.jcraft.jsch.JSchException:身份验证失败

    当我从本地磁盘上传文件到远程服务器时 出现这样的异常 com jcraft jsch JSchException Auth fail at org apache tools ant taskdefs optional ssh Scp exe
  • JAVA - 如何从扫描仪读取文件中检测到“\n”字符

    第一次海报 我在读取文本文件的扫描仪中读取返回字符时遇到问题 正在读取的文本文件如下所示 test txt start 2 0 30 30 1 1 90 30 0 test txt end 第一行 2 表示两个点 第二行 位置索引 0 xp
  • Jackson 将单个项目反序列化到列表中

    我正在尝试使用一项服务 该服务为我提供了一个带有数组字段的实体 id 23233 items name item 1 name item 2 但是 当数组包含单个项目时 将返回该项目本身 而不是包含一个元素的数组 id 43567 item

随机推荐

  • Linux3.10内核之后proc文件系统的使用

    最近在通过无线扫描周边的手机mac的事情 拿到AP周边的mac后需要送到应用层 之前接触的都是RTOS的系统 数据交互比较简单 Linux下应用层无法直接和驱动交换数据 需要通过kernel提供的一些通道 因为只是向应用层送数据 和应用层的
  • Windows7旗舰版和10 创建原始套接字失败,代码10013

    笔记本重装系统后 以前能运行的程序中的Ping程序不能运行了 查看代码 创建套接字失败 RawSock socket AF INET SOCK RAW IPPROTO ICMP RawSock INVALID SOCKET 用DWORD d
  • 微信小程序地图(map)组件点击(tap)获取经纬度

    微信小程序中使用地图 map 组件 通过点击 tap 获取经纬度 按照官方的回应 暂时是没法做到的 从地图组件API多有残缺判断 怀疑是个实习生干的 做个变通 适用性有限 请大家参考 基本思路就是在地图上铺满一层marker 从而通过点击m
  • 智慧合约:智能合约安全问题的AI解决方案

    一支穿云箭 千军万马来相见 在经历三个月 漫长熊市 后 从4月中旬开始 EOS的一个拉升 形成了数字货币市场大牛市的壮观景象 可是在美链BeautyChain BEC 的智能合约漏洞被黑客利用 随意刷币 SmartMesh SMT 智能合约
  • System.out.println()影响系统运行效率!!!

    在Java开发中 System out println 是一种常用的输出方式 可以将字符串输出到控制台 然而 这种输出方式在一定程度上会影响系统的运行效率 首先 System out println 的输出操作需要占用CPU和内存资源 因为
  • 配置Maven仓库私服

    在项目的pom xml文件中配置 将下面代码复制粘贴到文件的最下方即可
  • 霍尔传感器测电机的转速

    霍尔传感器可以用于测量电机的转速 测量原理是通过检测电机旋转时产生的磁场变化来计算转速 具体的测量方法如下 1 在电机旋转的轴上安装一个磁铁 磁铁的北极和南极在轴上相隔一定距离 2 在电机旋转轴的一侧安装一个霍尔传感器 传感器的感应面与磁铁
  • java的intern方法

    intern 方法返回值 一个字符串 内容与此字符串相同 但一定取自具有唯一字符串的池 new的字符串和变量不会进入常量池 String str1 a String str2 b String str3 ab 放在常量池 String st
  • Android_CTF: kgb_messenger

    环境 kgb messenger apk 测试机 OnePlus Andorid 9 1 Alerts 安装该apk后 使用发现如下的界面 用 jadx 反编译该 apk 搜索字符串 Russian 在MainActivity中发现了以上字
  • Git安装与配置及常见命令

    Git安装与配置及常见命令 1 下载与安装 1 官方下载地址 https git scm com download win 2 安装好之后 直接点击 运行即可 之后一直默认就行 3 桌面点击右键 会出现 Git Bash Here 点击此选
  • SpringBoot自定义bean的加载顺序

    最近面试的时候被问到这个问题 当时自己没回答上来 下来自己想了想然后又查了些博客 所以就记录下这个 首先写出两个测试类 Component public class TestA public TestA System out println
  • 基于深度学习的语义分割之FCN、SegNet、UNet、LinkNet、PSPNet、DeepLab系列

    图像分割 Image Segmentation 是计算机视觉研究中的一个经典难题 也是图像理解领域关注的一个热点 在场景理解 医学图像分析 机器人感知 视频监控 增强现实 图像压缩等领域有着广泛的应用 图像分割 简单来说就是在图像中把目标从
  • linux下wifi编程(基于netlink和nl80211.h)

    http blog csdn net vichie2008 article details 37520325
  • Mac系统(Linux系统) 当不知道MySql的root密码时候, 重置root密码

    1 首先打开终端 进入MySQL的安装目录下的bin文件夹 如 usr local mysql bin 2 执行以下命令以无密码方式登录MySQL mysql u root 3 进入MySQL后 选择mysql数据库 use mysql 4
  • QT信号与槽的自动连接

    信号与槽的自动连接 信号与槽可以通过使用手写代码显式的实现关联 也可以运用 QMetaObject 类规定的槽 函数命名范式来实现自动关联 显式关联 首先我们来看一下 不使用 自动关联规则 的情形 在下面这段代码里面 我们定义了一个对话框类
  • 48、Flutter之widgets LayoutBuilder组件

    LayoutBuilder 通过 LayoutBuilder 我们可以在布局过程中拿到父组件传递的约束信息 然后我们可以根据约束信息动态的构建不同的布局 比如我们实现一个响应式的 Column 组件 ResponsiveColumn 它的功
  • jquery筛选器

    在Web应用程序中 大部分的客户端操作都是基于对象的操作 要操作对象就必须先获取对象 jQuery提供了强大的选择器让我们获取对象 我人为地将jQuery选择器分为两大部分 选择对象和筛选条件 选择对象表示要获取什么对象 筛选条件是对获取的
  • # 2023 好用免费图床推荐

    1 聚合图床 该免费图床由来已久 稳定运行多年 满足多种个性化需要 可以说该图床是所有推荐当中最为灵活 扩展性最强图床 支持水印设置 防盗链设置 甚至还可以统计数据量大小 有普通用户和付费用户区分 付费用户自定义功能将更加强大 就个人而言
  • Spring Cloud Config配置服务及那些你不知道的坑

    目录 1 为什么选择Spring Cloud Config 1 1 集中式管理 1 2 动态修改配置 2 Spring Cloud Config 简介 3 服务端配置 3 1 添加依赖 3 2 开启服务注册 3 3 添加YML配置 3 4
  • springboot结合aop和pagehelper实现分页筛选排序功能

    一 前言 首先我们要知道什么是aop 什么是pagehelper 从而我们知道 pagehelper的实现其实是两行代码 PageHelper startPage pageNum pageSize 开始分页 PageInfo pageInf