购物项目实战学习记录(7)——分页功能实现

几个重要的类

PagingResult

分页结果的封装,结果(List)+分页信息。

Search

查询相关的类,封装查询条件+分页信息(当前页和每页记录数)。

BaseMybatisDAO

分页查询相关方法。

前端分页显示

通过PagingResult中的当前页码数总页码数每页显示数来计算最大显示页码
下面通过一些逻辑,来制定第一页最后一页中间页的显示。

<#macro paging pagingList url>
	<#--计算最大页码-->
    <#if pagingList.total % pagingList.pageSize == 0>
        <#assign maxPageIndex = pagingList.total / pagingList.pageSize>
    <#else>
        <#assign maxPageIndex = (pagingList.total / pagingList.pageSize)?floor + 1>
    </#if>

	<div class="page">
        <#--第一页,禁用“上一页”按钮-->
        <#if pagingList.total == 0 || pagingList.page == 1>
        	<span class="prev-disabled">上一页</span>
        <#else>
        	<#if pagingList.page == 2>
            	<a href="${url}">上一页</a>
            <#else>
            	<a href="${url}/${pagingList.page-1}">上一页</a>
            </#if>
        </#if>

        <#--第一页-->
        <#if (pagingList.total > 0)>
            <a href="${url}" <#if pagingList.page == 1>class="current_page"</#if>>1</a>
        </#if>

        <#--如果不只有一页-->
        <#if (maxPageIndex > 1)>
            <#--如果当前页往前查3页不是第2页-->
            <#if ((pagingList.page - 3) > 2)>
                <span class="text"></span>
            </#if>

            <#--当前页的前3页和后3页-->
            <#list (pagingList.page - 3)..(pagingList.page + 3) as index>
                <#--如果位于第一页和最后一页之间-->
                <#if (index > 1) && (index < maxPageIndex)>
                    <a href="${url}/${index}" <#if pagingList.page == index>class="current_page"</#if>>${index}</a>
                </#if>
            </#list>

            <#--如果当前页往后查3页不是倒数第2页-->
            <#if (pagingList.page + 3) < (maxPageIndex - 1)>
                <span class="text"></span>
            </#if>

            <#--最后页-->
            <a href="${url}/${maxPageIndex}" <#if pagingList.page == maxPageIndex>class="current_page"</#if>>${maxPageIndex}</a>
        </#if>

        <#--最后页,禁用“下一页”按钮-->
        <#if pagingList.total == 0 || pagingList.page == maxPageIndex>
            <span class="prev-disabled">下一页</span>
        <#else>
            <a href="${url}/${pagingList.page+1}">下一页</a>
        </#if>
    </div>
</#macro>

(1)第一页:禁用上一页。
(2)最后一页:禁用下一页。
(3)中间页(相差两端5页以上):显示...
PS:这里首页为不带页码的URL。

后台代码逻辑

Controller

	@RequestMapping(value = "/category/{urlName}/{page}", method = RequestMethod.GET)
	public String listDealsOfDealCategory(@PathVariable String urlName, @PathVariable Integer page, Model model,
										  HttpServletRequest request) {
		DealCategory dealCategory = dealCategoryService.getByUrlName(urlName);

		model.addAttribute("dealCategory", dealCategory);
		PagingResult<Deal> pageResult = dealService.getDealsOfCategories(dealCategory.getSelfAndChildrenIds(),
//				getAreaId(request), page, DealConstant.DEAL_NUM_PER_PAGE_IN_DEALS_OF_CATEGORY_PAGE);
				getAreaId(request), page, 6);
		model.addAttribute("pagingDealList", pageResult);
		return "/deal/category";
	}

说明:
(1)先拿到分类名称,根据分类名称进行查询,需要注意的是:包括他的孩子节点(细分的类别)。
(2)关键方法dealService.getDealsOfCategories(dealCategory.getSelfAndChildrenIds(),getAreaId(request), page, 6);
获取PagingResult<Deal>
(3)拿到封装后的对象,添加到模型里面供前端使用。

Service

    public PagingResult<Deal> getDealsOfCategories(List<Long> categoryIds, Long areaId, int page, int rows) {
        Search search = new Search();
        List<Condition> conditionList = new ArrayList<>();
        conditionList.add(new Condition("publishStatus", DealConstant.DEAL_PUBLISH_STATUS_PUBLISH)); // 发布状态为已发布

        conditionList.add(new Condition("categoryIdList", categoryIds));
        conditionList.add(new Condition("nowTime", new Date()));
        conditionList.add(new Condition("areaId", areaId));
        search.setConditionList(conditionList);
        search.setPage(page);
        search.setRows(rows);

        return dealDAO.getDealsOfCategories(search);
    }

说明:
(1)构建Search查询类,封装查询条件(ConditionList)和分页信息。
(2)构建查询条件,发布状态、类别ID、时间、地区ID。
(3)数据库查询,返回封装的结果。

DealDAO

    public PagingResult<Deal> getDealsOfCategories(Search search) {
        return super.findForPage(MAPPER_NAMESPACE + ".countDealsOfCategories", MAPPER_NAMESPACE
                + ".selectDealsOfCategories", search);
    }

说明:调用父类的findForPage方法,第一个sqlId为计算记录总数,第二个sqlId为查询相应的记录。
疑问:分页必须查询所有的记录吗?表小一点还好,如果表很大,岂不是内存爆了。

BaseMybatisDAO

	public <T extends BaseEntity> PagingResult<T> findForPage(String countSqlId, String sqlId, Search search) {
		RowBounds rowBounds = new RowBounds(search.getFirstRowNum(), search.getRows());
		List<T> list = template.selectList(sqlId, getConditionMap(search), rowBounds);
		return new PagingResult<>(count(countSqlId, search), list, search.getPage(), search.getRows());
	}
	// 不用Search条件如何分页
	public <T extends BaseEntity> PagingResult<T> findForPage(String countSqlId, String sqlId, int page, int rows, Map<String, Object> params) {
		RowBounds rowBounds = new RowBounds((page - 1) * rows, rows);
		List<T> data = template.selectList(sqlId, params, rowBounds);
		return new PagingResult<>(count(countSqlId, params), data, page, rows);
	}

说明:
(1)RowBounds为MyBatis自带的分页处理工具,对于index之前的采取skip操作,采用limit操作限制数量。
(2)getConditionMap只是把封装在search中的ConditionList转换为Map。
(3)template.selectList查询所有语句,附带参数rowBounds,进行分页查询。【解答了上面的疑问。。。】
(4)封装一个分页结果,count(countSqlId, search)利用数据库查询总数,封装当前结果集、当前页码、显示数量。
(5)重点是RowBounds,即使不用Search也可以通过上面第二个方法进行分页查询,根据RowBounds的参数进行构造。
(6)也可以不查询总量,既返回值中构造的对象第一个参数为0,因为总量太大,前端没有显示的必要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值