spring mvc 分页
分页主要需要两个参数:
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);
- }
- }
接着,就要处理如何翻页的问题。解决方法就是在页面间传递参数,传递当前是第几页。
使用自己定义标签实现比较简便(由于现在只做了一个页面,并不能保证翻页功能的通用性,以后会慢慢完善)
自定义标签的配置:
my.tld
- <?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的缓存应该会使性能有所提高。