关于 PageInfo 泛型类型转换的抽象

2,283 阅读2分钟

#java #mybatis #PageHelper #PageInfo #泛型

背景

通常在使用 Mybatis PageHelper 插件时,会将 PageInfo 对象直接作为 response 返回。

经常会遇到如下类似的场景:

controller 层返回的 PageInfo 泛型类型通常会定义为 VO 等类型。但是在 mapper 层,返回的 PageInfo 对象通常是 model 类型。

所以返回的时候还需要有很多手动处理类型转换的代码。造成代码很臃肿,类似的代码在项目中会出现很多。

目标

提供一个工具类,将相同的代码封装起来,可变的部分暴露给开发者自己实现。

工具类

import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;

import java.util.List;
import java.util.stream.Collectors;

public class PageInfoUtil {
    @FunctionalInterface
    public interface PageInfoConvertor<T, R> {
        /**
         * convert 将 T 类型对象转换为 R 类型对象
         *
         * @param t 原始类型对象
         * @return 目标类型对象
         */
        R convert(T t);
    }

    /**
     * convertPageInfo 转换 PageInfo 泛型类型
     *
     * @param sourcePageInfo 原始的 pageInfo 对象
     * @param convertor      自定义转换器
     * @param <T>            原始类型
     * @param <R>            目标类型
     * @return 转换之后的 PageInfo 对象
     */
    public static <T, R> PageInfo<R> convertPageInfo(PageInfo<T> sourcePageInfo, PageInfoConvertor<T, R> convertor) {
        Page<R> page = new Page<>(sourcePageInfo.getPageNum(), sourcePageInfo.getPageSize());
        page.setTotal(sourcePageInfo.getTotal());

        PageInfo<R> targetPageInfo = new PageInfo<>(page);
        List<R> targetList = sourcePageInfo.getList().stream().map(convertor::convert).collect(Collectors.toList());
        targetPageInfo.setList(targetList);
        return targetPageInfo;
    }

    /**
     * convertPageInfo 转换 PageInfo 泛型类型
     *
     * @param sourcePageInfo 原始的 pageInfo 对象
     * @param targetClazz    需要转换的 PageInfo 泛型类型
     * @param <T>            原始类型
     * @param <R>            目标类型
     * @return 转换之后的 PageInfo 对象
     */
    public static <T, R> PageInfo<R> convertPageInfo(PageInfo<T> sourcePageInfo, Class<R> targetClazz) {
        Page<R> page = new Page<>(sourcePageInfo.getPageNum(), sourcePageInfo.getPageSize());
        page.setTotal(sourcePageInfo.getTotal());

        PageInfo<R> targetPageInfo = new PageInfo<>(page);
        List<R> targetList = sourcePageInfo.getList().stream().map(e -> {
            try {
                R r = targetClazz.getDeclaredConstructor().newInstance();
                BeanUtils.copyProperties(e, r);
                return r;
            } catch (Exception exception) {
                throw new RuntimeException("convertPageInfo cause exception", exception);
            }
        }).collect(Collectors.toList());
        targetPageInfo.setList(targetList);
        return targetPageInfo;
    }
}

提供两个方法:

convertPageInfo(PageInfo<T> sourcePageInfo, PageInfoConvertor<T, R> convertor)

其中 PageInfoConvertor 是一个函数式接口,用户可以在开发的时候自定义泛型类型的转换规则。 有时候我们需要转换的类型中部分字段需要其他的业务逻辑处理,就可以采用这种方式。

convertPageInfo(PageInfo<T> sourcePageInfo, Class<R> targetClazz)

通过第二参数指定泛型转换的类型,该方法内部是通过 BeanUtils.copyProperties() 方法做类型转换的。 当原类型和目标类型属性一致的场景下个,可以采用这种方式。

使用

指定泛型转换类型:

PageInfo<Bean2> targetPageInfo = PageInfoUtil.convertPageInfo(pageInfo, Bean2.class);

自定义转换规则:

PageInfo<Bean2> targetPageInfo = PageInfoUtil.convertPageInfo(pageInfo, (bean1) -> {
    Bean2 bean2 = new Bean2();
    bean2.setName(bean1.getName());
    return bean2;
});

完事!🎉🎉🎉🎉