zoukankan      html  css  js  c++  java
  • 自定义注解,更优雅的使用MP分页功能

    分页功能使用

    MP的分页功能是通过MyBatis的插件实现的,使用起来也非常简单。下面先介绍下使用方式。

    step1:配置分页插件

    @Configuration
    @EnableTransactionManagement
    @MapperScan("com.csx.demo.spring.boot.dao")
    public class MyBatisPlusConfig {
    
        private static final Logger log = LoggerFactory.getLogger(MyBatisPlusConfig.class);
    
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            // 如果是单数据源的话,最好制定数据库类型,不然的话MP需要根据数据库连接来推断数据库类型
            // 性能上略有损失
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
            interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return interceptor;
        }
    }
    

    需要注意的是:MP提供了很多开箱即用的插件,这些插件的使用顺序有讲究。官方文档建议的配置顺序是:

    目前已有的功能:

    • 自动分页: PaginationInnerInterceptor
    • 多租户: TenantLineInnerInterceptor
    • 动态表名: DynamicTableNameInnerInterceptor
    • 乐观锁: OptimisticLockerInnerInterceptor
    • sql性能规范: IllegalSQLInnerInterceptor
    • 防止全表更新与删除: BlockAttackInnerInterceptor

    注意:
    使用多个功能需要注意顺序关系,建议使用如下顺序
    多租户,动态表名
    分页,乐观锁
    sql性能规范,防止全表更新与删除
    总结: 对sql进行单次改造的优先放入,不对sql进行改造的最后放入

    step2:写分页代码

    IPage<User> page = new Page<>(1,10);
    ((Page<User>) page).addOrder(OrderItem.desc("user_id"));
    IPage<User> userIPage = userDAO.selectPage(page, null);
    

    自定义注解,更优雅的使用MP分页功能

    我们发现:虽然MP的分页插件使用起来非常简单,但是还是需要每次从参数中拿分页参数、排序参数等,代码看起来还是略微显得冗余。

    这边定义了一个自定义注解,可以简化上面的这些操作。下面是实现的代码。

    step1:定义自己的PageInfo

    说明下:这边的PageInfo是可以不定义的,你可以直接使用MP的IPage实现。但是个人具有洁癖,有些信息不想返回前端,所以定义了一个精简的PageInfo.

    /**
     * 自定义的PageInfo
     * 内容比MP中的IPage精简
     * @param <T>
     */
    public class PageInfo<T> {
    
        private Integer pageNo;
    
        private Integer pageSize;
    
        private String sortColumn;
        
        private Long total;
    
        private List<T> rows;
        
        public PageInfo(Integer pageNo, Integer pageSize, String sortColumn) {
            this.pageNo = pageNo;
            this.pageSize = pageSize;
            this.sortColumn = sortColumn;
        }
        // 省略get和set方法
    }
    

    step2:定义分页注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Pagination {
    
        // 可以自定义分页字段名称,当前页字段名称默认是pageNO
        String pageNoField() default "pageNo";
        // 可以自定义分页字段名称,每页数量名称默认是pageNO
        String pageSizeField() default "pageSize";
        // 可以自定义分页字段名称,排序字段名称默认是pageNO
        String sortField() default "sort";
        // 也可以通过注解指定排序字段
        String sortItem() default "";
    }
    

    step3:注解处理类

    @Aspect
    @Component
    public class PaginationHandler {
    
        private static final Logger log = LoggerFactory.getLogger(PaginationHandler.class);
    
        private static final int DEFAULT_PAGE_NO = 1;
        private static final int DEFAULT_PAGE_SIZE = 10;
    
        @Around("@annotation(pagination)&&args(pageParam)")
        public Object handlePagination(ProceedingJoinPoint point,
                                       Pagination pagination,
                                       Object pageParam) throws Throwable {
            int pageNo = DEFAULT_PAGE_NO;
            int pageSize = DEFAULT_PAGE_SIZE;
            String sortCols;
    
            String pageNoField = pagination.pageNoField();
            String pageSizeField = pagination.pageSizeField();
            String sortField = pagination.sortField();
            sortCols = pagination.sortItem();
    
            if (pageParam == null) {
                PageInfo pageInfo = new PageInfo(pageNo, pageSize, sortCols);
                PageUtil.setPageInfo(pageInfo);
            } else {
                if (pageParam instanceof Map) {
                    Map<String, Object> param = (Map<String, Object>) pageParam;
                    JSONObject json = new JSONObject(param);
                    if (json.getInteger(pageNoField) != null) {
                        pageNo = json.getIntValue(pageNoField);
                    }
                    if (json.getInteger(pageSizeField) != null) {
                        pageSize = json.getIntValue(pageSizeField);
                    }
                    if (json.getInteger(sortField) != null) {
                        sortCols = json.getString(sortField);
                    }
                    PageInfo pageInfo = new PageInfo(pageNo, pageSize, sortCols);
                    PageUtil.setPageInfo(pageInfo);
                } else {
                    // 暂时只支持Map类型的参数
                    // 如果需要支持其他类型的参数,可以在这边添加
                    PageInfo pageInfo = new PageInfo(pageNo, pageSize, sortCols);
                    PageUtil.setPageInfo(pageInfo);
                }
            }
            try {
                Object result = point.proceed();
                if (result instanceof Response) {
                    Object data = ((Response) result).getData();
                    if(data instanceof IPage){
                        long total = ((IPage) data).getTotal();
                        List records = ((IPage) data).getRecords();
                        PageInfo pageInfo = PageUtil.getPageInfo();
                        pageInfo.setTotal(total);
                        pageInfo.setRows(records);
                        ((Response) result).setData(pageInfo);
                    }
                    return result;
                } else {
                    // Todo 暂时没想到好的处理方法
                    return result;
                }
            } finally {
                PageUtil.removePageInfo();
            }
        }
    }
    

    step4:分页工具

    public class PageUtil {
    
        private static final String ASC = "asc";
    
        private static final String DESC = "desc";
    
        private static final Logger log = LoggerFactory.getLogger(PageUtil.class);
    
        private static final ThreadLocal<PageInfo> pageInfoHolder = new ThreadLocal<>();
    
        public static void setPageInfo(PageInfo pageInfo) {
            pageInfoHolder.set(pageInfo);
        }
    
        public static void removePageInfo() {
            pageInfoHolder.remove();
        }
    
        public static PageInfo getPageInfo() {
            return pageInfoHolder.get();
        }
    
        public static <T> IPage<T> page() {
            PageInfo pageInfo = getPageInfo();
            Integer pageNo = pageInfo.getPageNo();
            Integer pageSize = pageInfo.getPageSize();
            //col1:aes,col2:des形式
            String sortCols = pageInfo.getSortColumn();
            IPage<T> iPage = new Page<>(pageNo, pageSize);
            if (!StringUtils.isEmpty(sortCols)) {
                String[] split = sortCols.split(",");
                for (String s : split) {
                    try {
                        int index = s.lastIndexOf(':');
                        String col = s.substring(0, index);
                        String sortType = s.substring(index, s.length());
                        if(ASC.equalsIgnoreCase(sortCols)){
                            ((Page<T>) iPage).addOrder(OrderItem.asc(col));
                        } else if (DESC.equalsIgnoreCase(sortType)){
                            ((Page<T>) iPage).addOrder(OrderItem.desc(col));
                        } else {
                            log.warn("sort col {} is invalid, ignore it...",s);
                            continue;
                        }
                    } catch (Exception e) {
                        log.warn("sort col {} is invalid, ignore it...",s);
                    }
                }
            }
            return iPage;
        }
    }
    

    step5:使用

     @PostMapping("/page")
        @Pagination
        public Object info(@RequestBody Map param)  {
            IPage<User> page = userService.page(PageUtil.page(), null);
            Response response = new Response();
            response.success().success().setData(page);
            return response;
        }
    

    上面的代码比较简单,具体就不分析了。

  • 相关阅读:
    Flutter实战视频-移动电商-11.首页_屏幕适配方案讲解
    Flutter实战视频-移动电商-10.首页_FlutterSwiper轮播效果制作
    Flutter实战视频-移动电商-09.首页_项目结构建立和获取数据
    Flutter实战视频-移动电商-08.Dio基础_伪造请求头获取数据
    【RQNOJ】460 诺诺的队列
    NYOJ 483 Nightmare 【广搜】+【无标记】
    冒泡,简单选择,直接插入排序(Java版)
    基于MFC与第三方类CWebPage的百度地图API开发范例
    USACO 1.2 Palindromic Squares (进制转换,回文)
    与《新走遍美国》的邂逅
  • 原文地址:https://www.cnblogs.com/54chensongxia/p/14262676.html
Copyright © 2011-2022 走看看