分页的实现

最近用了一下EasyUI的分页插件,感觉用起来简单,只需要传给它两个参数rows和total就行,但是之前并不知道它的实现原理,所以学的时候还是挺不容易的。
现在了解了一下它的实现原理,之前的困惑就再也不在了。

首先,来分析一下:

在这里插入图片描述
我要实现的效果如图,在这里并不使用JS、Ajax或框架等工具,就用原生的servlet和jdbc来实现
先看最下面一行的实现:
数据的总条数:
这个简单,用一条sql查询就行了,语句如下:

select count(*) from mytable

(页面容量)每页显示的条数:
这里已经固定为5条

总页数
先判断能否整除,判断值 = 总条数 / 页面容量
若能整除, 总页数 = 总条数 / 页面容量
不能整除,则 总页数 = 总条数 / 页面容量+1

当前页码
开始时默认为1,每次用户向后台发送请求要换页时,前台就会向后台发送一个请求参数relocate,此参数的值为当前页码±1,从而定位到要跳转的页数

跳转:
当我们点击下一页时,jsp页面会向后台发送一个请求参数relocate,值为当前页码+1;
当我们点击下一页时,relocate的值为当前页码-1;
点击首页时,relocate的值为1,即重定位到第一页;
点击尾页时,relocate的值为总页数,即重定位到最后一页
点击刷新,relocate的值为1,重定位到第一页

当前页面中的数据从开始到结束的编号
首先我们要知道当前页面中第一条数据的编号,我们可以这样来判断:
上一页最后一条数据编号 =( 当前页码 - 1)*每页显示条数
然后我们就可以采用sql的分页语句limit来查询

select * from mytable limit 上一页最后一条数据编号 ,页面容量

因为limit语句中的查询开始数据是从第一个参数+1开始的,所以上述语句可以查询到本页中所有数据

现在开始实现

1、数据库的设计

CREATE TABLE `goods` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT ,
  `name` varchar(50) DEFAULT NULL ,
  `created` datetime DEFAULT NULL ,
  `updated` datetime DEFAULT NULL ,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1183 DEFAULT CHARSET=utf8'

一个商品表,主键为id,有属性name、created和updated这三个属性

2、pojo类

    private Long id;
	private String name;
	private Date created;
	private Date updated;

名为Goods,省去getter和setter方法

3、dao层

//水平有限,就不使用接口+代理了,直接类走起
public class pagDao {
    //第一个方法,统计数据总数
	public Integer getCount() throws SQLException {
		Integer all = 0;
		Connection conn = DBUtils.getConnection();
		String sql = "select count(*) from goods";
		PreparedStatement pstmt = null;
		try {
			pstmt = (PreparedStatement) conn.prepareStatement(sql);
			ResultSet rs = pstmt.executeQuery();
			if (rs.next()) {
				all = rs.getInt(1);
			}
			rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			pstmt.close();
			conn.close();
		}
		return all;
	}
    //第二个方法,统计需要查询的数据,需要传入两个参数:上一页最后一条数据的编号和页面容量
    //返回一个List类型的数据,里面存的是需要展示的数据
	public List<Goods> getLimit(Integer startNum,Integer endNum) throws SQLException {
		Connection conn = DBUtils.getConnection();
		String sql = "select * from goods limit ?,?";
		PreparedStatement pstmt = null;
		List<Goods> limit = new ArrayList();
		try {
			pstmt = (PreparedStatement) conn.prepareStatement(sql);
			pstmt.setInt(1, startNum);
			pstmt.setInt(2, endNum);
			ResultSet rs = pstmt.executeQuery();
			while (rs.next()) {
				Goods g = new Goods();
				g.setName(rs.getString("name"));
				g.setId(rs.getLong("id"));
				g.setCreated(rs.getDate("created"));
				g.setUpdated(rs.getDate("updated"));
				limit.add(g);
			}
			rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			pstmt.close();
			conn.close();
		}
		return limit;
	}
}

4、service层

public interface pagService {
    //设置页面容量
	public Integer setCapacity();
	//设置总条数
	public Integer setCount() throws SQLException;
	//设置总页数
	public Integer setWholePage() throws SQLException;
	//设置需要展示的数据
	public List<Goods> setList(Integer startNum,Integer endNum) throws SQLException;
}

5、serviceImpl层

public class pagServiceImpl implements pagService{
	//注入dao对象
	pagDao pagedao = new pagDao();
	//count为总数据,wholePage为总页数,capacity为页面容量
	//startNum和endNum为分页查询参数,startNum为上一页最后一条数据编号,endNum为页面容量
	Integer count,wholePage,startNum,endNum,capacity=5;
	public List<Goods> setList(Integer startNum,Integer endNum) throws SQLException {
		List<Goods> list = pagedao.getLimit(startNum,endNum);
		return list;
	}
	
	public Integer setCount() throws SQLException {
		count = pagedao.getCount();
		return count;
	}
	
	public Integer setCapacity() {
		return capacity;
	}
	
	public Integer setWholePage() throws SQLException {
		count = setCount();
		capacity = setCapacity();
		wholePage = count/capacity;
		int judge = count%capacity;
		if(judge!=0)
			wholePage++;
		return wholePage;
	}	
}

6、controller层

public class PageController extends HttpServlet {

private static final long serialVersionUID = 1L;
//注入service对象
pagService pagservice = new pagServiceImpl();
//List为要展示的数据,pageNow为当前页码
List<Goods> list;
Integer count, wholePage, startNum, pageNow, capacity;

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //获取前台表示跳转的参数
	String relocate = req.getParameter("relocate");
	try {
	    //统计总条数
		count = pagservice.setCount();
		//统计页面容量
		capacity = pagservice.setCapacity();
		//统计总页数
		wholePage = pagservice.setWholePage();
		//若第一次访问页面,则前台来的参数relocate为空
		if (relocate == null) {
		//第一次访问默认当前页码为1
			pageNow = startNum = 1;
		} else {
		//不是第一次访问
			startNum = Integer.parseInt(relocate);
			//若在第一页点击了“上一页”,默认返回本页
			if (startNum == 0)
				startNum = 1;
			//若在最后一页点击了“下一页”,默认返回本页
			if (startNum - 1 == wholePage)
				startNum = wholePage;
		//不是第一次访问,则当前页码为前台传过来的参数relocate,代表当前页码
			pageNow = startNum;
		}
		//查询要展示的数据
		list = pagservice.setList((startNum - 1) * capacity, capacity);
		//设置域对象
		req.setAttribute("LIST", list);
		req.setAttribute("COUNT", count);
		req.setAttribute("PAGENOW", pageNow);
		req.setAttribute("CAPACITY", capacity);
		req.setAttribute("WHOLEPAGE", wholePage);
	} catch (SQLException e) {
		e.printStackTrace();
	}
	//请求重定向
	req.getRequestDispatcher("/index01.jsp").forward(req, resp);
}

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	doGet(req, resp);
}

}

7、jsp页面的设计

<body>
    <table width="500" border="1px" id="idData">
		<tr>
			<td>编号</td>
			<td>名称</td>
			<td>创建时间</td>
			<td>更新时间</td>
		</tr>
		<c:forEach items="${LIST}" var="g">
		<tr>
		    <td>${g.getId()}</td>
			<td>${g.getName()}</td>
			<td>${g.getUpdated()}</td>
			<td>${g.getCreated()}</td>
		</tr>
        </c:forEach>
	</table>
	<br />
	<a href="${request.pageContext.ContextPath}/pagination/controller?relocate=1">首页</a>
	<a href="${request.pageContext.ContextPath}/pagination/controller?relocate=${PAGENOW-1}">上一页</a>
	<a href="${request.pageContext.ContextPath}/pagination/controller?relocate=${PAGENOW+1}">下一页</a>
	<a href="${request.pageContext.ContextPath}/pagination/controller?relocate=${WHOLEPAGE}">尾页</a>
	<a href="${request.pageContext.ContextPath}/pagination/controller?relocate=1">刷新</a>
	</br>
	总共${WHOLEPAGE}页, ${COUNT}条数据&nbsp; &nbsp; &nbsp;&nbsp;
	当前第${PAGENOW}页, 每页显示${CAPACITY}条
</body>

分页首先到这里,下次做个优化,用JS和Ajax来写,我想因该会简单很多

SunnyUI.Net 是基于.Net Framework 4.0+、.Net Core3.1、.Net 5 框架的 C# WinForm 开源控件库、工具类库、扩展类库、多页面开发框架。 源码编译环境:VS2019 16.8+,.Net5,.Net Core3.1 动态库应用环境:VS2010及以上,.Net Framework 4.0及以上(不包括.Net Framework 4 Client Profile),.Net Core 3.1,.Net 5.0 推荐通过Nuget安装:Install-Package SunnyUI,或者通过Nuget搜索SunnyUI安装。 软件介绍: 1、开源控件库 基于.Net Framework4.0,原生控件开发,参考 Element主题风格,包含 按钮、编辑框、下拉框、数据表格、工控仪表、统计图表在内的常用控件超过 50 个,满足常规开发需求,每个控件都精雕细琢,注重细节; 包含 Element 风格主题 11 个,其他主题 6 个,包含主题管理组件 UIStyleManager,可自由切换主题。 2、工具库 收集整理开发过程中经常用到的工具类库。 3、扩展库 收集整理开发过程中经常用到的扩展类库。 4、多页面框架 参考Element,包括7种常用框架风格,只需几行简单的代码即可创建多页面程序,其支撑组件包括UIForm,UIPage,UIFrame,集合常用控件库即可快速开发WinForm应用程序。 SunnyUI.Net开发框架 更新日志: v3.0.2 UIMarkLabel:增加带颜色标签的Label UIRoundProcess:圆形滚动条 UIBreadcrumb:增加面包屑导航 UILedLabel:增加Led标签 UIHeaderButton:在工具箱中显示 UILineChart:支持拖拽选取放大 UIDateTimePicker:修复下拉选择日期后关闭的Bug UINavMenu:增加设置二级菜单底色 UIColorPicker:增加单击事件以选中颜色 UITitlePage:增加ShowTitle可控制是否显示标题 UINavBar:增加可设置背景图片 框架增加IFrame接口,方便页面跳转 UIDataGridView:修改垂直滚动条和原版一致,并增加翻页方式滚动 UIPagination: 修正因两次查询数量相等而引起的不刷新 UIHeaderButton: 增加字体图标背景时鼠标移上背景色 UITabControl:修改第一个TabPage关不掉的Bug UIDataGridView:增加EnterAsTab属性,编辑输入时,用Enter键代替Tab键跳到下一个单元格 UILineChart:增加鼠标框选放大,可多次放大,右键点击恢复一次,双击恢复 UITitlePanel:修复OnMouseMove事件 UITrackBar:增加垂直显示方式 UIFlowLayoutPanel:修改了一处因为其加入控件大小发生变化而引起的滚动条出错。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值