how2j.cn


工具版本兼容问题
分页单独拿出来讲解



12分8秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器

步骤 1 : 效果   
步骤 2 : Page.java   
步骤 3 : 获取分页参数   
步骤 4 : 基于分页参数,获取数据   
步骤 5 : 为page对象设置总数   
步骤 6 : 为了便于理解,先来一个简化了的adminPage.jsp   
步骤 7 : 完整版的adminPage.jsp   

默认是每页显示5条数据,所以先增加几条数据,以观察分页效果
效果
Page这个类专门为分页提供必要信息
属性:
int start; 开始位置
int count; 每页显示的数量
int total; 总共有多少条数据
String param; 参数(这个属性在后续有用到,但是分类的分页查询里并没有用到,请忽略)

方法:
getTotalPage 根据 每页显示的数量count以及总共有多少条数据total,计算出总共有多少页
getLast 计算出最后一页的数值是多少
isHasPreviouse 判断是否有前一页
isHasNext 判断是否有后一页
package tmall.util; public class Page { int start; int count; int total; String param; 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 Page(int start, int count) { super(); this.start = start; this.count = count; } public boolean isHasPreviouse(){ if(start==0) return false; return true; } public boolean isHasNext(){ if(start==getLast()) return false; return true; } 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; } 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; } 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; } }
步骤 3 :

获取分页参数

edit
增值内容,请先登录
完整的J2EE模仿天猫项目,使用J2SE、前端技术(包含所有前端jsp文件)、J2EE一整套技术栈, 从无到有涵盖全部147个知识点,475个开发步骤, 充实J2EE项目经验,为简历加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢
package tmall.servlet; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import tmall.dao.CategoryDAO; import tmall.dao.OrderDAO; import tmall.dao.OrderItemDAO; import tmall.dao.ProductDAO; import tmall.dao.ProductImageDAO; import tmall.dao.PropertyDAO; import tmall.dao.PropertyValueDAO; import tmall.dao.ReviewDAO; import tmall.dao.UserDAO; import tmall.util.Page; public abstract class BaseBackServlet extends HttpServlet { public abstract String add(HttpServletRequest request, HttpServletResponse response, Page page) ; public abstract String delete(HttpServletRequest request, HttpServletResponse response, Page page) ; public abstract String edit(HttpServletRequest request, HttpServletResponse response, Page page) ; public abstract String update(HttpServletRequest request, HttpServletResponse response, Page page) ; public abstract String list(HttpServletRequest request, HttpServletResponse response, Page page) ; protected CategoryDAO categoryDAO = new CategoryDAO(); protected OrderDAO orderDAO = new OrderDAO(); protected OrderItemDAO orderItemDAO = new OrderItemDAO(); protected ProductDAO productDAO = new ProductDAO(); protected ProductImageDAO productImageDAO = new ProductImageDAO(); protected PropertyDAO propertyDAO = new PropertyDAO(); protected PropertyValueDAO propertyValueDAO = new PropertyValueDAO(); protected ReviewDAO reviewDAO = new ReviewDAO(); protected UserDAO userDAO = new UserDAO(); public void service(HttpServletRequest request, HttpServletResponse response) { try { /*获取分页信息*/ int start= 0; int count = 5; try { start = Integer.parseInt(request.getParameter("page.start")); } catch (Exception e) { } try { count = Integer.parseInt(request.getParameter("page.count")); } catch (Exception e) { } Page page = new Page(start,count); /*借助反射,调用对应的方法*/ String method = (String) request.getAttribute("method"); Method m = this.getClass().getMethod(method, javax.servlet.http.HttpServletRequest.class, javax.servlet.http.HttpServletResponse.class,Page.class); String redirect = m.invoke(this,request, response,page).toString(); /*根据方法的返回值,进行相应的客户端跳转,服务端跳转,或者仅仅是输出字符串*/ if(redirect.startsWith("@")) response.sendRedirect(redirect.substring(1)); else if(redirect.startsWith("%")) response.getWriter().print(redirect.substring(1)); else request.getRequestDispatcher(redirect).forward(request, response); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); throw new RuntimeException(e); } } public InputStream parseUpload(HttpServletRequest request, Map<String, String> params) { InputStream is =null; try { DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); // 设置上传文件的大小限制为10M factory.setSizeThreshold(1024 * 10240); List items = upload.parseRequest(request); Iterator iter = items.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (!item.isFormField()) { // item.getInputStream() 获取上传文件的输入流 is = item.getInputStream(); } else { String paramName = item.getFieldName(); String paramValue = item.getString(); paramValue = new String(paramValue.getBytes("ISO-8859-1"), "UTF-8"); params.put(paramName, paramValue); } } } catch (Exception e) { e.printStackTrace(); } return is; } }
步骤 4 :

基于分页参数,获取数据

edit
增值内容,请先登录
完整的J2EE模仿天猫项目,使用J2SE、前端技术(包含所有前端jsp文件)、J2EE一整套技术栈, 从无到有涵盖全部147个知识点,475个开发步骤, 充实J2EE项目经验,为简历加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢
步骤 5 :

为page对象设置总数

edit
增值内容,请先登录
完整的J2EE模仿天猫项目,使用J2SE、前端技术(包含所有前端jsp文件)、J2EE一整套技术栈, 从无到有涵盖全部147个知识点,475个开发步骤, 充实J2EE项目经验,为简历加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢
步骤 6 :

为了便于理解,先来一个简化了的adminPage.jsp

edit
增值内容,请先登录
完整的J2EE模仿天猫项目,使用J2SE、前端技术(包含所有前端jsp文件)、J2EE一整套技术栈, 从无到有涵盖全部147个知识点,475个开发步骤, 充实J2EE项目经验,为简历加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%> <script> $(function(){ $("ul.pagination li.disabled a").click(function(){ return false; }); }); </script> <nav> <ul class="pagination"> <li> <a href="?page.start=0" aria-label="Previous" > <span aria-hidden="true">«</span> </a> </li> <li > <a href="?page.start=${page.start-page.count}" aria-label="Previous" > <span aria-hidden="true">‹</span> </a> </li> <c:forEach begin="0" end="${page.totalPage-1}" varStatus="status"> <li> <a href="?page.start=${status.index*page.count}" class="current">${status.count}</a> </li> </c:forEach> <li > <a href="?page.start=${page.start+page.count}" aria-label="Next"> <span aria-hidden="true">›</span> </a> </li> <li > <a href="?page.start=${page.last}" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav>
步骤 7 :

完整版的adminPage.jsp

edit
简化的adminPage.jsp 用于帮助大家理解,其存在的问题是,即便是没有下一页的数据了,下一页超链也可以点击,点出来的页面是空白的。(首页,上一页,下一页和最后一页都存在这个问题)

那么所谓的完整版的adminPage.jsp,就是对这些边界进行了处理。当没有下一页的时候,对应超链处于不可点击状态。

比如首页:
当page.hasPreviouse为false的时候,为首页连接套用Bootstrap样式 disabled

<li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>>
<a href="?page.start=0${page.param}" aria-label="Previous" >
<span aria-hidden="true">&laquo;</span>
</a>
</li>

注: hasPreviouse会的导致isHasPreviouse()方法被调用,请参考EL表达式获取JavaBean的属性
完整版的adminPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%> <script> $(function(){ $("ul.pagination li.disabled a").click(function(){ return false; }); }); </script> <nav> <ul class="pagination"> <li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>> <a href="?page.start=0${page.param}" aria-label="Previous" > <span aria-hidden="true">«</span> </a> </li> <li <c:if test="${!page.hasPreviouse}">class="disabled"</c:if>> <a href="?page.start=${page.start-page.count}${page.param}" aria-label="Previous" > <span aria-hidden="true">‹</span> </a> </li> <c:forEach begin="0" end="${page.totalPage-1}" varStatus="status"> <c:if test="${status.count*page.count-page.start<=20 && status.count*page.count-page.start>=-10}"> <li <c:if test="${status.index*page.count==page.start}">class="disabled"</c:if>> <a href="?page.start=${status.index*page.count}${page.param}" <c:if test="${status.index*page.count==page.start}">class="current"</c:if> >${status.count}</a> </li> </c:if> </c:forEach> <li <c:if test="${!page.hasNext}">class="disabled"</c:if>> <a href="?page.start=${page.start+page.count}${page.param}" aria-label="Next"> <span aria-hidden="true">›</span> </a> </li> <li <c:if test="${!page.hasNext}">class="disabled"</c:if>> <a href="?page.start=${page.last}${page.param}" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav>


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


问答区域    
2021-04-13 分页的一点理解
VOID1




<c:forEach begin="0" end="${page. totalPage()-1}" varStatus="status"> <%-- 两边同时除以5可看作 -2 =< count(基于1)- start(当前页基于0) <=4--%> <c:if test="${status.count*page.count-page.start<=20 && status.count*page.count-page.start>=-10}"> <%-- 当前索引*一页产品的数量 与开始的位置作比较,相等则为本页不可点击--%> <li <c:if test="${status.index*page.count==page.start}">class="disabled"</c:if>> <a href="?page.start=${status.index*page.count}${page.param}" <%-- 当前索引*一页产品的数量 与开始的位置作比较,相等则为本页加粗--%> <c:if test="${status.index*page.count==page.start}">class="current"</c:if>> <%-- 输出是第几页,count:从1开始计数--%> ${status.count}
        <c:forEach begin="0" end="${page. totalPage()-1}" varStatus="status">
<%--                            两边同时除以5可看作   -2 =< count(基于1)- start(当前页基于0) <=4--%>
            <c:if test="${status.count*page.count-page.start<=20 && status.count*page.count-page.start>=-10}">
<%--                            当前索引*一页产品的数量 与开始的位置作比较,相等则为本页不可点击--%>                
                <li <c:if test="${status.index*page.count==page.start}">class="disabled"</c:if>>
                    <a href="?page.start=${status.index*page.count}${page.param}" 
<%--                            当前索引*一页产品的数量 与开始的位置作比较,相等则为本页加粗--%>
                       <c:if test="${status.index*page.count==page.start}">class="current"</c:if>>
<%--                            输出是第几页,count:从1开始计数--%>
                                ${status.count}
                    </a>
                </li>
            </c:if>
        </c:forEach>

							


2 个答案

Pipi_pika
答案时间:2021-09-17
status.count*page.count 某个链接(页码)的start值 page.start 当前页的start值 status.count*page.count == page.start 表示该链接为当前页页码 status.count*page.count - page.start <=20 表示该链接和当前页码间隔20/5=4页

VOID1
答案时间:2021-04-13
totalPage多个个括号,被我看到了。。。



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2020-02-28 a标签的超链为什么?开头
JacobNie98




a标签的超链直接问号开头什么意思
<a href="?page.start=${page.start+page.count}${page.param}" aria-label="Next">

							


1 个答案

how2j
答案时间:2020-02-29
表示 问号后面跟的都是参数。



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2020-02-13 获取分页参数
2020-02-04 请问Page对象是怎么获取的呢?
2019-12-19 中间页的 status.count*page.count-page.start>=-10 是判断什么的


提问太多,页面渲染太慢,为了加快渲染速度,本页最多只显示几条提问。还有 44 条以前的提问,请 点击查看

提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 实践项目-天猫整站J2EE-分页 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图