实现场景:首页中的商品展示列表
实现效果:
分页操作基本是大部分网站都实现的一个功能
实现它的原因:我们在进行查询操作的时候,如果数据库中数据过多时,我们可能并不需要将所有的数据都展示到页面中,而且这样做会导致 页面信息过多,很多噪音数据会影响用户体验,并且一次性查询过多数据服务器也会承受很多压力。因此我们需要实现分页功能。
分析分页功能过程:
第一步:我们应该在传入后台查询数据的时候需要先计算一共要分为多少页(总页数)
第二步:我们需要根据总行数和设定的每页应该显示的行数来计算总体需要分的页数
第三步:我们需要通过前端页面获取到当前页
总页数的计算:通过查询数据库总数据的行数/一页需要分多少数据。
但是要注意如果无法取模等于0,总页数需要+1;
第四步:控制前端界面传入需要查询的数值到查servlet询界面,servlet调用service层查询指定页数的数据。
具体实现代码:
jsp层:
<center><h3 align="center">用户信息管理</h3><table border='2' align='center'><tr><td> 商品编号 </td><td> 商品名称 </td><td> 生产日期 </td><td> 生产厂家 </td><td> 操作 </td><td><a href='/myWeb/addProduct.jsp'>添加商品</a></td></tr><c:forEach items="${requestScope.products}" var="p"><tr><td> ${p.pid} </td><td> ${p.pname} </td><td> ${p.pdate}</td><td> ${p.pfactory} </td><td><a href='/myWeb/product?action=delete&pid=${p.pid}'>删除商品</a></td><td><a href='/myWeb/product?action=select&pid=${p.pid}'>查看详情</a></td></tr></c:forEach></table><div class="page"><%-- 当前页减1 --%>当前是第${pageNows},总页数为${pages}<br><a href="show?pn=${pageNows-1}"><</a><c:forEach begin="1" end="${pages}" var="i"><a href="/myWeb/show?pn=${i}">${i}</a></c:forEach><a href="show?pn=${pageNows+1}">></a></div><a href='/myWeb/loginServlet?action=logout'>退出登录</a></center>
servlet层:
@WebServlet("/show")public class ShowServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ProductDao productDao=new ProductDaoImpl();// 获取到的当前页String pn = req.getParameter("pn");// 当前页int pageNow ;// 每页的行数int pageCount=3;// 总行数int pageRows;// 判断当前页是否为nullpageNow=pn==null?0:Integer.valueOf(pn);// 判断当前页页数是否小于 0if (pageNow <=0){pageNow=1;}System.out.println("------------当前页--------------");System.out.println(pageNow);System.out.println("------------当前页--------------");pageRows = productDao.selectCount();// 总页数(总行数/每页的行数)int pages=pageRows%pageCount==1?pageRows/pageCount:pageRows/pageCount+1;if (pageNow>=pages){pageNow=pages;}System.out.println("----------总页数----------------");System.out.println(pages);System.out.println("--------------------------");req.setAttribute("pages",pages);List<Product> products = productDao.selectAllProduct(pageNow,pageCount);// 查询到的所有商品req.setAttribute("products",products);// 当前页req.setAttribute("pageNows",pageNow);req.getRequestDispatcher("main.jsp").forward(req,resp);}}
dao层
/** @Author liu-miss* @Description 查询所有商品信息* @Date 19:44 2021/7/12* @Param []* @return java.util.List<com.luzhikun.myshopping.domaim.Product>**/@Overridepublic List<Product> selectAllProduct(int pageNow,int pageCount) {DBCPUtil dbcpUtil=new DBCPUtil();String sql = "select * from product limit ?,?";List<Product> query = dbcpUtil.query(sql, Product.class, pageNow,pageCount);return query;}
封装的util查询方法
public <T> List<T> query(String sql,Class<T> c,Object...params){Connection connection=null;PreparedStatement pst=null;ResultSet rs=null;List<T> list=new ArrayList<>();try {connection=getConnection();pst = connection.prepareStatement(sql);if (params!=null && params.length>0){for (int i = 0; i < params.length; i++) {pst.setObject(i+1,params[i]);}}rs = pst.executeQuery();// 通过反射封装结果集// 获取列数ResultSetMetaData metaData = rs.getMetaData();int columnCount = metaData.getColumnCount();System.out.println("列数====="+columnCount);while (rs.next()){try {// 创建泛型对象T t = c.getConstructor().newInstance();for (int i = 0; i < columnCount ; i++) {String columnName = metaData.getColumnLabel(i+1);System.out.println("columnName"+columnName);String methodName = "set" + columnName.substring(0,1).toUpperCase()+ columnName.substring(1);System.out.println("methodName"+methodName);Method method = c.getMethod(methodName,String.class);System.out.println("method"+method);method.invoke(t,rs.getObject(columnName));}list.add(t);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}}} catch (SQLException throwables) {throwables.printStackTrace();}return list;}
这些都完成后,还有一些小细节问题:
添加上一页下一页功能,实现方式有两种:一种是服务端实现,一种是客户端实现
服务端实现:
在servlet中:获取到前端页面的前一页和下一页传来的参数信息,并且判断当前页是否比第一页的数值还小,是否比最大页数还大,如果是 就给默认值
// 总页数(总行数/每页的行数)int pages=pageRows%pageCount==1?pageRows/pageCount:pageRows/pageCount+1;// 判断当前页页数是否小于 0if (pageNow <=0){pageNow=1;}if (pageNow>=pages){pageNow=pages;}
客户端实现:
使用JSTL标签库中的if标签判断当前页的值是否小于等于或者大于等于最小页或最大页时,让前一页或者后一页的连接失效就可以了。
当前是第${pageNows},总页数为${pages}<br><%-- 当前页减1 --%><c:if test="${pageNows}<=1"><</c:if><c:if test="${pageNows > 1 }"><a href="show?pn=${pageNows-1}"><</a></c:if><c:forEach begin="1" end="${pages}" var="i"><a href="/myWeb/show?pn=${i}">${i}</a></c:forEach><c:if test="${pageNows >= pages}">></c:if><c:if test="${pageNows < pages}"><a href="show?pn=${pageNows+1}">></a></c:if>
