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

一、前言

首先我们要知道什么是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属性觉得升降序
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在SpringBoot实现AOP,需要进行以下步骤: 1. 导入AOP相关的包,可以在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` [1] 2. 编写一个Controller类,例如UserController。 3. 使用@Aspect注解实现一个切面类,对UserController中的所有方法进行切入。切面类需要使用@Component注解将其声明为一个Bean实例,这样Spring IOC容器才会为与切面匹配的Bean创建代理。 ```java @Component @Aspect public class MyAspect { // 切入点定义和通知方法实现 // ... } ``` [2 [3] 通过以上步骤,就可以在SpringBoot项目中实现AOP。切面类中的切入点定义和通知方法实现可以根据具体需求进行编写,用于在方法执行前、后或异常时执行特定的行为。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [SpringBoot环境下实现AOP](https://blog.csdn.net/m0_37754981/article/details/89024041)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Spring boot实现aop](https://blog.csdn.net/qq_43599835/article/details/90721857)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LC超人在良家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值