|
说到分页算法,一般WEB开发都会用到,我只是在我的实现技术上用了struts框架,其实原理都一样的。 看了网上相当多的分页算法,有对的也有好多是错的,更有好多是不太优化的。还有以前自己在augmentum做的一个分页算法,总结了一些不足。决定重新再写一个分页算法。 首先,应该写个bean来记录存储一些页面的属性 分页大致需要如下属性:
private int currentPage = 1; // 当前页
private int totalPages = 0; // 总页数
private int pageRecorders = 5;// 每页5条数据
private int totalRows = 0; // 总数据数
private int pageStartRow = 0;// 每页的起始数
private int pageEndRow = 0; // 每页显示数据的终止数
private boolean hasNextPage = false; // 是否有下一页
private boolean hasPreviousPage = false; // 是否有前一页 private int nextPage = 0;//下一页的页码 private int previousPage = 0;//上一页的页码
然后这些属性之间是有联系的,我们可以在构造函数的时候就初始化一些属性 有两种方法: 一,根据总的页数,(假设当前页为1) public PageBean(int totalRows){ this.totalRows = totalRows; this.currentPage = 1; hasPreviousPage = false; if ((totalRows % pageRecorders) == 0) { totalPages = totalRows / pageRecorders; } else { totalPages = totalRows / pageRecorders + 1; } if (totalRows >= pageRecorders) { hasNextPage = true; nextPage = 2; this.pageEndRow = pageRecorders; } else { this.pageEndRow = totalRows; hasNextPage = false; nextPage = 1; } this.pageStartRow = 0; previousPage = 1; } 然后在按下一页或者上一页的时候需要如下函数处理: public void nextPage() { if(hasNextPage == true) currentPage = currentPage + 1; if ((currentPage - 1) > 0) { hasPreviousPage = true; } else { hasPreviousPage = false; } if (currentPage >= totalPages) { hasNextPage = false; this.nextPage = currentPage; } else { hasNextPage = true; nextPage = currentPage+1; } this.pageStartRow = (currentPage -1) * pageRecorders; if(hasNextPage == true) this.pageEndRow = pageStartRow + 5; else{ this.pageEndRow =this.totalPages; } previousPage = currentPage - 1; } public void previousPage() { if(hasPreviousPage == true) currentPage = currentPage - 1; if (currentPage == 0) { currentPage = 1; } if (currentPage >= totalPages) { hasNextPage = false; } else { hasNextPage = true; } nextPage = currentPage + 1; if ((currentPage - 1) > 0) { hasPreviousPage = true; previousPage = currentPage - 1; } else { hasPreviousPage = false; previousPage = currentPage; } this.pageStartRow = (currentPage -1) * pageRecorders; if(hasNextPage == true) this.pageEndRow = pageStartRow + 5; else{ this.pageEndRow =this.totalPages; } } 在HTML中按下一页或者上一页的时候有如下代码: <logic:equal name="page" property="hasNextPage" value="true"> <html:link page="/List.do?action=nextPage"> nextPage </html:link> </logic:equal> <logic:equal name="page" property="hasPreviousPage" value="true"> <html:link page="/List.do?action=previousPage"> PreviousPage </html:link> </logic:equal> 然后在Action中作如下处理: String currentPage = request.getParameter("currentPage"); HttpSession session = request.getSession(); EmployeeForm employeeForm = (EmployeeForm) form; String queryString = null; String queryCon = null; String action = employeeForm.getAction(); List list = new ArrayList(); PageBean pb = null; EmployeeDao employeeDao = new EmployeeDao(); if(action == null || action.equals("null")){ int totalRows = employeeDao.getTotalRows(); pb = new PageBean(totalRows); session.removeAttribute("page"); queryString = employeeForm.getQueryString(); queryCon = employeeForm.getQueryCon(); session.setAttribute("queryString",queryString); session.setAttribute("queryCon",queryCon); list = employeeDao.getAllEmployee(queryString, queryCon, String.valueOf(pb.getPageStartRow()), String.valueOf(pb.getPageRecorders())); }else if(action.equals("nextPage")){ queryString = (String)session.getAttribute("queryString"); queryCon = (String)session.getAttribute("queryCon"); employeeForm.setQueryString(queryString); employeeForm.setQueryCon(queryCon); pb = (PageBean)session.getAttribute("page"); pb.nextPage(); list = employeeDao.getAllEmployee(queryString, queryCon, String.valueOf(pb.getPageStartRow()), String.valueOf(pb.getPageRecorders())); }else if(action.equals("previousPage")){ queryString = (String)session.getAttribute("queryString"); queryCon = (String)session.getAttribute("queryCon"); employeeForm.setQueryString(queryString); employeeForm.setQueryCon(queryCon); pb = (PageBean)session.getAttribute("page"); pb.previousPage(); list = employeeDao.getAllEmployee(queryString, queryCon, String.valueOf(pb.getPageStartRow()), String.valueOf(pb.getPageRecorders())); } pb.description(); session.setAttribute("page",pb); request.setAttribute("admin", "admin"); request.setAttribute("employee", list); return mapping.findForward("showlist"); 然后在数据库查询中有如下代码: /** *查询总记录数 */ public int getTotalRows() { int totalRows = 0; String sql = "select count(*) from employee";//假设是员工表 Database db = new Database(); ResultSet rs = db.executeQuery(sql); try { while (rs.next()) { String id = (String) rs.getString(1); totalRows = Integer.parseInt(id); } } catch (SQLException e) { e.printStackTrace(); } db.close(); return totalRows; } /* *查询每一页需要查询的页码 */ public List getAllEmployee(String queryString, String queryCon,String startRow,String num) { List list = new ArrayList(); String sql = null; if (queryString == null || queryString.equals("")) { sql = "select * from employee,dept " + "where dept.Id = employee.deptId " + "order by employee.id asc"+ " limit "+startRow+","+num; } else { sql = "select * from employee,dept " + "where dept.Id = employee.deptId order by employee." + queryString + " " + queryCon + " limit "+startRow+","+num; } Employee employee = null; Database db = new Database(); ResultSet rs = db.executeQuery(sql); try { while (rs.next()) { String id = (String) rs.getString("employee.id"); String name = (String) rs.getString("employee.name"); String deptId = (String) rs.getString("employee.deptId"); String deptName = (String) rs.getString("dept.deptName"); employee = new Employee(); employee.setId(id); employee.setName(name); employee.setDeptId(deptId); employee.setDeptName(deptName); list.add(employee); } } catch (SQLException e) { e.printStackTrace(); } db.close(); return list; } 这里我用了hibernate进行数据库操作,你也可以用jdbc进行操作,情况类似。
二,根据总的页数,当前页 这样的话构造函数应该写成: public PageBean(int totalRows,int currentPage) { this.totalRows = totalRows; this.currentPage = currentPage; if(currentPage < 2) hasPreviousPage = false; else hasPreviousPage = true; if ((totalRows % pageRecorders) == 0) { totalPages = totalRows / pageRecorders; } else { totalPages = totalRows / pageRecorders + 1; } if (currentPage < totalPages) { hasNextPage = true; nextPage = currentPage + 1; pageStartRow = (currentPage - 1)*pageRecorders; this.pageEndRow = pageStartRow + pageRecorders; } else if(currentPage == totalPages){ pageStartRow = (currentPage - 1)*pageRecorders; this.pageEndRow = totalRows; hasNextPage = false; nextPage = currentPage; } if(currentPage < 2){ previousPage = currentPage; hasPreviousPage = false; }else if(currentPage > 1){ previousPage = currentPage-1; hasPreviousPage = true; } }
在action中应该写成 if(currentPage == null){ pb = new PageBean(totalRows); session.removeAttribute("page"); queryString = employeeForm.getQueryString(); queryCon = employeeForm.getQueryCon(); session.setAttribute("queryString",queryString); session.setAttribute("queryCon",queryCon); list = employeeDao.getAllEmployee(queryString, queryCon, String.valueOf(pb.getPageStartRow()), String.valueOf(pb.getPageRecorders())); } else{ pb = new PageBean(totalRows,Integer.parseInt(currentPage)); queryString = employeeForm.getQueryString(); queryCon = employeeForm.getQueryCon(); session.setAttribute("queryString",queryString); session.setAttribute("queryCon",queryCon); list = employeeDao.getAllEmployee(queryString, queryCon, String.valueOf(pb.getPageStartRow()), String.valueOf(pb.getPageRecorders())); } session.setAttribute("page",pb); request.setAttribute("admin", "admin"); request.setAttribute("employee", list); return mapping.findForward("showlist");
在jsp中应该写成: <logic:equal name="page" property="hasNextPage" value="true"> <a href="List.do?currentPage=<bean:write name="page" property="nextPage"/>"> nextPage </a> </logic:equal> <logic:equal name="page" property="hasPreviousPage" value="true"> | <a href="/test/List.do?currentPage=<bean:write name="page" property="previousPage"/>"> PreviousPage </a> </logic:equal> 数据库查询部分依然适用。
尽管洋洋洒洒贴了一部分代码,不过好像不太想看,包括我,也比较讨厌看一些烦琐的代码,所以如果你想要源代码进行探讨研究的话,欢迎随时找我。那就总结一下这两种方法吧 首先这两种方法都是取需要显示的数据显示,这样,在数据库庞大的情况下,比一次性把所有数据都取出来的效率要高。 第一种方法是把PageBean存在了一个HttpSession中,在进入到显示列表的时候就进行了初始化,在jsp页面传递的参数action是固定的三个值:null,nextPage,previousPage.这样虽然比较容易理解,但是我发现一个BUG,就是如果你按刷新,他也会翻页,因为他的url就是 .do?aciton=nextPage,这样的话你传进去的action还是有一个值,这样就会导致翻页。 第二种方法是考虑了第一种方法的BUG,在jsp页面传递的参数currentPage的值是bean中的nextPage的值或者previousPage里的值,用了struts标签库嵌套,把值赋予currentPage,这样的话currentPage的值是:1,2,3,4...totalPages之间。这样的话你即使按刷新按钮,他也是当前页,因为他的url就是.do?currentPage=someNumber(someNumber是1到totalPages中的一个值)。但是这样的话Pagebean在每次访问的时候都要重新生成一个对象,该对象也是根据totalRows(总数据数),currentPage(当前页数)进行构造,从而设置其他的一些属性。个人比较推荐第二种方法。
|