分页主要需要两个参数:
1、当前页是第几页
2、每页展示多少条数据
先写一个类来封装处理这两个参数:
package com.smvc.annonation.utils; import java.io.Serializable; import java.util.List; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; public class ResultFilter<T> implements Serializable{ private static final long serialVersionUID = 5472321653620726832L; private final static int DEFAULT_NAVIGATOR_SIZE = 5; //当前页 private int currentPage = 1; //每页显示数量 private int pageSize = 5; //总条数 private int totalCount; private boolean havaNextPage; private boolean havePrePage; private int navigatorSize; //存放查询结果用的list private List<T> items; public ResultFilter(){ } public ResultFilter(int totalCount, int pageSize, int currentPage) { this(totalCount, pageSize, currentPage, DEFAULT_NAVIGATOR_SIZE); } public ResultFilter(int totalCount, int pageSize, int currentPage, int navigatorSize) { this.totalCount = totalCount; this.pageSize = pageSize; this.currentPage = currentPage; this.navigatorSize = navigatorSize; } public int getPageCount() { int pageCount = 0; if (pageSize != 0) { pageCount = totalCount / pageSize; if (totalCount % pageSize != 0) pageCount++; } return pageCount; } public int getCurrentPage() { currentPage = currentPage < getPageCount() ? currentPage : getPageCount(); currentPage = currentPage < 1 ? 1 : currentPage; return currentPage; } public int getPageSize() { return pageSize; } public int getTotalCount() { return totalCount; } public boolean isHaveNextPage() { havaNextPage = false; if ((getPageCount() > 1) && (getPageCount() > getCurrentPage())) havaNextPage = true; return havaNextPage; } public boolean isHavePrePage() { havePrePage = false; if ((getPageCount() > 1) && (currentPage > 1)) havePrePage = true; return havePrePage; } private int getNavigatorIndex(boolean isBegin) { int beginNavigatorIndex = getCurrentPage() - navigatorSize / 2; int endNavigatorIndex = getCurrentPage() + navigatorSize / 2; beginNavigatorIndex = beginNavigatorIndex < 1 ? 1 : beginNavigatorIndex; endNavigatorIndex = endNavigatorIndex < getPageCount() ? endNavigatorIndex : getPageCount(); while ((endNavigatorIndex - beginNavigatorIndex) < navigatorSize && (beginNavigatorIndex != 1 || endNavigatorIndex != getPageCount())) { if (beginNavigatorIndex > 1) beginNavigatorIndex--; else if (endNavigatorIndex < getPageCount()) endNavigatorIndex++; } if(isBegin) return beginNavigatorIndex; else return endNavigatorIndex; } public int getBeginNavigatorIndex() { return getNavigatorIndex(true); } public int getEndNavigatorIndex() { return getNavigatorIndex(false); } public List<T> getItems() { return items; } public void setItems(List<T> items) { this.items = items; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } }
接着,就要处理如何翻页的问题。解决方法就是在页面间传递参数,传递当前是第几页。
使用自己定义标签实现比较简便(由于现在只做了一个页面,并不能保证翻页功能的通用性,以后会慢慢完善)
自定义标签的配置:
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <description>My Tag Library</description> <tlib-version>1.0</tlib-version> <short-name>my</short-name> <uri>my-taglib</uri> <tag> <description>split page</description> <name>paging</name> <tag-class>com.smvc.annonation.tag.PagingTag</tag-class> <body-content>empty</body-content> <attribute> <description>base href</description> <name>href</name> <required>false</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <description>curr page</description> <name>curr</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <description>page size</description> <name>size</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <description>total page</description> <name>total</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <description>curr parameter name</description> <name>cparam</name> <required>false</required> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <description>page size parameter name</description> <name>sparam</name> <required>false</required> <rtexprvalue>false</rtexprvalue> </attribute> <dynamic-attributes>false</dynamic-attributes> </tag> <tag> <description>front split page</description> <name>frontPaging</name> <tag-class>com.aspire.cms.demo.framework.tag.FrontPagingTag</tag-class> <body-content>empty</body-content> <attribute> <description>base href</description> <name>href</name> <required>false</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <description>result filter</description> <name>rf</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <dynamic-attributes>false</dynamic-attributes> </tag> </taglib>
对应的java类:
package com.smvc.annonation.tag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; import org.apache.commons.lang.StringUtils; public class PagingTag extends SimpleTagSupport { private String href; //当前页 private String cparam; //每页条数 private String sparam; private int curr;//当前页 private int size;//每页条数 private int total;//总页数 @Override public void doTag() throws JspException, IOException { JspWriter out = getJspContext().getOut(); if(StringUtils.isEmpty(cparam)) { cparam = "currentPage"; } if(StringUtils.isEmpty(sparam)) { sparam = "pageSize"; } if(!href.endsWith("?") && !href.endsWith("&")) { if(href.indexOf("?") == -1) { href = href + "?"; } else { href = href + "&"; } } if (curr <= 0) { curr = 1; } else if (curr > total) { curr = total; } out.append("<span>"); // 首页 if (curr == 1) { out.append("首页"); } else { href(out, href, 1, "首页"); } out.append(" | "); // 上一页 if (curr == 1) { out.append("上一页"); } else { href(out, href, curr - 1, "上一页"); } out.append(" | "); // 下一页 if (curr == total) { out.append("下一页"); } else { href(out, href, curr + 1, "下一页"); } out.append(" | "); // 末页 if (curr == total) { out.append("末页"); } else { href(out, href, total, "末页"); } out.append("</span>"); out.append("<span>第"); out.append(curr + "/" + total); out.append("页</span>"); super.doTag(); } private void href(JspWriter out, String href, int curr, String title) throws IOException { out.append("<a href=\"").append(href).append(cparam).append("=").append("" + curr).append("&").append(sparam).append("=").append("" + size).append("\">").append(title).append("</a>"); } public int getCurr() { return curr; } public void setCurr(int curr) { this.curr = curr; } public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public String getHref() { return href; } public void setHref(String href) { this.href = href; } public String getCparam() { return cparam; } public void setCparam(String cparam) { this.cparam = cparam; } public String getSparam() { return sparam; } public void setSparam(String sparam) { this.sparam = sparam; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } }
在jsp中使用自定义的标签库来实现翻页功能:
list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ page session="false"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib uri="my-taglib" prefix="my"%> <title>学生列表</title> <form action="list" method="post"> <table> <tr> <td width="160">id</td> <td width="160">姓名</td> <td width="160">性别</td> <td width="160">年龄</td> <td width="160">生日</td> </tr> <c:forEach items="${rf.items}" var="student"> <tr> <td><c:out value="${student.id}"/></td> <td><c:out value="${student.name}"/></td> <td><c:out value="${student.gender}"/></td> <td><c:out value="${student.age}"/></td> <td><fmt:formatDate value="${student.birthday}" type="both" pattern="yyyy-MM-dd"/></td> </tr> </c:forEach> </table> <my:paging curr="${rf.currentPage}" total="${rf.pageCount}" size="${rf.pageSize}" href="list"/> </form>
controller中根据参数对ResultFilter进行设置:
@RequestMapping(value="/list") public ModelAndView listStudent(@ModelAttribute ResultFilter<Student> rf){ studentService.listStudent(rf); return new ModelAndView("list", "rf", rf); }
service中的方法:
public void listStudent(ResultFilter<Student> rf){ rf.setTotalCount(getStudentCount()); rf.setItems(studentDao.getListForPage("from Student", (rf.getCurrentPage() - 1 )* rf.getPageSize(), rf.getPageSize())); }
这个方法没有使用session,能支持多台服务器共同提供服务的情况。但是这个方法的效率可能有点低,因为每次翻页的时候都会重新创建一个ResultFilter,使用hibernate的缓存应该会使性能有所提高。