ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
分页单独拿出来讲解 ## 步骤 1 : 效果 如图所示,每页显示5条数据。 注: 没有分类图片是正常的,在接下来的知识点就会做增加图片功能了 ![](https://box.kancloud.cn/8ac4d1288627df3e2e0d2c25c4b4ba9f_1892x432.png) ## 步骤 2 : Page.java 新增Page这个类专门为分页提供必要信息 属性: int start; 开始位置 int count; 每页显示的数量 int total; 总共有多少条数据 String param; 参数(这个属性在后续有用到,但是分类的分页查询里并没有用到,请忽略) 方法: getTotalPage 根据 每页显示的数量count以及总共有多少条数据total,计算出总共有多少页 getLast 计算出最后一页的数值是多少 isHasPreviouse 判断是否有前一页 isHasNext 判断是否有后一页 ~~~ package com.dodoke.tmall.util; /** * 分页类 * @author cui * */ public class Page { /** * 开始页数 */ private int start; /** * 每页显示个数 */ private int count; /** * 总个数 */ private int total; /** * 参数 */ private String param; /** * 默认每页显示5条 */ private static final int defaultCount = 5; public Page() { count = defaultCount; } public Page(int start, int count) { this(); this.start = start; this.count = count; } public int getStart() { return start; } public void setStart(int start) { this.start = start; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public String getParam() { return param; } public void setParam(String param) { this.param = param; } /** * 判断是否有前一页 * @return boolean */ public boolean isHasPreviouse() { if (start == 0) { return false; } return true; } /** * 判断是否有后一页 * @return boolean */ public boolean isHasNext() { if (start == getLast()){ return false; } return true; } /** * 计算出最后一页的数值是多少 * @return int */ public int getLast() { int last; // 假设总数是50,是能够被5整除的,那么最后一页的开始就是45 if (0 == total % count) last = total - count; // 假设总数是51,不能够被5整除的,那么最后一页的开始就是50 else last = total - total % count; last = last < 0 ? 0 : last; return last; } /** * 根据 每页显示的数量count以及总共有多少条数据total,计算出总共有多少页 * @return int */ public int getTotalPage() { int totalPage; // 假设总数是50,是能够被5整除的,那么就有10页 if (0 == total % count) { totalPage = total / count; } // 假设总数是51,不能够被5整除的,那么就有11页 else { totalPage = total / count + 1; } if (0 == totalPage) { totalPage = 1; } return totalPage; } @Override public String toString() { return "Page [start=" + start + ", count=" + count + ", total=" + total + ", getStart()=" + getStart() + ", getCount()=" + getCount() + ", isHasPreviouse()=" + isHasPreviouse() + ", isHasNext()=" + isHasNext() + ", getTotalPage()=" + getTotalPage() + ", getLast()=" + getLast() + "]"; } } ~~~ ## 步骤 3 : CategoryMapper.xml 修改CategoryMapper.xml,以提供带分页的查询语句和获取总数的sql语句 ~~~ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dodoke.tmall.mapper.CategoryMapper"> <select id="list" resultType="Category"> select * from t_category order by id desc <if test="start!=null and count!=null"> limit #{start},#{count} </if> </select> <select id="total" resultType="int"> select count(*) from t_category </select> </mapper> ~~~ ## 步骤 4 : CategoryMapper 修改CategoryMapper,提供一个支持分页的查询方法list(Page page)和获取总数的方法total ~~~ package com.dodoke.tmall.mapper; import java.util.List; import com.dodoke.tmall.pojo.Category; import com.dodoke.tmall.util.Page; public interface CategoryMapper { List<Category> list(Page page); public int total(); } ~~~ ## 步骤 5 : CategoryService 修改CategoryService,提供一个支持分页的查询方法list(Page page)和获取总数的方法total ~~~ package com.dodoke.tmall.service; import java.util.List; import com.dodoke.tmall.pojo.Category; import com.dodoke.tmall.util.Page; public interface CategoryService { List<Category> list(Page page); int total(); } ~~~ ## 步骤 6 : CategoryServiceImpl 修改CategoryServiceImpl,提供一个支持分页的查询方法list(Page page)和获取总数的方法total。 ~~~ package com.dodoke.tmall.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.dodoke.tmall.mapper.CategoryMapper; import com.dodoke.tmall.pojo.Category; import com.dodoke.tmall.service.CategoryService; import com.dodoke.tmall.util.Page; @Service public class CategoryServiceImpl implements CategoryService { @Autowired CategoryMapper categoryMapper; @Override public List<Category> list(Page page) { return categoryMapper.list(page); } @Override public int total() { return categoryMapper.total(); } } ~~~ ## 步骤 7 : CategoryController 修改CategoryController 1. 为方法list增加参数Page,用于获取浏览器传递过来的分页信息 2. categoryService.list(page); 获取当前页的分类集合 3. 通过categoryService.total(); 获取分类总数 4. 通过page.setTotal(total); 为分页对象设置总数 5. 把分类集合放在"cs"中 6. 把分页对象放在 "page“ 中 7. 跳转到listCategory.jsp页面 ~~~ package com.dodoke.tmall.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import com.dodoke.tmall.pojo.Category; import com.dodoke.tmall.service.CategoryService; import com.dodoke.tmall.util.Page; @RequestMapping("") @Controller public class CategoryController { @Autowired CategoryService categoryService; @RequestMapping("admin_category_list") public String list(Model model,Page page) { List<Category> cs = categoryService.list(page); int total = categoryService.total(); page.setTotal(total); model.addAttribute("cs", cs); model.addAttribute("page",page); return "admin/listCategory"; } } ~~~ > 1. start会被自动封装到page里的 > 2. page 对象 最开始访问方法list(Model model,Page page)时 ,实际上page就是相当于你new page()的默认值,参数如下: private int start; //开始页数 private int count; //每页显示个数 private int total; //总个数 private String param; //参数 private static final int defaultCount = 5; //默认每页显示5条 相当于最开始时 start =0;count=5;total =0;param=null; 所以第一次查询就查的是0至5的数据,后面通过前台页面点击在此过来start 就会再次改变 ## listCategory.jsp 本来注释掉的43行,去掉注释,即 `<%@include file="../include/admin/adminPage.jsp" %>` ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@include file="../include/admin/adminHeader.jsp"%> <%@include file="../include/admin/adminNavigator.jsp"%> <title>分类管理</title> <div class="workingArea"> <h1 class="label label-info" >分类管理</h1> <br> <br> <div class="listDataTableDiv"> <table class="table table-striped table-bordered table-hover table-condensed"> <thead> <tr class="success"> <th>ID</th> <th>图片</th> <th>分类名称</th> <th>属性管理</th> <th>产品管理</th> <th>编辑</th> <th>删除</th> </tr> </thead> <tbody> <c:forEach items="${cs}" var="c"> <tr> <td>${c.id}</td> <td><img height="40px" src="img/category/${c.id}.jpg"></td> <td>${c.name}</td> <td><a href="admin_property_list?cid=${c.id}"><span class="glyphicon glyphicon-th-list"></span></a></td> <td><a href="admin_product_list?cid=${c.id}"><span class="glyphicon glyphicon-shopping-cart"></span></a></td> <td><a href="admin_category_edit?id=${c.id}"><span class="glyphicon glyphicon-edit"></span></a></td> <td><a deleteLink="true" href="admin_category_delete?id=${c.id}"><span class=" glyphicon glyphicon-trash"></span></a></td> </tr> </c:forEach> </tbody> </table> </div> <div class="pageDiv"> <%@include file="../include/admin/adminPage.jsp" %> </div> <div class="panel panel-warning addDiv"> <div class="panel-heading">新增分类</div> <div class="panel-body"> <form method="post" id="addForm" action="admin_category_add" enctype="multipart/form-data"> <table class="addTable"> <tr> <td>分类名称</td> <td><input id="name" name="name" type="text" class="form-control"></td> </tr> <tr> <td>分类图片</td> <td> <input id="categoryPic" accept="image/*" type="file" name="image" /> </td> </tr> <tr class="submitTR"> <td colspan="2" align="center"> <button type="submit" class="btn btn-success">提 交</button> </td> </tr> </table> </form> </div> </div> </div> <%@include file="../include/admin/adminFooter.jsp"%> <script> $(function(){ $("#addForm").submit(function(){ if(!checkEmpty("name","分类名称")) return false; if(!checkEmpty("categoryPic","分类图片")) return false; return true; }); }); </script> ~~~ ## 步骤 9 : 为了便于理解,先来一个简化了的adminPage.jsp 在listCategory.jsp页面包含了分页专用jsp:adminPage.jsp 在其中,依据page对象,进行分页超链元素的显示 **完整版的adminPage.jsp** 比较复杂,为了便于大家理解,我先把完整版的adminPage.jsp简化一下 首先,分页超链的效果,用的**Bootstrap的分页**效果来制作 首页超链: ~~~ <li> <a href="?start=0" aria-label="Previous" > <span aria-hidden="true">«</span> </a> </li> ~~~ 上一页超链: ~~~ <li > <a href="?start=${page.start-page.count}" aria-label="Previous" > <span aria-hidden="true">‹</span> </a> </li> ~~~ 下一页超链: ~~~ <li > <a href="?start=${page.start+page.count}" aria-label="Next"> <span aria-hidden="true">›</span> </a> </li> ~~~ 最后一页 ~~~ <li > <a href="?start=${page.last}" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> ~~~ 中间页 ~~~ <c:forEach begin="0" end="${page.totalPage-1}" varStatus="status"> <li> <a href="?start=${status.index*page.count}" class="current">${status.count}</a> </li> </c:forEach> ~~~ > 直接写问号就会导致再度访问当前页面。 所以这样写就可以在不同的页面都适用,即分类管理分页也可以用,产品管理分页也可以用 ## 步骤 10 : 完整版的adminPage.jsp 简化的adminPage.jsp 用于帮助大家理解,其存在的问题是,即便是没有下一页的数据了,下一页超链也可以点击,点出来的页面是空白的。(首页,上一页,下一页和最后一页都存在这个问题) 那么所谓的完整版的adminPage.jsp,就是对这些边界进行了处理。当没有下一页的时候,对应超链处于不可点击状态。 比如首页: 当page.hasPreviouse为false的时候,为首页连接套用Bootstrap样式 disabled ~~~ <li> <a href="?start=0${page.param}" <c:if test="${!page.hasPreviouse}">class="btn disabled"</c:if> > <span aria-hidden="true">&laquo;</span> </a> </li> ~~~ > 注: hasPreviouse会的导致isHasPreviouse()方法被调用,即如果属性是boolean类型,那么就会自动调用isXXX方法了 ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <nav> <ul class="pagination"> <li> <a href="?start=0${page.param}" <c:if test="${!page.hasPreviouse}">class="btn disabled"</c:if> > <span aria-hidden="true">&laquo;</span> </a> </li> <li> <a href="?start=${page.start-page.count}${page.param}" <c:if test="${!page.hasPreviouse}">class="btn disabled"</c:if>> <span aria-hidden="true">&lsaquo;</span> </a> </li> <c:forEach begin="0" end="${page.totalPage-1}" varStatus="status"> <li > <a href="?start=${status.index*page.count}${page.param}" <c:if test="${status.index*page.count==page.start}">class="btn disabled current "</c:if> >${status.count}</a> </li> </c:forEach> <li > <a href="?start=${page.start+page.count}${page.param}" <c:if test="${!page.hasNext}">class="btn disabled"</c:if>> <span aria-hidden="true">&rsaquo;</span> </a> </li> <li > <a href="?start=${page.last}${page.param}" <c:if test="${!page.hasNext}">class="btn disabled"</c:if>> <span aria-hidden="true">&raquo;</span> </a> </li> </ul> </nav> <script> $(function(){ $("ul.pagination li.disabled a").click(function(){ return false; }); }); </script> ~~~ ## 步骤 11 : 自己做一遍 拿到本章节对应tmall_ssm.rar, 在其基础之上,按照当前的步骤,自己做一遍,把效果做出来,理解和消化各个步骤的内容,转化为自己的技能。