使用Servlet实现分页

64 篇文章 1 订阅
39 篇文章 1 订阅

本次分页功能的实现使用了servlet+jsp+mysql

【搬运自我的博客:创建于2020-06-22 17:29】


一、实现前的准备

1.本次分页我们使用MVC三层架构进行实现


2.项目结构如下


3.c3p0连接池:C3P0Util.java、c3p0-config.xml

数据库连接池工具包-C3P0Util.java

/**
 * @author Zhao Wen
 * @date 2020年6月5日上午10:40:42
 * @filename C3P0Util.java
 * @details C3P0连接池工具包
 */
public class C3P0Util {
	private static ComboPooledDataSource dataSource = new ComboPooledDataSource("zhaowen");
	

	public static ComboPooledDataSource getDataSource(){
		return dataSource;
	}
	
	
	public static Connection getConnection(){
		try {
			return (Connection) dataSource.getConnection();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	public static void release(Connection conn,Statement stmt,ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			rs=null;
		}
		
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			stmt=null;
		}
		
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			conn=null;
		}
	}
	
	
	public static void release(Connection conn,PreparedStatement ps,ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			rs=null;
		}
		
		if(ps!=null){
			try {
				ps.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			ps=null;
		}
		
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			conn=null;
		}
	}
	
	public static void release(Connection conn){
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			conn=null;
		}
	}
}

数据库里连接池配置文件-c3p0-config.xml(需要自行修改jdbcUrluserpassword属性值)

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">
     		jdbc:mysql://localhost:3306/student
     	</property>
		<property name="user">root</property>
		<property name="password">666666</property>
		<property name="checkoutTimeout">30000</property>
		<property name="initialPoolSize">10</property>
		<property name="maxIdleTime">30</property>
		<property name="maxPoolSize">100</property>
		<property name="minPoolSize">10</property>
		<property name="maxStatements">200</property>
	</default-config> 
	<!-- 本次连接使用配置 -->
	<named-config name="zhaowen">
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">
           	jdbc:mysql://localhost:3306/student
        </property>
		<property name="user">root</property>
		<property name="password">666666</property>
		<property name="initialPoolSize">5</property>
		<property name="maxPoolSize">50</property>
	</named-config>
</c3p0-config>

对于数据库连接池有疑问的可以查看我另一篇博客数据库连接池c3p0、dbcp和dbutils工具类的使用



二、后端实现

分页JavaBean:PageBean.java

说明:分页JavaBean,存储分页信息,方便在Web层显示

	private List<T> stuInfoList = new ArrayList<>(); // 每页显示信息List,此处使用泛型可提高代码复用率
	private int currentPage; // 当前浏览页
	private int currentCount; // 当前页显示条数
	private int totalPage; // 总页数
	private int totalCount; // 信息总条数


分页Servlet:PageShowServlet.java

说明:控制器 Servlet层,接收用户请求,调用service层分页功能实现代码获取数据,跳转(转发)页面

		PageShowService stuinfoService = new PageShowService();
		PageBean pageBean = null;
		String cp = request.getParameter("currentPage");
		int currentPage = 1;
		if (cp != null) {
			Integer cpInt = Integer.valueOf(cp);
			if (cpInt != -1) {
				currentPage = cpInt; // 当前浏览页数
			}
		}
		int currentCount = 20; // 每页显示信息数
		try {
			pageBean = stuinfoService.findPageBean(currentPage, currentCount);
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.print("分页信息查找失败");
		}

此处通过前端页面传送的参数CurrentPage,来获知具体请求的页数;再通过调用Service方法中的findPageBean()方法,来获取分页数据。



分页Service:PageShowService.java

说明:给servlet层提供分页查询功能方法调用,调用Dao层数据分页方法查询获取数据

public PageBean findPageBean(int currentPage, int currentCount) throws SQLException {
		PageBean<Userinfo> pageBean = new PageBean<>();
		StuInfoDao stuInfoDaoImpl = new StuInfoDaoImpl();

		pageBean.setCurrentPage(currentPage);
		pageBean.setCurrentCount(currentCount);

		int totalCount = stuInfoDaoImpl.getTotalCount();
		int totalPage = (int) Math.ceil(1.0 * totalCount / currentCount);
		pageBean.setTotalPage(totalPage);

		pageBean.setTotalCount(stuInfoDaoImpl.getTotalCount());

		// 分段获取用户信息
		int index = (currentPage - 1) * currentCount;
		pageBean.setStuInfoList(stuInfoDaoImpl.findStuListForPageBean(index, currentCount));

		return pageBean;
	}
  • 使用PageBean.java中的getter/setter方法,对分页属性进行封装,其中信息列表(stuinfoList)和信息总条数(totalcount),必须要在调用Dao实现类查询;


  • 而信息总页数,需要根据每页显示数(CurrentCount)和信息总数(stuinfoList)来判断,所以此处我们使用公式

总页数(totalPage)=Math.ceil(总条数  /当前显示的条数)【非四舍五入,应前进】

​ 转换为Java代码就是

int totalPage = Math.ceil(totalCount/currentCount)

  • 每次调用分页数据时,为了准确获取到指定数据,我们需要一个值,来在分段查询时作为一个初始值。

    此处我们使用index来表示,而index的计算公式如下:

    index=(当前页数currentPage-1)*每页显示的条数(currentCount)
    

    转换为Java代码就是

    int index = (currentPage - 1) * currentCount;
    
    

    index值会随着当前浏览页数和每一页显示条数限制:

    例如,当每页限制显示4条时,inde值变化情况如下:

页数开始索引每页显示条数
104
244
384
4124


分页Dao:StuInfoDaoImpl.java

说明:给Service层提供分页功能方法,直接接触数据库(一般使用DBUtils封装的工具类操作数据库/一般 作为抽象接口,新建 xxDaoImpl对其进行实现)


获取指定表的记录总数:getTotalCount()

	public int getTotalCount() throws SQLException {
		String sql = "select count(*) from userInfo";
		Long count = new QueryRunner(dataSource).query(sql, new ScalarHandler<>());
		return count.intValue();
	}


获取分页数据列表:findStuListForPageBean(int index,int currentCount)

	public List<Userinfo> findStuListForPageBean(int index, int currentCount) throws SQLException {
		String sql = "select sno,name,age,score from userInfo limit ? , ?";
		List<Userinfo_0134> stuInfoList = new QueryRunner(dataSource).query(sql,
				new BeanListHandler<>(Userinfo), index, currentCount);
		return stuInfoList;
	}

此处使用limit关键字,通过每次调用参数index和currentCount的值,来获取指定区段的数据。


三、前端界面

分页显示页面:page_list.jsp

说明:使用JSTL的c:forEach标签遍历分页数据,在前台进行展示

显示页面

		<!-- 信息展示 -->
		<table border="1">
			<tr>
				<td>学号</td>
				<td>姓名</td>
				<td>年龄</td>
				<td>成绩</td>
			</tr>
			<c:forEach items="${pageBean.stuInfoList}" var="stuinfo">
				<tr>
					<td>${stuinfo.sno}</td>
					<td>${stuinfo.name}</td>
					<td>${stuinfo.age}</td>
					<td>${stuinfo.score}</td>
				</tr>
			</c:forEach>
		</table>
		<p>----------------------------------------------------------------------------</p>

显示分页数据:当前浏览页、总页数、总信息条数

<div>
	<span>当前页:${pageBean.currentPage}/${pageBean.totalPage}</span>
    | 
    <span>总页数:${pageBean.totalPage}</span>
    |
    <span>总信息数:${pageBean.totalCount}</span>
</div>

显示分页页码:页码、前一页、后一页实现

<div>
    <!--首页-->
	<span><a href="${pageContext.request.contextPath}/PageShowServlet_0134?		   currentPage=1">首页</a>
    </span>
    ||
    <!--前一页-->
    <span><a href="${pageContext.request.contextPath}/PageShowServlet?currentPage=${pageBean.currentPage - 1}">上一页</a>
    </span>
    <!--页码-->
	<c:forEach begin="1" end="${pageBean.totalCount/20+1}" var="pageCount">
	|
	<a href="${pageContext.request.contextPath}/PageShowServlet?currentPage=${pageCount}">${pageCount}</a>
	|
     </c:forEach>
    |
    <!--后一页-->
    <span><a href="${pageContext.request.contextPath}/PageShowServlet?currentPage=${pageBean.currentPage + 1}">下一页</a>
    </span>
	|
    <!--尾页-->
    <span><a 
             <fmt:formatNumber var="lastPage" value="${pageBean.totalCount/20+1}" pattern="#" />
			href="${pageContext.request.contextPath}/PageShowServlet?currentPage=${lastPage - 1}">尾页</a>
    </span>
</div>


四、总结

要使用Servlet完成分页,我们首先要定义JavaBean用于数据封装、然后依次编写Dao数据库DDL语句、分页Servlet用于与前端交互,最后再编写前端页面并使用EL表达式接收数据并显示。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单从表现层来说分页不是一个复杂的工作,稍微理一下思路,处于不同competence level的同学应该都能自己搞出来。 以上面的文章列表分页为例,我觉得分页有两点重要的, 一是:分页我们必须首先自己搞清楚,文章总数、每页显示文章数(页大小)、页数 二是:如何做好页脚的分页导航条 实际应用中,文章总数这个值我们从数据库可以得到;每页显示的文章数即分页的页大小可以自己定义;页数我们可以通过下面的个表达式简单得出。 假设: int pageSize = 10; //分页大小 int totalPosts = PagingDAO.entryList.size(); //总文章数 int totalPages = totalPosts/pageSize + ((totalPosts%pageSize)>0?1:0); //计算得出的总页数 每页的文章怎么取出来? 知道分页的大小之后,我们生成了页好的选取下拉框,每次选择第几页的时候,都会向Servlet传递当前选择页号的参数,这样Servlet调用后面的DAO相应的方法,取得文章列表信息,再回传到JSP以供显示。 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> page Size : ${pageSize} <br /> Total Posts: ${totalPosts} <br /> Total Pages: ${totalPages} <br /> Current Page: ${pageNumber} <hr /> <table> <thead> <tr align="center"> <td width="10%">Article ID</td> <td width="70%">Article Title</td> <td colspan="3">Actions</td> </tr> </thead> <tbody> <c:forEach items="${entryList}" var="entry"> <tr align="center"> <td>${entry.entryID}</td> <td>${entry.title}</td> <td><a href="viewEntry?entryID=${entry.entryID}">View</a></td> <td><a href="editEntry?entryID=${entry.entryID}">Edit</a></td> <td><a href="deleteEntry?entryID=${entry.entryID}">Delete</a></td> </tr> </c:forEach> </tbody> <tfoot> <tr align="center"> <td colspan="5"> <jsp:include page="paging_footer.jsp"></jsp:include> </td> </tr> </tfoot> </table> <hr/>
好的,下面是使用layui和servlet实现分页的步骤: 1. 在前端页面引入layui的css和js文件,并添加一个div作为分页的容器: ``` <link rel="stylesheet" href="layui/css/layui.css"> <script src="layui/layui.js"></script> <div id="page"></div> ``` 2. 在servlet中获取需要分页的数据,并将其封装为一个json对象返回给前端页面: ``` protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int page = Integer.parseInt(request.getParameter("page")); // 获取当前页码 int limit = Integer.parseInt(request.getParameter("limit")); // 获取每页显示的记录数 // 根据页码和记录数从数据库中获取数据 List<User> userList = userService.getUserListByPage(page, limit); // 将数据封装为json对象返回给前端页面 JSONObject result = new JSONObject(); result.put("code", 0); result.put("msg", ""); result.put("count", userService.getUserCount()); result.put("data", userList); response.getWriter().write(result.toJSONString()); } ``` 3. 在前端页面使用layui的table组件展示数据,并添加分页功能: ``` <script> layui.use(['table', 'laypage'], function(){ var table = layui.table; var laypage = layui.laypage; table.render({ elem: '#table', url: 'userList', // 获取数据的servlet的url page: true, // 开启分页 cols: [[ {field:'id', title:'ID'}, {field:'name', title:'用户名'}, {field:'age', title:'年龄'} ]] }); laypage.render({ elem: 'page', limit: 10, // 每页显示的记录数 layout: ['prev', 'page', 'next', 'skip'], jump: function(obj, first){ if(!first){ // 点击页码时重新加载表格数据 table.reload('table', { where: { page: obj.curr, limit: obj.limit } }); } } }); }); </script> ``` 这样就完成了使用layui和servlet实现分页的过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值