Java分页类定义和使用
1 简介
在后端与前端进行交互的过程中,需要对后端得到的数据进行分页推送给前端,比如说在某个博客网站上某用户编写了100篇文档,但在页面展示时,可能在每个页面仅仅展示10条数据,如下图所示
因此,而且此类需求是一个常见需求,所以可以总结一下这个用法。
一般需要实现该情景,需要返回的类似数据如下:
{"result": "success","msg": "查询历史信息成功","data": {"totalPage": 66,"pageSize": 10,"currentPage": 1,"rows": [{"month": "08","createTime": "2018-12-24 16:15:36","year": "2018","description": "完成2018年08月的缴纳, 金额为800.0元","operation": "缴纳","operator": "周周"},{"month": "08","createTime": "2018-12-24 15:22:01","year": "2018","description": "完成2018年08月购买的发起","operation": "党费发起","operator": "周周"},{"month": "08","createTime": "2018-12-24 15:13:36","year": "2018","description": "完成文件的上传,可以发起2018年08月的购买流程","operation": "上传工资","operator": "周周"},{"month": "03","createTime": "2018-12-24 10:52:40","year": "2021","description": "完成2021年03月购买的部门领导","operation": "部门领导","operator": "猪八戒"},{"month": "03","createTime": "2018-12-24 10:52:07","year": "2021","description": "完成综合计划室党支部-政工组2021年03月购买的确认","operation": "党支部确认","operator": "松松"},{"month": "03","createTime": "2018-12-24 10:51:47","year": "2021","description": "完成2021年03月的购买, 金额为500.0元","operation": "购买","operator": "松松"},{"month": "03","createTime": "2018-12-24 10:51:27","year": "2021","description": "完成开发组2021年03月购买的确认","operation": "党支部确认","operator": "范范"},{"month": "03","createTime": "2018-12-24 10:51:22","year": "2021","description": "为吵吵代办2021年03月购买,金额为222.0元","operation": "党费代办","operator": "范范"},{"month": "03","createTime": "2018-12-24 10:51:12","year": "2021","description": "为猪八戒代办2021年03月购买,金额为555.0元","operation": "党费代办","operator": "范范"},{"month": "03","createTime": "2018-12-24 10:50:43","year": "2021","description": "完成2021年03月的购买, 金额为255.0元","operation": "购买","operator": "范范"}],"totalCount": 654}
}
一般在分页结构中应该包含的最少内容如下:
{“result”: “success”,“msg”: “获取数据成功”,“data”: {“totalCount”: 300,"totalPage": 66,"pageSize": 10,"currentPage": 1,rows: [{…},{…},{…},{…},…]}
}
因此,在定义该类时,应该包含上述5个成员totalCount, totalPage, pageSize, currentPage, 以及保存当前页对应的所有数据的rows成员.
2 定义
package com.sqh.util;import java.io.Serializable;
import java.util.List; public class Page<T> implements Serializable { private static final long serialVersionUID = 5760097915453738435L; public static final int DEFAULT_PAGE_SIZE = 10; /** * 每页显示个数 */ private int pageSize; /** * 当前页数 */ private int currentPage; /** * 总页数 */ private int totalPage; /** * 总记录数 */ private int totalCount; /** * 结果列表 */ private List<T> rows; public Page(){ this.currentPage = 1; this.pageSize = DEFAULT_PAGE_SIZE; } public Page(int currentPage,int pageSize){ this.currentPage=currentPage<=0?1:currentPage; this.pageSize=pageSize<=0?1:pageSize; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) {//设置了totalCount就可以计算出总totalPage this.totalCount = totalCount;int countRecords = this.getTotalCount();int totalPages = countRecords % pageSize == 0 ? countRecords / pageSize : (countRecords / pageSize + 1);setTotalPage(totalPages);} /** * 设置结果 及总页数 * @param rows 分页之后查询到的结果*/ public void build(List<T> rows) {this.setRows(rows);int count = this.getTotalCount();/*int divisor = count / this.getPageSize();int remainder = count % this.getPageSize();//设置总页数, Trash code, confusing.this.setTotalPage(remainder == 0 ? (divisor == 0 ? 1 : divisor) : divisor + 1);*///已在setTotalCount中进行/*
int countRecords = this.getTotalCount();int totalPages = countRecords % pageSize == 0 ? countRecords / pageSize : (countRecords / pageSize + 1);setTotalPage(totalPages);*/} public List<T> getRows() { return rows; } public void setRows(List<T> rows) {this.rows = rows; }
}
在该类使用时,应该首先使用步骤如下:
- currentPage和 pageSize进行分页类Page对象的实例化,
- 然后使用setTotalCount()函数传入总记录数,
- 这样在把当前页结果给取出来,传入Page对象,即可封装该分页结构
3 使用
3.1 Mongo数据库分页查询
在与mongo数据库进行交互时,由于没有直接提供分页的函数,因此我们可对这种应用场景进行封装
public Page<T> findPage(Page<T> page, Query query,String collectionName){//如果没有条件 则所有全部 query=query==null?new Query(Criteria.where("_id").exists(true)):query;long count = this.count(query, collectionName);// 总数 page.setTotalCount((int) count); int currentPage = page.getCurrentPage(); int pageSize = page.getPageSize(); query.skip((currentPage - 1) * pageSize).limit(pageSize); List<T> rows = this.find(query,collectionName); page.build(rows); return page; }
在上述的普通函数中,我们调用了Query类型,
public class Query extends Object
MongoDB Query类对象表示规则Criteria,投射Projection,排序sorting,和Query Hints。使用了mongoTemplate对象进行查询和计数。可查询相关API,不再赘述。
@RequestMapping(value = "/partydues/viewSalarayInfo", method = RequestMethod.POST)@ResponseBodypublic String viewSalarayInfo(@RequestBody JSONObject form) {System.out.println(("viewSalarayInfo starts"));JSONObject result = new JSONObject();if ((!form.containsKey("year")) || (!form.containsKey("month"))) {return result.element("result", "fail").element("msg", "查询工资时请指定年月参数").toString();}String year = form.getString("year");String month = form.getString("month");//获取分页参数并验证数据有效性if ((year.isEmpty()) || (month.isEmpty())) {return result.element("result", "fail").element("msg", "查询工资时年月参数不能为空").toString();}if ((!form.containsKey("pageSize")) || (!form.containsKey("page"))) {return result.element("result", "fail").element("msg", "查询时请指定分页信息").toString();}int page = form.getInt("page");int pageSize = form.getInt("pageSize");if (pageSize < 0) {pageSize = 10;}if (page<0) {page=0;}//创建分页对象Page<FreeModel> pageResult = new Page<FreeModel>();pageResult.setPageSize(pageSize);pageResult.setCurrentPage(page);Query query = new Query();query.addCriteria(new Criteria("map.year").is(year));query.addCriteria(new Criteria("map.month").is(month));query.with(new Sort(new Sort.Order(Sort.Direction.ASC, "map.orderBy")));//使用上述封装的函数,传入分页对象,和表名,这样在函数执行时自动填充totalCount,和rowsfreeDao.findPage(pageResult, query, SALARY_TABLE);List<FreeModel> rows = pageResult.getRows();JSONArray array = new JSONArray();//重组rows中的内容for(int i=0; i<rows.size(); i++) {//检索第一个元素,按照指定的形式返回前端数据PageData pageData = rows.get(i).getMap();JSONObject salaryRecord = JSONObject.fromObject(pageData);array.add(salaryRecord);}pageResult.setRows(array);return CommonReturn.httpReturn(CommonReturn.SUCCESS, "查询工资记录成功", pageResult);
}
可见,在上述的Controller层调用时依然遵循了相同的Page对象使用步骤。
3.2 普通List对象组装
在Java web开发的过程中,也存在一种情形,需要我们自己组织list数据,并返回给前端符合分页结构的数据,这也是一种常见的情形,对于这类情形,如何使用Page类进行分页对象的构建呢?查看下述例子:
/*** @description: 返回指定年月的工资信息,展示列表,支持分页展示* @url:* @author: Song Quanheng* @date: 2018/11/13-14:42* @return:*/@RequestMapping(value = "/partydues/viewSalarayInfoByDept/{year}/{month}")@ResponseBodypublic String viewSalaryInfoByDept(@PathVariable("year") String year,@PathVariable("month") String month, @RequestBody JSONObject form) {JSONObject res = new JSONObject();if (!form.containsKey("page") || !form.containsKey("pageSize")) {return CommonReturn.httpReturnFailure("请指定分页参数page和pageSize");}int page = form.getInt("page");int pageSize = form.getInt("pageSize");if (pageSize < 0) {pageSize = 10;}if (page<=0) {page=1;}Query query = new Query();query.addCriteria(new Criteria("map.year").is(year));query.addCriteria(new Criteria("map.month").is(month));JSONObject ret = partyDuesBusiness.findSalaryInfoByDept(year, month);if (ret.size() == 0) {return CommonReturn.httpReturnFailure("查询不到"+year+"年"+month+"月的工资信息");}JSONArray deptOrder = partyDuesBusiness.viewDeptInfoInOrder();JSONArray result = new JSONArray();if (0 == deptOrder.size()) {return CommonReturn.httpReturn(FAILURE, "请插入有序的部门名称到数据库中");}for (int i=0; i<deptOrder.size(); i++) {String deptName = deptOrder.getString(i);int count = 0;if (ret.containsKey(deptName)) {//根据部门名获得该部门相关的人数count = ret.getInt(deptName);} else {continue;}//如果0==count,表示该部门不用展示在页面上,因为不存在人员if (0==count) {continue;}JSONObject itemOne = new JSONObject();itemOne.put("deptName", deptName);itemOne.put("totalNumOfPersons", count);itemOne.put("year", year);itemOne.put("month", month);result.add(itemOne);}int countRecords = result.size();int totalPages = countRecords % pageSize == 0 ? countRecords / pageSize : (countRecords / pageSize + 1);//获得指定范围的结果List<JSONObject> pageResult = partyDuesBusiness.getListByPage(result, page, pageSize);//组织为分页对象Page pageRet = new Page(page, pageSize);pageRet.setRows(pageResult);pageRet.setTotalPage(totalPages);pageRet.setTotalCount(countRecords);return CommonReturn.httpReturn(CommonReturn.SUCCESS, "按照部门分组查询信息成功", pageRet);}
上述的代码遵循相同的步骤逻辑,查询分页范围内的结果,然后利用当前页和页面记录数新建分页对象,设置totalCount成员,最后设置分页范围的记录内容。返回给前端即可。
3.3 getListByPage
在上述普通的list对象生成分页数据的过程中,调用了一个函数getListByPage()函数,该函数封装内容如下:
public List getListByPage(List list,int page,int pageSize) {if(list.size() > 0 ){int firstIndex = (page - 1) * pageSize;int lastIndex = page * pageSize;int actualLastIndex = 0;if(list.size() > lastIndex || list.size() == lastIndex){actualLastIndex = lastIndex;}else{actualLastIndex = list.size();}return list.subList(firstIndex,actualLastIndex);}return list;
}
函数中主要使用List接口的subList函数。
List表示有序的collection。此接口的用户可以对列表中的每个元素的插入位置进行精确的控制。用户可以根据元素的整数索引访问元素,并搜索列表中元素的位置。
List<E> subList(int fromIndex, int toIndex)
返回列表中指定的fromIndex(包括)和toIndex(不包括)之间的部分视图。
返回:列表中指定范围的视图
抛出:IndexOutOfBoundsException – 非法的端点值(fromIndex<0 || toIndex > size || fromIndex > toIndex)
注意:由于getListByPage中list为List类型,因此只要类型实现了List接口,均可以传入,诸如ArrayList或者JSONArray都可以传入该函数进行分页提取数据。
4 总结
在编程过程中,对于不断重复的模式可以进行封装,这样既能锤炼代码的凝练度,同时可以增强代码的正确性。Java分页相关的内容介绍到这里,不断的反思和总结是一个人持续进步的基石,是每个程序员自我要求,自我实现的一部分。
5 参考
https://blog.csdn.net/lk142500/article/details/84561292
6下载
https://download.csdn.net/download/lk142500/10873558
Java分页类定义和使用相关推荐
- phppage类封装分页功能_PHP封装的page分页类定义与用法完整示例
本文实例讲述了PHP封装的page分页类定义与用法.分享给大家供大家参考,具体如下: 亲测有效,见下图=========> 1. 测试实例test.php header("Conten ...
- java里写分页,自己写的Java分页类
自己写的分页类 //分页类 package xiyou.cm.cattsoft.util; public class Page { private int totalRows;//总共记录数 priv ...
- java - 分页类
pager.java package com.jspnews.util;import java.io.Serializable; import java.util.List;/*** * <b& ...
- java box类定义三变量_01.类的成员变量:\n设计一个立方体类Box,定义三个属性,分别是长,宽,高。定义二个方法,分别计...
01.类的成员变量:\n设计一个立方体类Box,定义三个属性,分别是长,宽,高.定义二个方法,分别计算并输出立方体的体积和表面积 答:java.util.Scanner; public class B ...
- java分页类Page
package com.h3c.itac.util;import java.util.ArrayList; import java.util.List;@SuppressWarnings(" ...
- Java的类和包的总结
学习目录 面向对象的初步认识 面向对象和面向过程 简单的认识类 类定义的格式 类的实例化 总结类和对象 this引用 this引用的特性 构造方法 对象的初始化 封装 访问限定符 封装扩展包 包的 ...
- java定义一个类计算圆的半径,C++编程:定义一个圆类要求属性为半径,操作为计算圆的周长和面积...,java编程:定义一个圆类,属性为半径,方法为对输入的半径计...
导航:网站首页 > C++编程:定义一个圆类要求属性为半径,操作为计算圆的周长和面积...,java编程:定义一个圆类,属性为半径,方法为对输入的半径计 C++编程:定义一个圆类要求属性为半径, ...
- java定义一个学生类cstudent_编写一个JAVA程序片断 定义一个表示学生的类student
编写一个JAVA程序片断定义一个表示学生的类student,包括域"学号","班级","姓名","性别","年 ...
- 分页类实例 java
保存代码片段 分页类: 分页类,点击查看 1 package cn.news.vo; 2 3 import java.util.List; 4 /** 5 * 用于在页面上使用的数据类,包含有分页的信 ...
最新文章
- docker 上传到自己的容器
- python统计文件行数检测字符串_python统计文件中的字符串数目示例
- 时频特性分析(Matlab)
- 的有效性最好_世界前10名面膜补水排行榜 最好用的十款面膜推荐
- 利用反射获得类的public static/const成员的值
- huffman算法c语言实验报告,huffman二叉树实验报告--数据结构(c语言).doc
- R7-4 检查密码 (15 分)
- 19) maven 项目结构:聚集
- 中国急性髓系白血病药物市场趋势报告、技术动态创新及市场预测
- android mmkv使用_锦囊篇|一文摸懂SharedPreferences和MMKV(一)
- 开箱即用的SSH攻击字典收集工具
- 深度解析,AI如何让创新变得更简单
- ABP Framework 5.3.0 版本新增功能和变更说明
- python实现华氏温度和摄氏温度转换
- 正点原子ATK-LORA-01无线串口代码移植+STM32F103C8T6(标准库)
- 每日一练_是程序呀(每日更新)_XML
- foo:function(){}与function foo(){}还有foo=function()三者间的区别
- 报错:org.springframework.cloud.gateway.support.NotFoundException: Unable to find instance for localhos
- C语言实现稳定的快排
- 关于搭建一个简易搭建网站的大概步骤