spring boot3 六、 spring alibaba cloud 增强mybatis plus 、可无限扩增线程池、自动缓存、自动预热、通用高性能分页

在这里插入图片描述

EnhanceBatchDelete.class 增强批量删除

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

/**
 * @author kong
 */
public class EnhanceBatchDelete extends AbstractMethod {

    /**
     * @param methodName 方法名
     * @since 3.5.0
     */
    protected EnhanceBatchDelete(String methodName) {
        super(methodName);
    }

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        //真删代码
        //        final String sql = "<script>delete from "
        //                + tableInfo.getTableName()
        //                + " where "
        //                + tableInfo.getKeyColumn()
        //                + " in(<foreach collection=\"list\" item=\"i\" separator=\",\">#{i}</foreach>)</script>";

        //update t set deleted=1 where id in()

        //逻辑删除
        final String sql = "<script>update "
                + tableInfo.getTableName()
                + " set deleted=1"
                + " where "
                + tableInfo.getKeyColumn()
                + " in(<foreach collection=\"list\" item=\"i\" separator=\",\">#{i}</foreach>)</script>";

        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        final String id = "enhanceBatchDelete";
        return this.addDeleteMappedStatement(mapperClass, id, sqlSource);
    }

}

EnhanceBatchInsert .class 增强批量新增

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.List;
import java.util.function.Predicate;

/**
 * @author kong
 */
public class EnhanceBatchInsert extends AbstractMethod {

    @Setter
    @Accessors(chain = true)
    private Predicate<TableFieldInfo> predicate;

    /**
     * @param methodName 方法名
     * @since 3.5.0
     */
    protected EnhanceBatchInsert(String methodName) {
        super(methodName);
    }

    /**
     * <script>
     * INSERT INTO s_user
     * (<if test="list.get(0).id!=null">id,</if>username,nickname)
     * VALUES
     * <foreach collection="list" item="et" separator=",">
     * (<if test="list.get(0).id!=null">#{et.id},</if>#{et.username},#{et.nickname})
     * </foreach>
     * </script>
     */
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        String keyProperty = null;
        String keyColumn = null;
        // 表包含主键处理逻辑,如果不包含主键当普通字段处理
        final String id = "enhanceBatchInsert";
        if (tableInfo.havePK()) {
            if (tableInfo.getIdType() == IdType.AUTO) {
                /* 自增主键 */
                keyGenerator = new Jdbc3KeyGenerator();
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            } else {
                if (null != tableInfo.getKeySequence()) {
                    keyGenerator = TableInfoHelper.genKeyGenerator(id, tableInfo, builderAssistant);
                    keyProperty = tableInfo.getKeyProperty();
                    keyColumn = tableInfo.getKeyColumn();
                }
            }
        }
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, this.generateSql(tableInfo.getFieldList(), tableInfo), modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, id, sqlSource, keyGenerator, keyProperty, keyColumn);

    }


    private String generateSql(List<TableFieldInfo> fields, TableInfo tableInfo) {
        StringBuilder sb = new StringBuilder();
        sb.append("<script>insert into ").append(tableInfo.getTableName())
                .append("(<trim suffixOverrides=\",\"><if test=\"list.get(0).")
                .append(tableInfo.getKeyProperty()).append("!=null\">")
                .append(tableInfo.getKeyColumn()).append(",</if>");

        fields.forEach(i -> sb.append("<if test=\"list.get(0).").append(i.getProperty()).append("!=null\">").append(i.getColumn()).append(",</if>"));

        sb.append("</trim>) values <foreach collection=\"list\" item=\"et\" separator=\",\">(<trim  suffixOverrides=\",\"><if test=\"list.get(0).")
                .append(tableInfo.getKeyProperty())
                .append("!=null\">#{et.")
                .append(tableInfo.getKeyColumn())
                .append("},</if>");

        fields.forEach(i -> sb.append("<if test=\"list.get(0).").append(i.getProperty()).append("!=null\">#{et.").append(i.getProperty()).append("},</if>"));

        sb.append("</trim>) </foreach></script>");
        return sb.toString();
    }

}

EnhanceBatchUpdate.class 增强批量修改

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.List;

/**
 * @author kong
 */
public class EnhanceBatchUpdate extends AbstractMethod {
    /**
     * @param methodName 方法名
     * @since 3.5.0
     */
    protected EnhanceBatchUpdate(String methodName) {
        super(methodName);
    }

    /**
     * update s_access_log
     * <trim prefix="set" suffixOverrides=",">
     * <if test="list.get(0).description!=null">
     * <trim prefix="description=case" suffix="end,">
     * <foreach collection="list" item="et">
     * <if test="et!=null"> when id=#{et.id} then #{et.description}</if>
     * </foreach>
     * </trim>
     * </if>
     * </trim>
     * where id in
     * <foreach collection="list" item="et" separator="," open="(" close=")">#{et.id}</foreach>
     */
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, this.generateSql(tableInfo.getFieldList(), tableInfo), modelClass);
        final String id = "enhanceBatchUpdate";
        return this.addUpdateMappedStatement(mapperClass, modelClass, id, sqlSource);
    }

    private String generateSql(List<TableFieldInfo> fields, TableInfo tableInfo) {

        StringBuilder sb = new StringBuilder();
        fields.forEach(i -> sb
                .append("<if test=\"list.get(0).").append(i.getProperty()).append("!=null\">")
                .append("<trim prefix=\"")
                .append(i.getColumn())
                .append("=case\" suffix=\"end,\">")
                .append("<foreach collection=\"list\" item=\"et\">")
                .append("<if test=\"et!=null\">")
                .append(" when ")
                .append(tableInfo.getKeyColumn()).append("=#{et.").append(tableInfo.getKeyProperty()).append("} then #{et.").append(i.getProperty()).append("}")
                .append("</if>")
                .append("</foreach>")
                .append("</trim>")
                .append("</if>"));

        return "<script>update " + tableInfo.getTableName()
                + "<trim prefix=\"set\" suffixOverrides=\",\">"
                + sb
                + "</trim> where " + tableInfo.getKeyColumn() + " in <foreach collection=\"list\" item=\"et\" separator=\",\" open=\"(\" close=\")\"> #{et."
                + tableInfo.getKeyProperty() + "} </foreach> </script>";
    }


}

EnhanceDelete .class 增强删除 sql 追加 limit 1

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

public class EnhanceDelete extends AbstractMethod {

    /**
     * @param methodName 方法名
     * @since 3.5.0
     */
    protected EnhanceDelete(String methodName) {
        super(methodName);
    }

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
//        final String sql = "<script>delete from " + tableInfo.getTableName() + " where " + tableInfo.getKeyColumn() + "=#{id} limit 1</script>";
        final String sql = "<script>update " + tableInfo.getTableName() + " set deleted=1 where deleted=0 and " + tableInfo.getKeyColumn() + "=#{id}  limit 1</script>";
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        final String id = "enhanceDelete";
        return this.addDeleteMappedStatement(mapperClass, id, sqlSource);
    }

}

EnhanceUpdate 增强更新 追加limit 1

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.List;

public class EnhanceUpdate extends AbstractMethod {

    /**
     * @param methodName 方法名
     * @since 3.5.0
     */
    protected EnhanceUpdate(String methodName) {
        super(methodName);
    }

    /**
     * update s_access_log
     * <trim prefix="set" suffixOverrides=",">
     * <if test="list.get(0).description!=null">
     * <trim prefix="description=case" suffix="end,">
     * <foreach collection="list" item="et">
     * <if test="et!=null"> when id=#{et.id} then #{et.description}</if>
     * </foreach>
     * </trim>
     * </if>
     * </trim>
     * where id in
     * <foreach collection="list" item="et" separator="," open="(" close=")">#{et.id}</foreach>
     */
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, this.generateSql(tableInfo.getFieldList(), tableInfo), modelClass);
        final String id = "enhanceUpdate";
        return this.addUpdateMappedStatement(mapperClass, modelClass, id, sqlSource);
    }

    private String generateSql(List<TableFieldInfo> fields, TableInfo tableInfo) {


        StringBuilder sb = new StringBuilder();
        fields.forEach(i -> sb
                .append("<if test=\"")
                .append(i.getProperty()).append("!=null\">")
                .append(i.getColumn()).append("=").append("#{").append(i.getProperty()).append("},")
                .append("</if>")
        );

        return "<script>update " + tableInfo.getTableName()
                + "<trim prefix=\"set\" suffixOverrides=\",\">"
                + sb
                + "</trim> where " + tableInfo.getKeyColumn() + "=#{" + tableInfo.getKeyProperty() + "} limit 1</script>";
    }


}

增强实现相关常量

package com.jm.common.conf.mybatis;

/**
 * @author kong
 */
public class EnhanceConstant {
    /**
     * redis 对象 前缀
     */
    public static final String REDIS_PREFIX = "jm:model:";

    private EnhanceConstant() {
    }
}

增强mapper 接口

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;

import java.util.Collection;

/**
 * @author kong
 */
public interface EnhancePlusMapper<T> extends BaseMapper<T> {

    /**
     * 增强批量新增
     */
    int enhanceBatchInsert(@Param("list") Collection<T> rows);

    /**
     * 增强批量更新
     */
    int enhanceBatchUpdate(@Param("list") Collection<T> rows);

    /**
     * 增强更新
     */
    int enhanceUpdate(T t);

    /**
     * 增强批量删除
     */
    int enhanceBatchDelete(@Param("list") Collection<String> rows);

    /**
     * 增强删除
     */
    int enhanceDelete(Object id);

}

EnhanceService 接口

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jm.common.bean.base.PageParam;
import com.jm.common.bean.base.PageVO;

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

public interface EnhanceService<T> extends IService<T> {

    void delCache(T t);

    void delCache(Serializable id);

    boolean add(T t);

    boolean modify(T t);

    boolean del(String id);

    boolean del(List<String> ids);

    T get(Serializable id);

    PageVO<T> getPage(PageParam param) throws IllegalAccessException;

    PageVO<T> getPage(PageParam param, LambdaQueryWrapper<T> pageWrapper, LambdaQueryWrapper<T> countWrapper,
                      LambdaQueryWrapper<T> lastWrapper, int expireSecond, String id) throws IllegalAccessException;

    PageVO<T> getPage(PageParam param, List<T> pls);
}

查询-自动缓存 自动预热、通用高性能分页

package com.jm.common.conf.mybatis;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jm.common.bean.base.PageParam;
import com.jm.common.bean.base.PageVO;
import com.jm.common.conf.constant.SysRedisConstant;
import com.jm.common.tool.ClassTool;
import com.jm.common.tool.LogTool;
import com.jm.common.tool.ParseTool;
import com.jm.common.tool.RandomTool;
import com.jm.common.tool.function.ThrowTool;
import com.jm.common.tool.pool.ThreadPoolTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author kong
 */
@Slf4j
public class EnhanceServiceImpl<M extends EnhancePlusMapper<T>, T> extends ServiceImpl<M, T> implements EnhanceService<T> {
    /**
     * model redis of key 前缀
     */
    public final String KEY_PREFIX;
    public final ValueOperations<String, Object> redisValue;
    public final RedisTemplate<String, Object> redis;
    public final Class<T> classz;
    /**
     * model of 主键
     */
    public final Field primaryKeyField;
    /**
     * model of 主键类型
     */
    public final String primaryKeyType;
    /**
     * model of 主键 名
     */
    public final String primaryKeyName;
    public final RedissonClient redissonClient;

    public EnhanceServiceImpl(RedisTemplate<String, Object> redis, RedissonClient redissonClient) {
        this.redis = redis;
        this.redisValue = redis.opsForValue();
        this.redissonClient = redissonClient;
        this.classz = (Class<T>) ClassTool.getClassz(this.getClass());

        TableName tableName = this.classz.getAnnotation(TableName.class);
        this.KEY_PREFIX = EnhanceConstant.REDIS_PREFIX + tableName.value() + ":";

        this.primaryKeyField = this.getPrimaryKeyField();
        this.primaryKeyType = this.primaryKeyField.getType().getTypeName();

        //通过@TableId注解获取主键id 数据库 列名
        TableId tableId = this.primaryKeyField.getAnnotation(TableId.class);
        this.primaryKeyName = tableId.value();
    }

    public String getKeyPrefix() {
        return this.KEY_PREFIX;
    }

    public Class<T> getClassz() {
        Type type = this.getClass().getGenericSuperclass();
        Type[] types = ((ParameterizedType) type).getActualTypeArguments();
        return (Class<T>) types[1];
    }

    public String getClassName() {
        return this.classz.getSimpleName();
    }

    public Field getPrimaryKeyField() {
        //获取主键属性及类型
        List<Field> fields = FieldUtils.getFieldsListWithAnnotation(this.classz, TableId.class);
        return fields.get(0);
    }

    public List<Field> getFields() {
        return FieldUtils.getAllFieldsList(getClassz());
    }

    public String getPrimaryKeyValue(T t) throws IllegalAccessException {
        return String.valueOf(FieldUtils.readField(t, this.primaryKeyField.getName(), true));
    }

    @Override
    public void delCache(T t) {
        try {
            redis.delete(KEY_PREFIX + this.getPrimaryKeyValue(t));
        } catch (IllegalAccessException e) {
            log.error("数据删除异常 ", e);
        }
    }

    @Override
    public void delCache(Serializable id) {
        redis.delete(KEY_PREFIX + id);
    }

    @Override
    public boolean add(T t) {
        return save(t);
    }

    protected void checkPrimaryValue(final String id) {
        if (Pattern.matches("\\d*", id.replaceAll("\"", ""))) {
            long number = Long.parseLong(id);
            ThrowTool.isTrue(number <= 0).throwMsg("id不合法");
        }
    }

    @Override
    public boolean modify(T t) {
        try {
            final String id = this.getPrimaryKeyValue(t);
            this.checkPrimaryValue(id);
            //每次更新 自动填入更新时间
            Field field = ClassTool.getField(this.classz, "updateTime");
            if (field != null) {
                field.set(t, LocalDateTime.now());
            }
            final boolean flag = this.baseMapper.enhanceUpdate(t) > 0;
            this.delCache(id);
            return flag;
        } catch (Exception e) {
            log.error("数据修改异常 ", e);
        }
        return false;
    }

    @Override
    public boolean del(String sid) {
        this.checkPrimaryValue(sid);
        //将值转换为主键类型值
        Object id = ParseTool.parseObject(sid, this.primaryKeyType);
        final boolean flag = this.baseMapper.enhanceDelete(id) > 0;
        this.delCache(sid);
        return flag;
    }

    @Override
    public boolean del(List<String> ids) {
        ThrowTool.isTrue(CollectionUtils.isEmpty(ids)).throwMsg("empty collection");
        if (ids.size() > 1) {
            final boolean flag = removeBatchByIds(ids);
            CompletableFuture.runAsync(() -> redis.delete(ids.parallelStream().map(i -> KEY_PREFIX + i).collect(Collectors.toList())), ThreadPoolTool.EXECUTOR).exceptionally(LogTool::err);
            return flag;
        }
        return del(ids.get(0));
    }

    @Override
    public boolean removeBatchByIds(Collection<?> list) {
        return this.baseMapper.enhanceBatchDelete(list.parallelStream().map(String::valueOf).collect(Collectors.toList())) > 0;
    }

    @Override
    public T get(Serializable id) {
        this.checkPrimaryValue(String.valueOf(id));
        final String key = this.KEY_PREFIX + id;
        Object o = redisValue.get(key);
        T t;
        if (o == null) {
            t = getOne(new LambdaQueryWrapper<T>().apply(this.primaryKeyName + "='" + id + "'").last("limit 1"));
            if (t == null) {
                CompletableFuture.runAsync(() -> redis.delete(key), ThreadPoolTool.EXECUTOR).exceptionally(LogTool::err);
            } else {
                //1小时后失效
                CompletableFuture.runAsync(() -> redisValue.set(key, t, 3600, TimeUnit.SECONDS), ThreadPoolTool.EXECUTOR).exceptionally(LogTool::err);
            }
        } else {
            t = (T) o;
            //小于一个小时自动续期
            CompletableFuture.runAsync(() -> this.renewal(key), ThreadPoolTool.EXECUTOR).exceptionally(LogTool::err);
        }
        return t;
    }


    /**
     * 小于一个小时自动续期
     *
     * @param key redis key
     */
    public void renewal(final String key) {
        //以redis key加锁 redisson 锁的key不能有:
        RLock lock = redissonClient.getLock("lock_" + key.replaceAll(":", "_"));
        try {
            boolean is = lock.tryLock(20, 10, TimeUnit.SECONDS);
            if (is) {
                long expireTime = Optional.ofNullable(redis.getExpire(key)).orElse(0L);
                if (expireTime < 3600) {
                    //续期时间为 剩余时间+一小时+随机秒
                    CompletableFuture.runAsync(() -> redis.expire(key, expireTime + 3600 + RandomTool.random(999, 100), TimeUnit.SECONDS), ThreadPoolTool.EXECUTOR).exceptionally(LogTool::err);
                }
            }
        } catch (InterruptedException e) {
            log.error("redis 缓存续期 错误 ", e);
        } finally {
            lock.unlock();
        }

    }

    @Override
    public PageVO<T> getPage(PageParam param) throws IllegalAccessException {
        //默认过期时间 10分钟
        LambdaQueryWrapper<T> w = new LambdaQueryWrapper<>();
        return this.getPage(param, w, w, new LambdaQueryWrapper<T>()
                .select(this.classz, e -> false).last("order by id desc limit 1"), 600, "");
    }

    /**
     * @param param        分页参数
     * @param pageWrapper  查询参数 分页
     * @param lastWrapper  查询参数 最后一条数据
     * @param expireSecond 过期秒数
     * @param id           分页区分标识
     * @return 返回由id索引的数据
     * @throws IllegalAccessException 反射异常
     */
    @Override
    public PageVO<T> getPage(PageParam param, LambdaQueryWrapper<T> pageWrapper, LambdaQueryWrapper<T> countWrapper,
                             LambdaQueryWrapper<T> lastWrapper, int expireSecond, String id) throws IllegalAccessException {
        //缓存key
        final String key = SysRedisConstant.PAGE_COUNT + this.getClassName() + id;
        //获取缓存中分页总条数
        long count = Long.parseLong(Optional.ofNullable((String) redis.opsForValue().get(key)).orElse("0"));

        //下一页就是当前页最后一条数据的id   上一页就是当前页第一条数据id
        long lastId;
        //传入的当前页最后一条数据的id
        if (StringUtils.isBlank(param.getCurrentLastId())) {
            T t = getOne(lastWrapper);
            if (t == null) {
                lastId = 0;
            } else {
                lastId = Long.parseLong(this.getPrimaryKeyValue(t));
            }
        } else {
            lastId = Long.parseLong(param.getCurrentLastId());
        }

        //默认为下一页 nexted true  逆序 <    顺序 >
        if (Optional.ofNullable(param.getNexted()).orElse(Boolean.TRUE)) {
            if (param.getCurrent() == 1) {
                //第一页 <= 包含第一条数据
                pageWrapper.apply("id<=" + lastId);
            } else {
                //下一页 < 不包含上一条数据
                pageWrapper.apply("id<" + lastId);
            }
        } else {
            // > 上一页数据
            pageWrapper.apply("id <=" + Optional.ofNullable(param.getTopFirstId()).orElse("0"));
        }
        //按时间逆序 限制查询条数
        pageWrapper.last("order by id desc limit " + param.getSize());

        return new PageVO<T>().setData(list(pageWrapper)).setCurrent(param.getCurrent()).setSize(param.getSize()).setPages(count / param.getSize()).setTotal(count);
    }


    @Override
    public PageVO<T> getPage(PageParam param, List<T> pls) {
        if (CollectionUtils.isEmpty(pls)) {
            return new PageVO<>();
        }
        final int count = pls.size();
        final int current = param.getCurrent().intValue();
        final int size = param.getSize().intValue();
        //分页
        final int start = (current - 1) * size;
        final int end = Math.min(size * current, count);
        if (start > end) {
            //TODO start > end 错误待解决
            return new PageVO<T>().setPages((long) ((count + size - 1) / size)).setTotal((long) count).setSize(param.getSize()).setCurrent(param.getCurrent());
        } else {
            pls = pls.subList(start, end);
            return new PageVO<T>().setPages((long) ((count + size - 1) / size)).setTotal((long) count).setSize(param.getSize()).setCurrent(param.getCurrent()).setData(pls);
        }
    }

}

完整代码请看项目git地址

https://gitee.com/sunuping/jianmu-example-jdk17.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

等一场春雨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值