This website requires JavaScript.

PageImp无法序列化问题

问题

使用Spring data的Page进行分页之后,在缓存的时候发生无法序列化的问题,原因是PageImp没有无参构造函数,而GenericJackson2JsonRedisSerializer在反序列化的时候针对空值情况需要使用无餐构造函数

ERROR: Could not read JSON: Cannot construct instance of `org.springframework.data.domain.PageImpl` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

解决

  • 要么改用本地缓存,cachetype设置为simple等(逃避

  • 要么自定义序列化器

  • 要么更改序列化器

JdkSerializationRedisSerializer,通用型较好,但是效率较低,占用空间更大,并且序列化后是二进制数组,可读性较差

或者使用FST、Kryo,性能会更高,Kryo线程不安全,还需要自己registry对象

有关序列化器选型:https://my.oschina.net/wangshuhui/blog/3144798

对比测试:https://gitee.com/SoftMeng/spring-boot-skill/tree/master/redis-serializer-line

  • 要么自定义一个有无餐构造的page类(要把用到page的地方都重构,有点痛苦)

通用的自定义Page类:(这里可以用装饰器模式)

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;


public class MyPage<T> implements Iterable<T>, Serializable {
    private static final long serialVersionUID = -2295910683371889666L;
    private List<T> content = new ArrayList<>();
    private long totalElements;
    private int pageNumber;
    private int pageSize;
    private boolean first;
    private boolean last;
    private boolean empty;
    private int totalPages;
    private int numberOfElements;
    private Sort sort;

    public MyPage() {
    }

    /**
     * 原Page转换为MyPage
     * @param page
     */
    public MyPage(Page<T> page) {
        this.content = page.getContent();
        this.totalElements = page.getTotalElements();
        this.pageNumber = page.getPageable().getPageNumber();
        this.pageSize = page.getPageable().getPageSize();
        this.numberOfElements = page.getNumberOfElements();
        this.sort = page.getSort();
    }

    /**
     * 是否有前一页
     * @return
     */
    public boolean hasPrevious() {
        return getPageNumber() > 0;
    }

    /**
     * 是否有下一页
     * @return
     */
    public boolean hasNext() {
        return getPageNumber() + 1 < getTotalPages();
    }

    /**
     * 是否第一页
     * @return
     */
    public boolean isFirst() {
        return !hasPrevious();
    }

    /**
     * 是否最后一页
     * @return
     */
    public boolean isLast() {
        return !hasNext();
    }

    /**
     * 获取内容
     * @return
     */
    public List<T> getContent() {
        return Collections.unmodifiableList(content);
    }

    /**
     * 设置内容
     */
    public void setContent(List<T> content) {
        this.content = content;
    }

    /**
     * 是否有内容
     * @return
     */
    public boolean hasContent() {
        return getNumberOfElements() > 0;
    }

    /**
     * 获取单页大小
     * @return
     */
    public int getPageSize() {
        return pageSize;
    }

    /**
     * 设置单页大小
     * @param pageSize
     */
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    /**
     * 获取全部元素数目
     * @return
     */
    public long getTotalElements() {
        return totalElements;
    }

    /**
     * 设置全部元素数目
     * @param totalElements
     */
    public void setTotalElements(long totalElements) {
        this.totalElements = totalElements;
    }

    /**
     * 设置是否第一页
     * @param first
     */
    public void setFirst(boolean first) {
        this.first = first;
    }

    /**
     * 设置是否最后一页
     * @param last
     */
    public void setLast(boolean last) {
        this.last = last;
    }

    /**
     * 获取当前页号
     * @return
     */
    public int getPageNumber() {
        return pageNumber;
    }

    /**
     * 设置当前页号
     * @param pageNumber
     */
    public void setPageNumber(int pageNumber) {
        this.pageNumber = pageNumber;
    }

    /**
     * 获取总页数
     * @return
     */
    public int getTotalPages() {
        return getPageSize() == 0 ? 1 : (int) Math.ceil((double) totalElements / (double) getPageSize());
    }

    /**
     * 设置总页数
     * @param totalPages
     */
    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

    /**
     * 获取单页元素数目
     * @return
     */
    public int getNumberOfElements() {
        return numberOfElements;
    }

    /**
     * 设置单页元素数目
     * @param numberOfElements
     */
    public void setNumberOfElements(int numberOfElements) {
        this.numberOfElements = numberOfElements;
    }

    /**
     * 获得Sort
     * @return
     */
    public Sort getSort() {
        return sort;
    }

    /**
     * 设置Sort
     * @param sort
     */
    public void setSort(Sort sort) {
        this.sort = sort;
    }

    /**
     * 判断是否为空
     * @return
     */
    public boolean isEmpty() {
        return !hasContent();
    }

    /**
     * 设置是否为空
     * @param empty
     */
    public void setEmpty(boolean empty) {
        this.empty = empty;
    }

    /**
     * 迭代器
     * @return
     */
    @Override
    public Iterator<T> iterator() {
        return getContent().iterator();
    }
}
0条评论
avatar