Java互联网架构学习之page分页
1.在DAO层连接数据库是使用limit查询,传入index和pageSize参数
如我按页查询我的book信息,返回一个Book类型的List
public List<Book>getLimitBookList(int index,int pageSize){ Connection conn=JDBCUtil.getConnection(); List<Book> Books=new ArrayList<>(); ResultSet rs=null; String sql="select * from book limit ? , ?"; PreparedStatement ps=null; try { ps=conn.prepareStatement(sql); ps.setInt(1, index); ps.setInt(2, pageSize); rs=ps.executeQuery(); while(rs.next()) { Books.add(new Book(rs.getInt("id"),rs.getString("name"), rs.getString("writer"),rs.getString("category"))); } } catch (Exception e) { // TODO: handle exception }finally { JDBCUtil.close(conn, ps, rs); } return Books; }
并要有一个获得总记录数的方法,此处不在赘述
2.建立一个page的实体bean
其中成员如下:
private int pageNumber; private int pageSize; private int index; private int totalRecord; private List<T> data; private String path;pageNumber需要经过过滤,防止页面上的上一页和下一页造成首页末页溢出
public int getPageNumber() { //如果pageNumber<1,则返回1 if(pageNumber < 1){ return 1; } //如果当前页大于总页数,则返回总页数 if(pageNumber > getTotalPage()){ return getTotalPage(); } return pageNumber; }需要有计算总页数的方法
public int getTotalPage() { /** * 在这来计算总页数 * * 总记录数 每页的条数 总页数 * 10 2 5 * 9 2 5 * 8 2 4 * 7 2 4 * * 当可以整除时: * totalRecord/pageSize * * 当有余数时: * totalRecord/pageSize+1 */ if(getTotalRecord()%getPageSize()==0){ return getTotalRecord()/getPageSize(); }else{ return getTotalRecord()/getPageSize()+1; } }需要通过当前页码来计算index,即limit搜索中的起始位置
public int getIndex() { /** * 在getIndex方法中来计算index值 * * index pageSize pageNumber * 0 3 1 * 3 3 2 * 6 3 3 * index = (pageNumber-1)*pagesize */ return (getPageNumber() - 1) * getPageSize(); }其余通过编译器生成set/get方法即可
3.在service层中需要new一个dao对象,传入pageNo和pageSize获得结果对象集合,获得总记录数,并使用这些成员创建一个page对象,返回给上层
public class BookPageService { private searchBookDao searchBookDao=new searchBookDao(); public Page<Book>getBookList(int pageNo,int pageSize){ //1.查询表中所有数据数 int totalRecord = searchBookDao.getTotalRecord(); //2.创建page对象 Page<Book>page=new Page<Book>(totalRecord,pageNo,pageSize); //3.查询分页数据并存储到page中 List<Book>list=searchBookDao.getLimitBookList(page.getIndex(), page.getPageSize()); page.setData(list); return page; } public Book getBookById(int id) { return searchBookDao.getBookById(id); } }
4.创建一个BaseServlet,实现对方法的反射,使得可以通过调用servlet并在url中传入方法名来调用相关方法
@WebServlet("/BaseServlet") public class BaseServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected static int pageNo=1; protected static int pageSize=2;//自行设定 public BaseServlet() { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { pageNo=Integer.parseInt(request.getParameter("pageNo")); } catch (NumberFormatException e) { e.getMessage(); } //获取用户传递的请求参数 String methodName=request.getParameter("method"); //通过方法名获取到方法的对象 //获取当前类的Class对象 Class cla=this.getClass(); //获取cla的的方法(Method对象) //getDeclaredMethod需要两个参数,方法名和参数名 //因为在java需要通过方法名和参数列表来确定一个方法 try { //获取方法对象 Method method=cla.getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class); //设置方法权限 method.setAccessible(true); //调用方法 //invoke用于调用一个方法,第一个参数时要调用方法的对象,剩下是调用方法需要的参数 method.invoke(this, request,response); } catch (Exception e) { e.getMessage(); } }
5.创建一个搜索用servlet,继承BaseServlet父类,在其中定义方法,对页面请求进行处理
public class BookPageService { private searchBookDao searchBookDao=new searchBookDao(); public Page<Book>getBookList(int pageNo,int pageSize){ //1.查询表中所有数据数 int totalRecord = searchBookDao.getTotalRecord(); //2.创建page对象 Page<Book>page=new Page<Book>(totalRecord,pageNo,pageSize); //3.查询分页数据并存储到page中 List<Book>list=searchBookDao.getLimitBookList(page.getIndex(), page.getPageSize()); page.setData(list); return page; } public Book getBookById(int id) { return searchBookDao.getBookById(id); } }
此处使用了getPath(request)方法,由于页面url每次传入时在后面加一个&pageNo=...,第二次后就会在url后进行叠加,如127.0.0.1:8080/xxxx.yyyServlet?pageNo=1&pageNo=2&pageNo=3,这样无法使用,于是对url进行一个过滤
public static String getPath(HttpServletRequest request) { String requestURI = request.getRequestURI(); String queryString = request.getQueryString(); String url=requestURI+"?"+queryString; if (url.contains("&pageNo")) { url = url.substring(0, url.indexOf("&pageNo")); } return url; }
至此,后端分页已全部完成,下面来完成前端的分页
1.页面向servlet发送的请求格式应为如下:
<a href="${pageContext.request.contextPath }/BookPageServlet?method=getBookList&pageNo=1">
我们刚刚定义了BaseServlet的反射,便需要在url中传入一个method的parameter,用以获取调用哪个函数,并传入初始页面号1
2.在显示页面获取的Book集合对象为${page.data }
3.在显示页面加入页码条的代码
为实现java的封装思想,我们选择在表单最后静态包含一个paging.jsp页面,在该页面中写入页码条的代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <div id="page_nav" align="center"> <a href="${page.path }&pageNo=1">首页</a> <a href="${page.path }&pageNo=${page.pageNumber-1}">上一页</a> <c:choose> <c:when test="${page.totalPage <= 5}"> <c:set var="begin" value="1"></c:set> <c:set var="end" value="${page.totalPage }"></c:set> </c:when> <c:when test="${page.pageNumber<=3 }"> <c:set var="begin" value="1"></c:set> <c:set var="end" value="5"></c:set> </c:when> <c:otherwise> <c:set var="begin" value="${page.pageNumber-2 }"></c:set> <c:set var="end" value="${page.pageNumber+2 }"></c:set> <c:if test="${end >=page.totalPage}"> <c:set var="begin" value="${page.totalPage-4 }"></c:set> <c:set var="end" value="${page.totalPage }"></c:set> </c:if> </c:otherwise> </c:choose> <c:forEach begin="${begin }" end="${end}" var="num"> <c:if test="${page.pageNumber==num }">[${num }]</c:if> <c:if test="${page.pageNumber!=num }"> <a href="${page.path }&pageNo=${num}">${num }</a> </c:if> </c:forEach> <a href="${page.path }&pageNo=${page.pageNumber+1}">下一页</a> <a href="${page.path }&pageNo=${page.totalPage}">末页</a> 共${page.totalPage }页,${page.totalRecord }条记录,跳转至<input type="text" id="pageInput">页 <input type="button" value="确定" id="btn1"/> <script type="text/javascript"> $("#btn1").click(function(){ var value= $("#pageInput").val(); window.location="${page.path}&pageNo="+value; }); </script> </div>
本页面需要导入taglib-standard-impl、taglib-standard-spec、jquery.min.js三个包
至此,我们手工添加的页码条可以说大功告成了
—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— ——
表单分页是一个搜索功能所必备的功能之一,十分的重要,倘若没有,数据量小尚可,数据量大那网页就爆炸了。我们以前的增删查改一直没有考虑这个问题,因为我们都是基于自己测试的渺小的数据上。课程设计的分页也是使用的easy-ui,填一下复制一下代码,从数据库搜索出count(*)就完事了,也不知道是什么原理,具体在哪里实现的也不知道。今日的分页功能我尚为模仿老师的方法,完全脱离老师的代码和视频,要写出来可能相当的费劲,仍需要多加练习,深化理解。不会自己写而只会模仿、只会填代码是不会进步的,这只会将自己局限为一个码农的角色,把自己的视野定格在眼前的一亩三分地中。狮子不是天生会捕猎的,也是通过不断的练习、模仿才成为一匹草原之王,倘若出生就把它关在笼子里喂食,它只会成为一只张嘴咀嚼的家猫。我们不能把今天的内容单单的当做一个工具包,“以后要用了直接导入就行”,没有什么资源是永恒存在的,而对知识的理解并化为己有是永恒的。对于技术,如今的我们不是一个创造者的角色,我们是学习者是模仿者,我们学习的目标就是将可以利用的资源,可以学习的只是,转化为自己的东西,不断扩充自己的知识库,追寻创造者的脚印,虽不能说是楷模,但也要成为他人的模仿对象。
鸡汤作为一篇文章的结尾也许是必要的,也许是鸡肋,学习技术也许并不需要这样在结尾鸡汤一下。但我们过去接受的语文教育将这样的思想种植在了我们的大脑中,这样写更符合大众的风格。我们不研究哲学,我们不研究普世观,我们也不研究教育,我们不必去探索世间真相,我们不必去格物致知,我们也不必去学习一个营销号是怎样写一篇文的,我们只学习技术,博客只为提醒自己,那便不必在意那么许多,让形式停留在形式上。
- 上一篇: 项目server中设置session timeout遇到的问题
- 下一篇: php简单的下拉菜单