JSP页面:
 
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <%-- 引入标签库 --%>
 <%@ taglib uri="" prefix="q"%>
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>自定义分页标签使用示例</title>
 <style type="text/css">
 body {
  margin-top: 20px;
  text-align: left;
  font-family: 宋体, Arial, Verdana;
  font-size: 13px;
  line-height: 150%;
  min-width:800px;
  word-break:break-all;
 }
 /* 分页标签样式 */
 .pagination {
     padding: 5px;
     float: right;
 }
 .pagination a, .pagination a:link, .pagination a:visited {
     padding: 2px 5px 2px 5px;
     margin: 2px;
     border: 1px solid #aaaadd;
     text-decoration: none;
     color: #006699;
 }
 .pagination a:hover, .pagination a:active {
     border: 1px solid #ff0000;
     color: #000;
     text-decoration: none;
 }
 .pagination span.current {
     padding: 2px 5px 2px 5px;
     margin: 2px;
     border: 1px solid #ff0000;
     font-weight: bold;
     background-color: #ff0000;
     color: #FFF;
 }
 .pagination span.disabled {
     padding: 2px 5px 2px 5px;
     margin: 2px;
     border: 1px solid #eee;
     color: #ddd;
 }
 </style>
   </head>
   
   <body>
    <div style="margin: 0px auto; width:700px">
    <div id="title">
      <h3>自定义数据分页标签的使用示例</h3><hr/>
    </div>
    <div id="data">
   <table border="1" width="600px" align="center">
   <%  //获取分页后的数据进行显示
    List<String> datas = (List<String>)request.getAttribute("datas");
    for(String str : datas){
       out.println("<tr><td>" + str + "</td></tr>");
    } %>
   </table>
    </div>
  <%-- 分页标签的使用 
  <q:pager pageNo='<%= ((Integer)request.getAttribute("pageNo")).intValue()%>'
    pageSize='<%= ((Integer)request.getAttribute("pageSize")).intValue()%>'
    recordCount='<%= ((Integer)request.getAttribute("recordCount")).intValue()%>'
    url="TestPagerTagServlet" />
   --%>
  <%-- 使用EL表达式简化分页标签的使用--%>
  <q:pager pageNo="${pageNo}"
     pageSize="${pageSize}"
     recordCount="${recordCount}"
     url="TestPagerTagServlet" />
  
    </div>
   </body>
 </html> 
JAVA类:
 
1、
package com.qiujy.web.Servlet;
import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;/**
  * 测试分页标签使用的Servlet
  * @author qiujy
  */
 public class TestPagerTagServlet extends HttpServlet { private static final long serialVersionUID = -3305996070755176492L;
 private List<String> datas;
  public static final int PAGER_PAGESIZE = 10;
  
  public void init() throws ServletException {
   datas  = new ArrayList<String>();
   for(int i = 1; i <= 123; i++){
    datas.add("字符串" + i);
   }
  } public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
   this.doPost(request, response);
  } public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
   request.setCharacterEncoding("utf-8");
   
   int recordCount = this.datas.size(); //获取总记录数  //获取当前页号
   int pageNo = 1;  
   String pageNoStr = request.getParameter("pageNo");
   if(null != pageNoStr && !pageNoStr.equals("")){
    pageNo = Integer.parseInt(pageNoStr);
   }  //获取分页数据
   int start = (pageNo - 1) * PAGER_PAGESIZE;
   int end = start + PAGER_PAGESIZE;
   if(end > this.datas.size()){
    end = this.datas.size();
   }
   List<String> results = this.datas.subList(start, end);
   
   //把分页数据和分页标签所需要的参数存放到request中
   request.setAttribute("datas", results);
   request.setAttribute("pageNo", pageNo);
   request.setAttribute("pageSize", PAGER_PAGESIZE);
   request.setAttribute("recordCount", recordCount);
   
   //转发请求到JSP页面
   request.getRequestDispatcher("/pager.jsp").forward(request, response);
  }
 }2、
/**
  *  ClassName: PagerTag.java
  *  created on 2009-03-20
  *  Copyrights 2009 qjyong All rights reserved.
  *  EMail: qjyong@gmail.com  */
 package com.qiujy.web.tags;import java.io.IOException;
 import java.util.Enumeration;import javax.servlet.http.HttpServletRequest;
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.tagext.TagSupport;/**
  * 分页标签处理类
  */
 public class PagerTag extends TagSupport {
  private static final long serialVersionUID = 5729832874890369508L;
  private String url;         //请求URI
  private int pageSize = 10;  //每页要显示的记录数
  private int pageNo = 1;     //当前页号
  private int recordCount;    //总记录数 @SuppressWarnings("unchecked")
  public int doStartTag() throws JspException {
   int pageCount = (recordCount + pageSize - 1) / pageSize;  //计算总页数
   
   //拼写要输出到页面的HTML文本
   StringBuilder sb = new StringBuilder();
   sb.append("\r\n<div class=\"pagination\">\r\n");
   if(recordCount == 0){
    sb.append("<strong>没有可显示的项目</strong>\r\n");
   }else{
    //页号越界处理
    if(pageNo > pageCount){  pageNo = pageCount; }
    if(pageNo < 1){  pageNo = 1; }
    
    sb.append("<form method=\"post\" action=\"\" ")
     .append("name=\"qPagerForm\">\r\n");
    
    //获取请求中的所有参数
    HttpServletRequest request = (HttpServletRequest) pageContext
      .getRequest();
    Enumeration<String> enumeration = request.getParameterNames();
    String name = null;  //参数名
    String value = null; //参数值
    //把请求中的所有参数当作隐藏表单域
    while (enumeration.hasMoreElements()) {
     name =  enumeration.nextElement();
     value = request.getParameter(name);
     // 去除页号
     if (name.equals("pageNo")) {
      if (null != value && !"".equals(value)) {
       pageNo = Integer.parseInt(value);
      }
      continue;
     }
     sb.append("<input type=\"hidden\" name=\"")
       .append(name)
       .append("\" value=\"")
       .append(value)
       .append("\"/>\r\n");
    }
  
    // 把当前页号设置成请求参数
    sb.append("<input type=\"hidden\" name=\"").append("pageNo")
     .append("\" value=\"").append(pageNo).append("\"/>\r\n");
    
    // 输出统计数据
    sb.append(" 共<strong>").append(recordCount)
     .append("</strong>项")
     .append(",<strong>")
     .append(pageCount)
     .append("</strong>页: \r\n");
    
    //上一页处理
    if (pageNo == 1) {
     sb.append("<span class=\"disabled\">« 上一页")
      .append("</span>\r\n");
    } else {
     sb.append("<a href=\"javascript:void(null)\"")
       .append(" οnclick=\"turnOverPage(")
       .append((pageNo - 1))
       .append(")\">« 上一页</a>\r\n");
    }
    
    //如果前面页数过多,显示"..."
    int start = 1; 
    if(this.pageNo > 4){
     start = this.pageNo - 1;
     sb.append("<a href=\"javascript:void(null)\"")
     .append(" οnclick=\"turnOverPage(1)\">1</a>\r\n");
     sb.append("<a href=\"javascript:void(null)\"")
     .append(" οnclick=\"turnOverPage(2)\">2</a>\r\n");
     sb.append("…\r\n");
    }
    //显示当前页附近的页
    int end = this.pageNo + 1;
    if(end > pageCount){
     end = pageCount;
    }
    for(int i = start; i <= end; i++){
     if(pageNo == i){   //当前页号不需要超链接
      sb.append("<span class=\"current\">")
       .append(i)
       .append("</span>\r\n");
     }else{
      sb.append("<a href=\"javascript:void(null)\"")
       .append(" οnclick=\"turnOverPage(")
       .append(i)
       .append(")\">")
       .append(i)
       .append("</a>\r\n");
     }
    }
    //如果后面页数过多,显示"..."
    if(end < pageCount - 2){
     sb.append("…\r\n");
    }
    if(end < pageCount - 1){
     sb.append("<a href=\"javascript:void(null)\"")
     .append(" οnclick=\"turnOverPage(")
     .append(pageCount - 1)
     .append(")\">")
     .append(pageCount - 1)
     .append("</a>\r\n");
    }
    if(end < pageCount){
     sb.append("<a href=\"javascript:void(null)\"")
     .append(" οnclick=\"turnOverPage(")
     .append(pageCount)
     .append(")\">")
     .append(pageCount)
     .append("</a>\r\n"); 
    }
    
    //下一页处理
    if (pageNo == pageCount) {
     sb.append("<span class=\"disabled\">下一页 »")
      .append("</span>\r\n");
    } else {
     sb.append("<a href=\"javascript:void(null)\"")
      .append(" οnclick=\"turnOverPage(")
      .append((pageNo + 1))
      .append(")\">下一页 »</a>\r\n");
    }
    sb.append("</form>\r\n");
  
    // 生成提交表单的JS
    sb.append("<script language=\"javascript\">\r\n");
    sb.append("  function turnOverPage(no){\r\n");
    sb.append("    var qForm=document.qPagerForm;\r\n");
    sb.append("    if(no>").append(pageCount).append("){");
    sb.append("no=").append(pageCount).append(";}\r\n");
    sb.append("    if(no<1){no=1;}\r\n");
    sb.append("    qForm.pageNo.value=no;\r\n");
    sb.append("    qForm.action=\"").append(url).append("\";\r\n");
    sb.append("    qForm.submit();\r\n");
    sb.append("  }\r\n");
    sb.append("</script>\r\n");
   }
   sb.append("</div>\r\n");
   
   //把生成的HTML输出到响应中
   try {
    pageContext.getOut().println(sb.toString());
   } catch (IOException e) {
    throw new JspException(e);
   }
   return SKIP_BODY;  //本标签主体为空,所以直接跳过主体
  } public void setUrl(String url) {
   this.url = url;
  }
  public void setPageSize(int pageSize) {
   this.pageSize = pageSize;
  }
  public void setPageNo(int pageNo) {
   this.pageNo = pageNo;
  }
  public void setRecordCount(int recordCount) {
   this.recordCount = recordCount;
  }
 }3、
/**
  *  ClassName: TestPagerTagServlet.java
  *  created on 2009-03-20
  *  Copyrights 2009 qjyong All rights reserved.
  *  EMail: qjyong@gmail.com  */
 package web.Servlet;import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;/**
  * 测试分页标签使用的Servlet
  * @author qiujy
  */
 public class TestPagerTagServlet extends HttpServlet { private static final long serialVersionUID = -3305996070755176492L;
 private List<String> datas;
  public static final int PAGER_PAGESIZE = 10;
  
  public void init() throws ServletException {
   datas  = new ArrayList<String>();
   for(int i = 1; i <= 123; i++){
    datas.add("字符串" + i);
   }
  } public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
   this.doPost(request, response);
  } public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
   request.setCharacterEncoding("utf-8");
   
   int recordCount = this.datas.size(); //获取总记录数  //获取当前页号
   int pageNo = 1;  
   String pageNoStr = request.getParameter("pageNo");
   if(null != pageNoStr && !pageNoStr.equals("")){
    pageNo = Integer.parseInt(pageNoStr);
   }  //获取分页数据
   int start = (pageNo - 1) * PAGER_PAGESIZE;
   int end = start + PAGER_PAGESIZE;
   if(end > this.datas.size()){
    end = this.datas.size();
   }
   List<String> results = this.datas.subList(start, end);
   
   //把分页数据和分页标签所需要的参数存放到request中
   request.setAttribute("datas", results);
   request.setAttribute("pageNo", pageNo);
   request.setAttribute("pageSize", PAGER_PAGESIZE);
   request.setAttribute("recordCount", recordCount);
   
   //转发请求到JSP页面
   request.getRequestDispatcher("/pager.jsp").forward(request, response);
  }
 }4、
/**
  *  ClassName: PagerTag.java
  *  created on 2009-03-20
  *  Copyrights 2009 qjyong All rights reserved.
  *  EMail: qjyong@gmail.com  */
 package web.tags;import java.io.IOException;
 import java.util.Enumeration;import javax.servlet.http.HttpServletRequest;
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.tagext.TagSupport;/**
  * 分页标签处理类
  */
 public class PagerTag extends TagSupport {
  private static final long serialVersionUID = 5729832874890369508L;
  private String url;         //请求URI
  private int pageSize = 10;  //每页要显示的记录数
  private int pageNo = 1;     //当前页号
  private int recordCount;    //总记录数 @SuppressWarnings("unchecked")
  public int doStartTag() throws JspException {
   int pageCount = (recordCount + pageSize - 1) / pageSize;  //计算总页数
   
   //拼写要输出到页面的HTML文本
   StringBuilder sb = new StringBuilder();
   sb.append("\r\n<div class=\"pagination\">\r\n");
   if(recordCount == 0){
    sb.append("<strong>没有可显示的项目</strong>\r\n");
   }else{
    //页号越界处理
    if(pageNo > pageCount){  pageNo = pageCount; }
    if(pageNo < 1){  pageNo = 1; }
    
    sb.append("<form method=\"post\" action=\"\" ")
     .append("name=\"qPagerForm\">\r\n");
    
    //获取请求中的所有参数
    HttpServletRequest request = (HttpServletRequest) pageContext
      .getRequest();
    Enumeration<String> enumeration = request.getParameterNames();
    String name = null;  //参数名
    String value = null; //参数值
    //把请求中的所有参数当作隐藏表单域
    while (enumeration.hasMoreElements()) {
     name =  enumeration.nextElement();
     value = request.getParameter(name);
     // 去除页号
     if (name.equals("pageNo")) {
      if (null != value && !"".equals(value)) {
       pageNo = Integer.parseInt(value);
      }
      continue;
     }
     sb.append("<input type=\"hidden\" name=\"")
       .append(name)
       .append("\" value=\"")
       .append(value)
       .append("\"/>\r\n");
    }
  
    // 把当前页号设置成请求参数
    sb.append("<input type=\"hidden\" name=\"").append("pageNo")
     .append("\" value=\"").append(pageNo).append("\"/>\r\n");
    
    // 输出统计数据
    sb.append(" 共<strong>").append(recordCount)
     .append("</strong>项")
     .append(",<strong>")
     .append(pageCount)
     .append("</strong>页: \r\n");
    
    //上一页处理
    if (pageNo == 1) {
     sb.append("<span class=\"disabled\">« 上一页")
      .append("</span>\r\n");
    } else {
     sb.append("<a href=\"javascript:void(null)\"")
       .append(" οnclick=\"turnOverPage(")
       .append((pageNo - 1))
       .append(")\">« 上一页</a>\r\n");
    }
    
    //如果前面页数过多,显示"..."
    int start = 1; 
    if(this.pageNo > 4){
     start = this.pageNo - 1;
     sb.append("<a href=\"javascript:void(null)\"")
     .append(" οnclick=\"turnOverPage(1)\">1</a>\r\n");
     sb.append("<a href=\"javascript:void(null)\"")
     .append(" οnclick=\"turnOverPage(2)\">2</a>\r\n");
     sb.append("…\r\n");
    }
    //显示当前页附近的页
    int end = this.pageNo + 1;
    if(end > pageCount){
     end = pageCount;
    }
    for(int i = start; i <= end; i++){
     if(pageNo == i){   //当前页号不需要超链接
      sb.append("<span class=\"current\">")
       .append(i)
       .append("</span>\r\n");
     }else{
      sb.append("<a href=\"javascript:void(null)\"")
       .append(" οnclick=\"turnOverPage(")
       .append(i)
       .append(")\">")
       .append(i)
       .append("</a>\r\n");
     }
    }
    //如果后面页数过多,显示"..."
    if(end < pageCount - 2){
     sb.append("…\r\n");
    }
    if(end < pageCount - 1){
     sb.append("<a href=\"javascript:void(null)\"")
     .append(" οnclick=\"turnOverPage(")
     .append(pageCount - 1)
     .append(")\">")
     .append(pageCount - 1)
     .append("</a>\r\n");
    }
    if(end < pageCount){
     sb.append("<a href=\"javascript:void(null)\"")
     .append(" οnclick=\"turnOverPage(")
     .append(pageCount)
     .append(")\">")
     .append(pageCount)
     .append("</a>\r\n"); 
    }
    
    //下一页处理
    if (pageNo == pageCount) {
     sb.append("<span class=\"disabled\">下一页 »")
      .append("</span>\r\n");
    } else {
     sb.append("<a href=\"javascript:void(null)\"")
      .append(" οnclick=\"turnOverPage(")
      .append((pageNo + 1))
      .append(")\">下一页 »</a>\r\n");
    }
    sb.append("</form>\r\n");
  
    // 生成提交表单的JS
    sb.append("<script language=\"javascript\">\r\n");
    sb.append("  function turnOverPage(no){\r\n");
    sb.append("    var qForm=document.qPagerForm;\r\n");
    sb.append("    if(no>").append(pageCount).append("){");
    sb.append("no=").append(pageCount).append(";}\r\n");
    sb.append("    if(no<1){no=1;}\r\n");
    sb.append("    qForm.pageNo.value=no;\r\n");
    sb.append("    qForm.action=\"").append(url).append("\";\r\n");
    sb.append("    qForm.submit();\r\n");
    sb.append("  }\r\n");
    sb.append("</script>\r\n");
   }
   sb.append("</div>\r\n");
   
   //把生成的HTML输出到响应中
   try {
    pageContext.getOut().println(sb.toString());
   } catch (IOException e) {
    throw new JspException(e);
   }
   return SKIP_BODY;  //本标签主体为空,所以直接跳过主体
  } public void setUrl(String url) {
   this.url = url;
  }
  public void setPageSize(int pageSize) {
   this.pageSize = pageSize;
  }
  public void setPageNo(int pageNo) {
   this.pageNo = pageNo;
  }
  public void setRecordCount(int recordCount) {
   this.recordCount = recordCount;
  }
 }TLD:<?xml version="1.0" encoding="UTF-8"?>
 <taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd">
  <tlib-version>0.9</tlib-version>
  <short-name>q</short-name>
  <uri></uri>
  
  <!-- 自定义标签的描述信息 -->
  <tag>
   <!-- 标签名 -->
   <name>pager</name>
   <!-- 对应的标签处理类全限定名 -->
   <tag-class>com.qiujy.web.tags.PagerTag</tag-class>
   <!-- 标签主体的类型 -->
   <body-content>empty</body-content>
   <!-- 当前页号属性的描述信息 -->
   <attribute>
    <!-- 属性名 -->
    <name>pageNo</name>
    <!-- 该属性是否为必要的 -->
    <required>true</required>
    <!-- 属性值是否可以在JSP运行时期动态产生 -->
    <rtexprvalue>true</rtexprvalue>
    <!-- 属性的数据类型 -->
    <type>int</type>
   </attribute>
   <!-- 总记录数属性的描述信息 -->
   <attribute>
    <name>recordCount</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
    <type>int</type>
   </attribute>
   <!-- 总页数属性的描述信息 -->
   <attribute>
    <name>pageSize</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
    <type>int</type>
   </attribute>
   <!-- 分页标签要跳转的URI属性的描述信息 -->
   <attribute>
    <name>url</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.String</type>
   </attribute>
  </tag>
 </taglib>