java通过注解实现分页功能

java通过注解实现分页功能

一. 概述

1.1 为什么要使用分页功能?

  • 在我们的业务系统中,经常会涉及到查询列表查询,使用分页功能可以灵活清晰的展现出我们的数据结果,就像翻书一样,达到了非常棒的阅读体验。

1.2 传统分页与注解分页的区别?

  • 优点:
    1. 使用简单,使用注解分页,我们可以只用去关心如何拿到数据,而不需要关心如何按前端要求去拿;
    2. 精简代码,提升效率,通过自定义注解的使用,我们只需要加一个注解即可对其进行分页,而不需要再代码中再去做分页操作;
    3. 更加优雅,逼格满满,阅读注解中所涉及到的反射,自定义注解,以及切面等技术,无疑又是对自己的一个提高;
  • 缺点:
    1. 灵活性降低,统一都是使用一种分页方式,且查询出来的数据先必须是全部数据,明显灵活性降低了;
    2. 性能降低,使用反射等技术本身会使得机器性能更低一点,且查出来的数据首先得是全部数据,会导致查询数据库也会增加耗时;

    随着机器的配置越来越好,使用注解分页无疑是更优雅更前卫的选择;当然任何时候都得考虑这种技术适用于什么场景。自定义注解分页适用于数据量较少的数据;

1.3 注解分页效果图

  • 接口加上 @PageQuery
    在这里插入图片描述
  • 返回数据已展示分页:
    1. pageIndex=1,pageSize=10 ,结果如图:
      在这里插入图片描述
    2. pageIndex=1,pageSize=5 ,结果如图:
      在这里插入图片描述

      分页效果与我们平时所需要的效果一致。仅仅在接口上加了一个自定义注解,即可自动分页。返回的pageInfo如果觉得少了,还能自定义进行添加;

二. 实战自定义注解分页

2.1 定义核心注解类 @PageQuery

package com.annotation.page;

import java.lang.annotation.*;

/**
 * @program: xxxx
 * @description: PageSize注解类
 * @author: an yu
 * @create: 2020-03-23
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PageQuery {
    String pageIndexName() default "pageIndex";//页号的参数名

    String pageSizeName() default "pageSize";//每页行数的参数名
}


2.2 定义PageInfo类(返回的分页信息)PageInfo

package com.annotation.page;

import lombok.Data;
import lombok.experimental.Accessors;

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

/**
 * @program: xxxx
 * @description: 自定义PageInfo
 * @author: anyu
 * @create: 2020-03-23
 */
@Data
@Accessors(chain = true)
@SuppressWarnings("all")
public class PageInfo implements Serializable {

    private int pageNum;            //

    private int pageSize;

    private long total;

    private List<Object> list;

    public PageInfo(int pageNum, int pageSize, long total, List<Object> list) {
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.total = total;
        this.list = list;
    }

    public PageInfo(int pageNum, int pageSize, List<Object> list) {
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.list = list;
    }

    public PageInfo(List<Object> list) {
        this.list = list;
    }

    public PageInfo() {
    }

}

2.3 定义切面类

package com.annotation.page;

import com.alibaba.dubbo.common.utils.IOUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cdmtc.response.RespEntity;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: xxxx
 * @description: 分页切面
 * @author: anyu
 * @create: 2020-03-23
 */
@Aspect
@Component
public class PageAspect {

    private final static Logger LOGGER = LoggerFactory.getLogger(PageAspect.class);

    @Around("@annotation(pageQuery)")
    public Object pagingQuery(ProceedingJoinPoint joinPoint, PageQuery pageQuery) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Class<?> returnType = signature.getMethod().getReturnType();
        if (("com.cdmtc.response.RespEntity").equals(returnType.getName())) {

            /* 1. 获取分页名称*/
            String pageIndexName = pageQuery.pageIndexName();
            String pageSizeName = pageQuery.pageSizeName();

            /* 2. 获取分页值 */
            ServletRequestAttributes currentRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            HttpServletRequest request = currentRequestAttributes.getRequest();
            String body = IOUtils.read(request.getReader());
            JSONObject jsonObject = JSONObject.parseObject(body);
            String pageNum = jsonObject.getString(pageIndexName);
            String pageSize = jsonObject.getString(pageSizeName);

            /* 3. 赋默认值 */
            try {
                /* 进行分页 */
                Object respEntityObj = joinPoint.proceed();
                RespEntity respEntity = JSON.parseObject(JSON.toJSONString(respEntityObj), RespEntity.class);           // 这里根据自己的接口通用返回实体类进行对应修改
                Object result = respEntity.getResult();    // 这里根据自己的接口通用返回实体类进行对应修改
                List list = JSON.parseObject(JSON.toJSONString(result), List.class);
                Integer pageNumInt = Integer.valueOf(pageNum);
                Integer pageSizeInt = Integer.valueOf(pageSize);
                List list1 = pageBySubList(list, pageNumInt, pageSizeInt);
                PageInfo pageInfo = new PageInfo(pageNumInt, pageSizeInt, list.size(), list1);              // 将结果存入
                return RespEntity.success(pageInfo);
            } catch (Exception e) {
                LOGGER.error("查询失败", e);
                return RespEntity.success(new PageInfo());
            }
        }
        return joinPoint.proceed();
    }


    /**
     * 利用subList方法进行分页
     *
     * @param list        分页数据
     * @param pageSize    页面大小
     * @param currentPage 当前页面
     */
    public static List pageBySubList(List list, int currentPage, int pageSize) {
        if (pageSize < 1 || currentPage < 1 || list.size() / pageSize < currentPage - 1) {
            return new ArrayList();
        }
        return list.subList((currentPage - 1) * pageSize, pageSize * currentPage < list.size() ? pageSize * currentPage : list.size());
    }
}

2.4 定义 PageQuery实体类

package com.param;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;

/**
 * @Create anyu
 * @CraeteTime 2019/5/31
 * @Description
 */
@Data
@ToString
public class PageQuery<T> implements Serializable {
    private static final long serialVersionUID = 1918876594784006915L;
    @ApiModelProperty(value="页码",name="pageIndex",example="1")
    @NotBlank(message = "当前页不能为空")
    @Pattern(regexp = "[1-9]\\d*",message = "参数错误")
    private int pageIndex;

    @ApiModelProperty(value="每页条数",name="pageSize",example="10")
    @NotBlank(message = "每页记录数不能为空")
    @Pattern(regexp = "[1-9]\\d*",message = "参数错误")
    private int pageSize;

    @ApiModelProperty(value="请求条件",name="param",example="")
    private T param;
}

2.5 定义接口类

package com.controller;

import com.cdmtc.annotation.page.PageQuery;
import com.cdmtc.response.RespEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @program: xxxx
 * @description: ceshilei
 * @author: zhang lei
 * @create: 2020-03-13
 */
@RestController
@RequestMapping("api")
@Api(value="CustomMonitor",tags={"测试类"})
public class DemoController {

    @ApiOperation("测试分页集合")
    @PostMapping("getList")
    @PageQuery
    public RespEntity getList(@RequestBody com.cdmtc.param.PageQuery<String> pageQuerys){
        List<String> list=new ArrayList<>();
        Collections.addAll(list,"0","1","2","3","4","5","6","7","8","9","10","11","12","13");
        return RespEntity.success(list);
    }
}

2.6 定义返回值类

package com.response;

import com.model.response.RespResult;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.util.MultiValueMap;

import java.io.Serializable;

/**
 * @create_by: anyu
 * @craete_time 2019/7/17
 */
@Data
@Accessors(chain = true)
public class RespEntity implements Serializable {
    public int errCode=0;
    public String errMsg="success";
    public Object result="";
    private static final RespEntity fail = new RespEntity().setErrCode(1).setErrMsg("fail").setResult("");
    private static final RespEntity success = new RespEntity().setResult("");

    private RespEntity() {
    }

    public static RespEntity fail() {
        return fail;
    }
    public static RespEntity success(){
        return success;
    }

    public static RespEntity fail(String errMsg,Object object){
        RespEntity fail= RespEntity.fail();
        fail.setErrMsg(errMsg);
        fail.setResult(object);
        return fail;
    }

    public static RespEntity fail(String errMsg){
        RespEntity fail= RespEntity.fail();
        fail.setErrMsg(errMsg);
        return fail;
    }


    public static RespEntity success(Object object){
        RespEntity success = RespEntity.success;
        success.setResult(object);
        return success;
    }
}

三. 总结

3.1 回顾

  1. 讲述了传统pageQuery与现在的注解分页的区别
  2. 讲述了相关的源码

3.2 注意:

  1. 这里用到了Swagger-ui,所以使用代码的时候,如果相关的爆红则可以直接注释掉或者导入swagger-ui,具体使用swagger-ui请网上找相关资料
  2. 请先阅读源码后再使用,可进行自定义修改。刚写完肯定有一些的瑕疵,勿怪~
发布了127 篇原创文章 · 获赞 52 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_37128049/article/details/105045717