分页问题学习及一些小结
1.首先我们想象一下我们的分页页面中有哪些内容
然后我们知道查询分页数sql 语句是:
Select * frombs_book limit index, pageSize
所以加一个字段 index
这样我们就分析出来Page<T>类(泛型 是因为我们以后可能还要对别的不仅是图书分页)
class Page<T>
//页码
//这个我们可以从前台获取回来
pageNumber
//我们也可以通过前台设置 或者我们在Servlet中设置其大小 也就是每页显示的条数
pageSize
//查询要用到的下标
index //这个我们是通过计算得到的 index = (pageNumber-1)* pageSize
//总的记录数
totalRecord //我们通过数据库 便可以查询的到
//总的页数我们也可以通过计算得到
totalPage //(totalRecord -1 ) / pageSize + 1
//查询到的数据列表
List<T> data;//通过数据库sql = Select * from bs_book limit index, pageSize
2.我们利用创建好的page类就可以封装对象啦
a.首先我们拿到的page 对象 他的pageSize 和 pageNumber 是有的
所以接下来 我们应该设计BookDao 增加一个 查询分页图书的方法
Page<Book>findPage(page<Book> page);
b.我们在其实现类中 实现其方法
Page<Book>findPage(page<Book> page){
//首先我们可以通过数据库查询到page对象中总记录数
String sql = “select count(*) from bs_book ”
//调用baseDao中的getSingleValue()注意这查询出来的是long 类型的我们必须得强转
long total Rcord = (long)this.getSingleValue(sql);
//设置这个totalRecord到page中
page.setTotalRecord((int) total Rcord);
//获取index
Int index = page.getIndex();
然后我们就可以查询数据库了
sql = selet title … from bs_book limit ?,?;
List<Book> list = this.getBeanList(sql,index,page,getPageSize());
//然后将查询到的list放进page中
page.setData(list);
return page;
}
c.接下来我们可以完成我们的Service方法了
在BookService接口 新增添一个方法
Page<Book>findPage(String pageNumber, int pageSize);
那么我们就在实现类中实现这个方法
Page<Book>findPage(String pageNumber, int pageSize){
//我们得对这个pageNumber进行强转 , 但我们需要得考虑 万一强转失败之后的一些问题
所以我们先默认一个值为1
int pn = 1;
try{
pn =Integer.parseInt(pageNumber);
}catch(){}
然后创建page对象
Page<Book> page = newPage<Book>();
page.setPageNumber(pn);
page.setPageSize(pageSize);
//然后调用BookDao中的findPage()方法 获取到完整的page对象
return page;
}
d.接下来我们就可以完成我们bookManagerServlet了
新添加一个方法findPage(request,response);
findPage(){
//首先我们可以获取 页面来的信息
String pageNumber = request.getParamer(“pageNumber”);
Int pageSize = 4;
然后调用Service方法 获取page对象
Page<Book> page = bookService.findPage(pageNumber.pageSize);
那我们就可以将我们得到的page对象放进域中啦
request.setAttribute(“page”,page);
//然后转发到指定页面
Request.getRequestDispatcher(…).forward(request,response);
}
e.到了最麻烦的一步啦: 就是在页面中操作
首先我们可以从域中获取到page对象
那么我们便可以通过这个page获取到pageNumber和 pageTotalNumber totalPage 及要遍历的data数据
分页的显示首页
首页:
<a href=”manger/BookManagerServlet?method=findPage&pageNumber=1”>首页</a>
当我们看到这个的时候 会发现 其实这个地址我们是可以解析出来的
于是 我们 可以给page<T> 再设置一个属性path 用来保存除了&pageNumber前面的内容
那现在问题来了 这个path 我们要怎么获取呢?
我们观察报文 发现 其实很简单 就可以获取回来
当我们的地址栏是:
http://localhost:8080/BookStoreOfPage/manager/BookManagerServlet?method=findPage&pageNumber=2
请求来源
请求参数
通过这个我们就可以拼接出这个完成的地址
通过调用request.getRequestURI()//获取manger/BookManagerServlet
通过调用request.getQueryString()//获取请求参数method=findPage&pageNumber=1
但考虑到我们的页面的pageNumber需要当时获取也就是说自己选择所以 我们在设置path的时候 需要把&pageNumber给截取掉
但第一次请求的时候 pageNumber可能为空所以我们应该先判断一下是不是为空在截取 (我就是因为没判断这个搞了好几个小时,一夜未睡呀!)
具体操作:
String requestURI =request.getRequestURI();
String queryString =request.getQueryString();
if(queryString.contains("&pageNumber")){
queryString=queryString.substring(0,queryString.indexOf("&pageNumber"));
}
path = requestURI + ? + queryString;
return path;
那我们通过这个得到的path(记得是在Servlet中设置啊) 也设置进 page中
这样接下来我们在通过获取域中的page 可以操作pageNumber 和pageTotalNumber totalPage 及要遍历的data数据 当然加入path
<a href=”manger/BookManagerServlet?method=findPage&pageNumber=1”>首页</a>
从而设置进path中那么我们在页面中就可以直接使用
${page.path}&pageNumber=…
如下:
<a href=”${page.path}&pageNumber=1”>首页</a>
<a href=”${page.path}&pageNumber=${page.pageNumber-1}”>上一页</a>
//接下来正如我们看到的分页 是 1 2 3 4 5 ….
那么我们就的遍历这个下标
<c:forEach begin=”1” end=”${page.totalPage}” var=”index”>
<c:choose>
<c:when test=”index==${page.pageNumber}”>//当前的下标等于当前页面 我们就着重显示一下
<spanstyle="color:red;">[${index }]</span>
</c:when>
<c:otherwise>//其他情况
<a href="${page.path }&pageNumber=${index }">${index }</a>
</c: otherwise >
</c:choose>
</c:forEach>
<a href=”${page.path}&pageNumber=${page.pageNumber-1}”>下一页</a>
<a href=”${page.path}&pageNumber=${page.totalPage}”>末页</a>
在我们页面中一般还显示这个
共${page.totalPage}页,${page.totalRecord}条记录,到第<input type=”text” value=”${page.pageNumber}” id=”pn_id”/>页<input type=”submit” value=”确定” id=”btn”/>
//因为你点击了这个确定按钮 我们的地址栏是要发生变换的 所以 我们用jQuery来做这个让地址栏发生变化的工作
//当然 你得保证你前面导入过jQuery 库
<script type=”text/javascript”>
$(“#btn”).click(function(){
//首先我们得获取输入的pageNumber
var pn = $(“#pn_id”).val();
//window有个属性可以直接更改地址
window.location=”${page.path}$pageNumber=”+pn;
});
</script>
做到这里感觉总算完成了 分页 其实 不然 我们想象一下 一些网站的分页
所以我们来反思我们的代码也就是 遍历下标那段
<c:forEach begin=”1” end=”${page.totalPage}” var=”index”>
<c:choose>
<c:when test=”index==${page.pageNumber}”>//当前的下标等于当前页面 我们就着重显示一下
<spanstyle="color:red;">[${index }]</span>
</c:when>
<c:otherwise>//其他情况
<a href="${page.path }&pageNumber=${index }">${index }</a>
</c: otherwise >
</c:choose>
</c:forEach>
那就要求我们的begin 和 end 应该是动态变化的
假设我们的分页是每5页显示一个
[1] 2 3 4 5
1 [2] 3 4 5
1 2 [3] 4 5
当我们选择4的时候
2 3 [4] 5
begin 就变成了2 end 就变成了 6
….
其实很简单我们只要每次判断当前pageNumber是多少从而 更新我们begin 和 end
<c:choose >
<c:when test=”${page.pageNumber<=3}”> 可以设置1 到 5
<c:set var=”begin” value=”1”></c:set>
<c:set var=”end” value=”5”></c:set>//但要注意 万一我们的总页数不足5页呢?
<c:if test=”${page.totalPage < 5}”>
<c:setvar=”end” value=”${ page.totalPage }”></c:set>
</c:if>
</c:when>
<c:when test=”${page.pageNumber > 3}”>
<c:set var=”begin”value=”${pageNumber-2}”></c:set>
<c:set var=”end” value=”${pageNumber+2}”></c:set>
//问题又来了 那万一我们当前的页是最后一页呢
<c:if test=”${page.pageNumber== page.totalPage}”>
<c:setvar=”begin” value=”${pageNumber-4}”></c:set>
<c:set var=”end” value=”${page.totalPage}”></c:set>
</c:if>
</c:when>
</c:choose>
然后我们更改一下 我们之前写的遍历 下标
<c:forEach begin=”${begin}” end=”${end}” var=”index”>
<c:choose>
<c:when test=”index==${page.pageNumber}”>//当前的下标等于当前页面 我们就着重显示一下
<spanstyle="color:red;">[${index }]</span>
</c:when>
<c:otherwise>//其他情况
<a href="${page.path }&pageNumber=${index }">${index }</a>
</c: otherwise >
</c:choose>
</c:forEach>