All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wl4g.infra.common.bean.page.PageHolder Maven / Gradle / Ivy

There is a newer version: 3.1.72
Show newest version
/*
 * Copyright 2017 ~ 2025 the original author or authors. James Wong 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wl4g.infra.common.bean.page;

import static com.wl4g.infra.common.lang.Assert2.notNullOf;
import static com.wl4g.infra.common.serialize.JacksonUtils.toJSONString;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import static java.util.Objects.nonNull;

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

import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;

import org.apache.commons.beanutils.BeanUtilsBean2;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.wl4g.infra.common.bridge.RpcContextHolderBridges;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiModelProperty.AccessMode;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.annotations.ApiParam;

/**
 * The original intention of the integrated paging packaging model is that
 * multiple modules under microservices must be completely decoupled. Therefore,
 * we refer to part of the code of 11 instead of relying on it directly. We are
 * very grateful for {@link com.github.pageSpechelper.PageSpec} work and fully
 * abide by your agreements.
 * 
 * @auhtor James Wong 
 * @version v1.0 2018年9月7日
 * @since
 * @see https://github.com/pageSpechelper/Mybatis-PageHelper/blob/master/wikis/zh/Interceptor.md
 */
@ApiModel("Pagination")
@SuppressWarnings("unchecked")
public class PageHolder implements Serializable {
    private static final long serialVersionUID = -7002775417254397561L;

    /**
     * PageSpec of {@link PageSpec}
     */
    @Schema(hidden = true, accessMode = io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE)
    @JsonIgnore
    private PageSpec pageSpec;

    /**
     * PageSpec record rows.
*
* * Note: The following annotation combination configuration does not * implement the effect that the records field can make the request display * no two responses. Can't swagger2 still achieve this effect: when the type * of request and response are the same model class, can't some fields be * displayed or not displayed according to the request and response?
*
* *

* for negative examples: * *

     * @ApiOperation(value = "Query myuser page list")
     * @RequestMapping(value = "/list", method = { GET })
     * public RespBase<PageModel<MyUserModel>> list(PageModel<MyUserModel> pm, MyUserModel param) {
     *     RespBase<PageModel<MyUserModel>> resp = RespBase.create();
     *     resp.setData(myUserService.pageSpec(pm, param));
     *     return resp;
     * }
     * 
* * for positive examples(Solution): * *
     * @ApiOperation(value = "Query myuser page list")
     * @ApiImplicitParams({
     *	@ApiImplicitParam(name = "pageNum", dataType = "int32", defaultValue = "1"),
     *	@ApiImplicitParam(name = "pageSize", dataType = "int32", defaultValue = "10")
     * })
     * @RequestMapping(value = "/list", method = { GET })
     * public RespBase<PageModel<MyUserModel>> list({@code @ApiIgnore} PageModel<MyUserModel> pm, MyUserModel param) {
     * 	RespBase<PageModel<MyUserModel>> resp = RespBase.create();
     * 	resp.setData(myUserService.pageSpec(pm, param));
     * 	return resp;
     * }
     * 
*

*/ @Schema(hidden = false, accessMode = io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY) @ApiModelProperty(readOnly = true, accessMode = AccessMode.READ_ONLY) @ApiParam(readOnly = true, hidden = true) @JsonIgnoreProperties(allowGetters = true, allowSetters = false) private List records = (List) DEFAULT_RECORDS; public PageHolder() { this(1, 10); } public PageHolder(@NotNull PageHolder page) { notNullOf(page, "page"); setPageSpec(page.getPageSpec()); } public PageHolder(@NotNull PageSpec pageSpec) { setPageSpec(pageSpec); } public PageHolder(@Nullable Integer pageNum, @Nullable Integer pageSize) { setPageSpec(new PageSpec()); getPageSpec().setPageNum(pageNum); getPageSpec().setPageSize(pageSize); } public PageSpec getPageSpec() { return pageSpec; } public final void setPageSpec(@NotNull PageSpec pageSpec) { this.pageSpec = notNullOf(pageSpec, "pageSpec"); } public final PageHolder withPageSpec(@NotNull PageSpec pageSpec) { setPageSpec(pageSpec); return this; } public Integer getPageNum() { return pageSpec.getPageNum(); } public void setPageNum(@Nullable Integer pageNum) { if (nonNull(pageNum)) { pageSpec.setPageNum(pageNum); } } public PageHolder withPageNum(@Nullable Integer pageNum) { setPageNum(pageNum); return this; } public Integer getPageSize() { return pageSpec.getPageSize(); } public void setPageSize(@Nullable Integer pageSize) { if (nonNull(pageSize)) { pageSpec.setPageSize(pageSize); } } public PageHolder withPageSize(@Nullable Integer pageSize) { setPageSize(pageSize); return this; } public Long getTotal() { return pageSpec.getTotal(); } public void setTotal(@Nullable Long total) { if (nonNull(total)) { pageSpec.setTotal(total); } } public PageHolder withTotal(@Nullable Long total) { setTotal(total); return this; } public Integer getPages() { return pageSpec.getPages(); } public void setPages(Integer pageSpecs) { if (nonNull(pageSpecs)) { pageSpec.setPages(pageSpecs); } } public PageHolder withPages(Integer pageSpecs) { return this; } public List getRecords() { return records; } public final void setRecords(List records) { if (nonNull(records) && !records.isEmpty()) { this.records = records; } } public PageHolder withRecords(List records) { setRecords(records); return this; } @Override public String toString() { return getClass().getSimpleName().concat("<").concat(toJSONString(this)).concat(">"); } // --- Current pageSpec function methods. --- public PageHolder useCount() { getPageSpec().setCount(true); return this; } /** * Sets pageSpec in current Rpc context. */ public PageHolder bind() { Util.bind(false, getPageSpec()); return this; } /** * For example jdbc/mybatis/mongo-collection/... pagination specification. *
* Thank refer to very much {@link com.github.pageSpechelper.PageSpec}. We * are in full compliance with your agreements. * * @param * @see http://git.oschina.net/free/Mybatis_PageHelper */ public static class PageSpec implements Serializable { private static final long serialVersionUID = -5149671532631896079L; /** PageSpec number, starting from 0 */ private int pageNum; /** PageSpec size. */ private int pageSize; /** Start row. */ private int startRow; /** End row. */ private int endRow; /** Total row count. */ private long total; /** Total pageSpec size. */ private int pageSpecs; /** Include count query. */ private boolean count; /** * Count signal: in three cases, the default boundsql is executed when * null, count is executed when true, and paging is performed when * false. */ private Boolean countSignal; /** Sort of sql. */ private String orderBy; /** Add sort only. */ private boolean orderByOnly; /** Paging rationalization. */ private Boolean reasonable; /** * When set to true, if PageSize is set to 0 (or rowbounds limit = 0), * paging is not performed and all results are returned. */ private Boolean pageSizeZero; public PageSpec() { super(); } public PageSpec(int pageNum, int pageSize) { this(pageNum, pageSize, true, null); } public PageSpec(int pageNum, int pageSize, boolean count) { this(pageNum, pageSize, count, null); } private PageSpec(int pageNum, int pageSize, boolean count, Boolean reasonable) { if (pageNum <= 1 && pageSize == Integer.MAX_VALUE) { pageSizeZero = true; pageSize = 0; } this.pageNum = (pageNum <= 0 ? 0 : pageNum); this.pageSize = pageSize; this.count = count; calculateStartAndEndRow(); setReasonable(reasonable); } /** * int[] rowBounds 0 : offset 1 : limit */ public PageSpec(int[] rowBounds, boolean count) { if (rowBounds[0] == 0 && rowBounds[1] == Integer.MAX_VALUE) { pageSizeZero = true; this.pageSize = 0; } else { this.pageSize = rowBounds[1]; this.pageNum = rowBounds[1] != 0 ? (int) (Math.ceil(((double) rowBounds[0] + rowBounds[1]) / rowBounds[1])) : 0; } this.startRow = rowBounds[0]; this.count = count; this.endRow = this.startRow + rowBounds[1]; } public int getPages() { return pageSpecs; } public PageSpec setPages(int pageSpecs) { this.pageSpecs = pageSpecs; return this; } public int getEndRow() { return endRow; } public PageSpec setEndRow(int endRow) { this.endRow = endRow; return this; } public int getPageNum() { return pageNum; } public PageSpec setPageNum(int pageNum) { // 分页合理化,针对不合理的页码自动处理 this.pageNum = ((reasonable != null && reasonable) && pageNum <= 0) ? 1 : pageNum; return this; } public int getPageSize() { return pageSize; } public PageSpec setPageSize(int pageSize) { this.pageSize = pageSize; return this; } public int getStartRow() { return startRow; } public PageSpec setStartRow(int startRow) { this.startRow = startRow; return this; } public long getTotal() { return total; } public void setTotal(long total) { this.total = total; if (total == -1) { pageSpecs = 1; return; } if (pageSize > 0) { pageSpecs = (int) (total / pageSize + ((total % pageSize == 0) ? 0 : 1)); } else { pageSpecs = 0; } // 分页合理化,针对不合理的页码自动处理 if ((reasonable != null && reasonable) && pageNum > pageSpecs) { pageNum = pageSpecs; calculateStartAndEndRow(); } } public Boolean getReasonable() { return reasonable; } public PageSpec setReasonable(Boolean reasonable) { if (reasonable == null) { return this; } this.reasonable = reasonable; // 分页合理化,针对不合理的页码自动处理 if (this.reasonable && this.pageNum <= 0) { this.pageNum = 1; calculateStartAndEndRow(); } return this; } public Boolean getPageSizeZero() { return pageSizeZero; } public PageSpec setPageSizeZero(Boolean pageSizeZero) { if (pageSizeZero != null) { this.pageSizeZero = pageSizeZero; } return this; } /** * 计算起止行号 */ private void calculateStartAndEndRow() { this.startRow = this.pageNum > 0 ? (this.pageNum - 1) * this.pageSize : 0; this.endRow = this.startRow + this.pageSize * (this.pageNum > 0 ? 1 : 0); } public boolean isCount() { return this.count; } public PageSpec setCount(boolean count) { this.count = count; return this; } public String getOrderBy() { return orderBy; } public PageSpec setOrderBy(String orderBy) { this.orderBy = orderBy; return this; } public boolean isOrderByOnly() { return orderByOnly; } public void setOrderByOnly(boolean orderByOnly) { this.orderByOnly = orderByOnly; } public Boolean getCountSignal() { return countSignal; } public void setCountSignal(Boolean countSignal) { this.countSignal = countSignal; } // 增加链式调用方法 /** * 设置页码 * * @param pageNum * @return */ public PageSpec pageNum(int pageNum) { // 分页合理化,针对不合理的页码自动处理 this.pageNum = ((reasonable != null && reasonable) && pageNum <= 0) ? 1 : pageNum; return this; } /** * 设置页面大小 * * @param pageSize * @return */ public PageSpec pageSize(int pageSize) { this.pageSize = pageSize; calculateStartAndEndRow(); return this; } /** * 是否执行count查询 * * @param count * @return */ public PageSpec count(Boolean count) { this.count = count; return this; } /** * 设置合理化 * * @param reasonable * @return */ public PageSpec reasonable(Boolean reasonable) { setReasonable(reasonable); return this; } /** * 当设置为true的时候,如果pageSpecsize设置为0(或RowBounds的limit=0),就不执行分页,返回全部结果 * * @param pageSizeZero * @return */ public PageSpec pageSizeZero(Boolean pageSizeZero) { setPageSizeZero(pageSizeZero); return this; } @Override public String toString() { return "PageSpec{" + "count=" + count + ", pageNum=" + pageNum + ", pageSize=" + pageSize + ", startRow=" + startRow + ", endRow=" + endRow + ", total=" + total + ", pageSpecs=" + pageSpecs + ", countSignal=" + countSignal + ", orderBy='" + orderBy + '\'' + ", orderByOnly=" + orderByOnly + ", reasonable=" + reasonable + ", pageSizeZero=" + pageSizeZero + '}'; } } /** * Internal utility for {@link PageHolder} */ public static final class Util { /** * Sets pageSpec in current Rpc context. * * @param useServerContext * @param pageSpec */ public static void bind(boolean useServerContext, @Nullable PageSpec pageSpec) { localCurrentPage.set(pageSpec); if (RpcContextHolderBridges.hasRpcContextHolderClass()) { // Distributed(cluster)? RpcContextHolderBridges.invokeSet(useServerContext, CURRENT_PAGE_KEY, pageSpec); } } /** * Gets current {@link PageHolder} from (RPC)context. * * @param useServerContext * @return */ public @Nullable static PageSpec current(boolean useServerContext) { PageSpec lCurrentPage = (PageSpec) localCurrentPage.get(); if (RpcContextHolderBridges.hasRpcContextHolderClass()) { // Distributed-mode? PageSpec rCurrentPage = (PageSpec) RpcContextHolderBridges.invokeGet(useServerContext, CURRENT_PAGE_KEY, PageSpec.class); if (nonNull(rCurrentPage) && nonNull(lCurrentPage)) { try { BeanUtilsBean2.getInstance().copyProperties(rCurrentPage, lCurrentPage); } catch (Exception e) { throw new IllegalStateException(e); } } else { // Fallback lCurrentPage = rCurrentPage; } } return lCurrentPage; } /** * Reload current executed paging information to local current pageSpec * object and release from local and origin RPC context. */ public static void update() { // Reload executed paging information to local current pageSpec // object. current(true); // Remove object reference from local. localCurrentPage.remove(); // Remove from RPC origin context. if (RpcContextHolderBridges.hasRpcContextHolderClass()) { // Distributed-mode? // It's cleanup too: // see:com.wl4g.infra.integration.feign.core.context.interceptor.ProviderFeignContextFilter#postHandle RpcContextHolderBridges.invokeRemoveAttachment(false, CURRENT_PAGE_KEY); } } /** * Distributed mode, current pageSpec RPC context key. */ private static transient final String CURRENT_PAGE_KEY = "currentPage"; private static transient final ThreadLocal localCurrentPage = new ThreadLocal<>(); } private static transient final List DEFAULT_RECORDS = unmodifiableList(emptyList()); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy