10.10
一、项目:
做了分页:
(1)对于输入,输出(相对于服务器而言):
输出(服务器需要向客户端输出的数据):
- int totalCount //查询出来的总记录数
- int totalPage //总页码数
- List list //当前页要显示的条目
- int currentPage //当前页码(为了给当前页码加上被选中的样式)
最后服务器会将这些项目封装成PageBean对象一起输出给客户端,注在PageBean对象对象中还多加了一项rows,为了方便
输入(客户端向服务器的输入):
1.对于服务器端所需的totalCount,客户端不需要输入,服务器直接查询即可:
select count(*) from user;
2.对于totalPage,需要用到客户端输入的rows(每一页显示多少条数据):
totalPage=totalCount%rows==0 ? totalCount/rows : totalCount/rows+1;
3.对于list,可以直接用select从第几个开始查询
select * from user limit 参数1,参数2
其中参数1是:从哪开始查
参数2是:查询多少条
所以需要客户端输入当前是多少页currentPage,从而确定开始从哪开始查:
比如:
当前页码:参数1,参数2
第一页:0,5
第二页:5,5
第三页:10,5
所以:int start=(currentPage-1)*rows
4、对于currentPage是客户端直接传给服务器的
所以客户端只需传两个参数给服务器:currentPage和rows
(2)后端编写
(1)先写PageBean对象:
public class PageBean<T> {
int totalCount; //查询的总记录数
int totalPage;//查询出来的总页码数
List<T> list; //查询出来的该页码下的条目
int currentPage;//当前的页码
int rows;//每页中显示的条数
...(加set和get,tostring方法)
}
注意:此处用泛型,因为不知道要显示的对象是什么,可能是User,也可能是别的,为了以后通用
(2)前端点击页码向后台传两个参数,currentPage和rows,后台接收参数
String currentPage = request.getParameter("currentPage");
String rows = request.getParameter("rows");
(3)调用service查询PageBean:
(11)
userService userService=new userServiceImpl();
PageBean<User> cp=userService.findUserByPage(currentPage,rows);
(22)userServiceImpl中的findUserByPage方法:
public PageBean<User> findUserByPage(String _currentPage, String _rows) {
// TODO Auto-generated method stub
//创建一个空的PageBean对象
PageBean<User> pageBean=new PageBean<User>();
//将参数字符串型转换成整型
int currentPage=Integer.parseInt(_currentPage);
int rows=Integer.parseInt(_rows);
//设置currentPage和rows的值
pageBean.setCurrentPage(currentPage);
pageBean.setRows(rows);
//计算一共有多少条数据
int totalCount=users.findTotalCount();
pageBean.setTotalCount(totalCount);
//计算总共有多少页
int totalPage=totalCount%rows==0?totalCount/rows:(totalCount/rows+1);
pageBean.setTotalPage(totalPage);
//计算当前页显示的条目
int start=(currentPage-1)*rows;
List<User> list=users.findByPage(start,rows);
pageBean.setList(list);
return pageBean;
}
(33)userDaoImpl中findTotalCount和findByPage方法:
public int findTotalCount() {
// TODO Auto-generated method stub
String sql="select count(*) from user1";
return jdbc.queryForObject(sql, Integer.class);
}
public List<User> findByPage(int start, int rows) {
// TODO Auto-generated method stub
String sql="select * from user1 limit ?,?";
List<User> list = jdbc.query(sql, new BeanPropertyRowMapper<User>(User.class),start,rows);
return list;
}
(1)现在终于明白query和queryForObject的区别了:前者返回的是多个查询结果,后者返回的是一个查询结果。
(2)query...第二个参数的作用:返回值类型
比如:第一个函数中为Integer.class返回的是一个整型
第二个为new BeanPropertyRowMapper<User>(User.class),返回的是User类型,但由于是query,所以返回的是User类型的list.
(3)将PageBean存入到request中
request.setAttribute("cp", cp);
注意:名字是cp,后面会多次提到
(4)转发到list.jsp页面(该页面用来展示查询的结果)
request.getRequestDispatcher("/list.jsp").forward(request, response);
(3)前端编写:
(1)首先在展示的表格中for循环的对象不再是 u s e r 整 个 查 询 的 结 果 了 , 而 应 该 改 成 {user}整个查询的结果了,而应该改成 user整个查询的结果了,而应该改成{cp.list}
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th><input type="checkbox" id="firstcb"></th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<c:forEach items="${cp.list}" var="user" varStatus="s"> //注意此处改成cp.list
<tr>
<th><input name="uid" value="${user.id }" type="checkbox"></th>
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.age}</td>
<td>${user.address}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td><a class="btn btn-default btn-sm" href="${pageContext.request.contextPath }/findUserServlet?id=${user.id}">修改</a>
<a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id });">删除</a></td>
</tr>
</c:forEach>
</table>
(2)改页码的总记录数,总页码数,以及显示多少页:
//改显示的总记录数和总页码数
<span style="font-size:25px;margin-left: 5px">
共${cp.totalCount }条数据,共${cp.totalPage}页
</span>
//用循环显示各个页码数
<c:forEach begin="1" end="${cp.totalPage}" var="i">
<li><a href=#">${i}</a></li>
</c:forEach>
(3)每按一页就显示该页码应下的条目:
将循环中的<li><a href=#">${i}</a></li>中的herf改成:
href="${pageContext.request.contextPath }/findUserByPage?currentPage=${i}&&rows=5"
(4)将index.jsp中点击查询的路径不再是userListServlet查询所有的了,改成fingUserByPage,再此处由于是第一次访问findUserByPage需要传递参数 currentPage和rows,但是不在此处传,而在后台发ingUserByPage中做相应的处理:
String currentPage = request.getParameter("currentPage");
if(currentPage==null ||"".equals(currentPage)) {
currentPage="1";
} //如果是这两种的话,直接默认赋值为1
String rows = request.getParameter("rows");
if(rows==null || "".equals(rows)) {
rows="5";
}
(4)优化:
(1)当前选中页码的样式,与未选中的不同
在展示页码那里改,如果获取的当前页码与此页码相同,则置为bootStrap中的激活,加上一个class样式:
由这个:
<c:forEach begin="1" end="${cp.totalPage}" var="i">
<li><a href=#">${i}</a></li>
</c:forEach>
改成:
<c:forEach begin="1" end="${cp.totalPage}" var="i">
//若当前选中页码与此页码想相同,则加class="active",置为激活状态
<c:if test="${cp.currentPage==i }">
<li class="active"><a href="${pageContext.request.contextPath }/findUserByPage?currentPage=${i}&&rows=5">${i}</a></li>
</c:if>
//若不等于,则不加
<c:if test="${cp.currentPage!=i }">
<li><a href="${pageContext.request.contextPath }/findUserByPage?currentPage=${i}&&rows=5">${i}</a></li>
</c:if>
</c:forEach>
(2)上一页和下一页功能:
//上一页,就是在当前页的基础上减1
<li>
<a href="${pageContext.request.contextPath }/findUserByPage?currentPage=${cp.currentPage-1}&&rows=5" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
//下一页,就是在当前页的基础上加1
<li>
<a href="${pageContext.request.contextPath }/findUserByPage?currentPage=${cp.currentPage+1}&&rows=5" aria-label="Next">
<if>
此处的bug是:如果当前页是1,则点上一页会报错,同样当前页是最后一页的话,虽然不会报错,但效果不佳:
(1)现在前端加上禁止提示,即当前页是第一页或最后一页时,再点击会出现禁用点击的图标:加上class标签即可:
上一页的处置:
<c:if test="${cp.currentPage==1 }">
<li class="disabled"> //加上class标签
</c:if>
<c:if test="${cp.currentPage!=1 }">
<li>
</c:if>
<a href="${pageContext.request.contextPath }/findUserByPage?currentPage=${cp.currentPage-1}&&rows=5" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
下一页类似:
(2)虽然在前端做了如此处理,但是当当前页为1时还是可以继续点击并报错的,一种处理是:
上一页的处理:在后端进行:
int parseInt = Integer.parseInt(currentPage);
if(parseInt<1) {
currentPage="1";
}
如果当前页小于1时,将当前页置为1
下一页的处理:在前端进行:
//r如果当前页是最后一页时,传参数时传递的仍然是当前页
<c:if test="${cp.currentPage==cp.totalPage }">
<a href="${pageContext.request.contextPath }/findUserByPage?currentPage=${cp.totalPage}&&rows=5" aria-label="Next">
</c:if>
//如果当前页不是最后一页,传参数时加1页
<c:if test="${cp.currentPage!=cp.totalPage }">
<a href="${pageContext.request.contextPath }/findUserByPage?currentPage=${cp.currentPage+1}&&rows=5" aria-label="Next">
</c:if>