说明:曾经在网上看过花样繁多的分页,很多都号称如何通用,但很多时候往往不尽如人意:有在分页类中还加入URL地址信息的,有在分页类中还进行分页动作处理(此动作完全属于操作数据库方面的事情)的。现在好了,经本人总结与提炼:
无论你是否自己手动分页,还是借助了框架进行分页。此工具类都可以帮助你达到稳定的分页效果(包括导航页码功能),而且使用方法也相对简单:好了,废话少说,代码如下:package cn.asiatelecom.wlan.dao;import java.util.List;/**
 * 用于分页的工具类
 * @author 莫取网名
 */
public class Pager<T> { private List<T> list; //对象记录结果集
private int total = 0; // 总记录数
private int limit = 20; // 每页显示记录数
private int pages = 1; // 总页数
private int pageNumber = 1; // 当前页

private boolean isFirstPage=false;        //是否为第一页
    private boolean isLastPage=false;         //是否为最后一页
    private boolean hasPreviousPage=false;   //是否有前一页
    private boolean hasNextPage=false;       //是否有下一页
    
private int navigatePages=8; //导航页码数
private int[] navigatePageNumbers;  //所有导航页号

public Pager(int total, int pageNumber) {
init(total, pageNumber, limit);
}

public Pager(int total, int pageNumber, int limit) {
init(total, pageNumber, limit);
}

private void init(int total, int pageNumber, int limit){
//设置基本参数
this.total=total;
this.limit=limit;
this.pages=(this.total-1)/this.limit+1;

//根据输入可能错误的当前号码进行自动纠正
if(pageNumber<1){
this.pageNumber=1;
}else if(pageNumber>this.pages){
this.pageNumber=this.pages;
}else{
this.pageNumber=pageNumber;
}

//基本参数设定之后进行导航页面的计算
calcNavigatePageNumbers();

//以及页面边界的判定
judgePageBoudary();
}

/**
 * 计算导航页
 */
private void calcNavigatePageNumbers(){
//当总页数小于或等于导航页码数时
if(pages<=navigatePages){
navigatePageNumbers=new int[pages];
for(int i=0;i<pages;i++){
navigatePageNumbers[i]=i+1;
}
}else{ //当总页数大于导航页码数时
navigatePageNumbers=new int[navigatePages];
int startNum=pageNumber-navigatePages/2;
int endNum=pageNumber+navigatePages/2;

if(startNum<1){
startNum=1;
//(最前navPageCount页
for(int i=0;i<navigatePages;i++){
navigatePageNumbers[i]=startNum++;
}
}else if(endNum>pages){
endNum=pages;
//最后navPageCount页
for(int i=navigatePages-1;i>=0;i--){
navigatePageNumbers[i]=endNum--;
}
}else{
//所有中间页
for(int i=0;i<navigatePages;i++){
navigatePageNumbers[i]=startNum++;
}
}
}
} /**
 * 判定页面边界
 */
private void judgePageBoudary(){
isFirstPage = pageNumber == 1;
isLastPage = pageNumber == pages && pageNumber!=1;
hasPreviousPage = pageNumber!=1;
hasNextPage = pageNumber!=pages;
}


public void setList(List<T> list) {
this.list = list;
} /**
 * 得到当前页的内容
 * @return {List}
 */
public List<T> getList() {
return list;
} /**
 * 得到记录总数
 * @return {int}
 */
public int getTotal() {
return total;
} /**
 * 得到每页显示多少条记录
 * @return {int}
 */
public int getLimit() {
return limit;
} /**
 * 得到页面总数
 * @return {int}
 */
public int getPages() {
return pages;
} /**
 * 得到当前页号
 * @return {int}
 */
public int getPageNumber() {
return pageNumber;
}
/**
 * 得到所有导航页号 
 * @return {int[]}
 */
public int[] getNavigatePageNumbers() {
return navigatePageNumbers;
} public boolean isFirstPage() {
return isFirstPage;
} public boolean isLastPage() {
return isLastPage;
} public boolean hasPreviousPage() {
return hasPreviousPage;
} public boolean hasNextPage() {
return hasNextPage;
} public String toString(){
String str=new String();
str= "[" +
"total="+total+
",pages="+pages+
",pageNumber="+pageNumber+
",limit="+limit+
//",navigatePages="+navigatePages+
",isFirstPage="+isFirstPage+
",isLastPage="+isLastPage+
",hasPreviousPage="+hasPreviousPage+
",hasNextPage="+hasNextPage+
",navigatePageNumbers=";
int len=navigatePageNumbers.length;
if(len>0)str+=(navigatePageNumbers[0]);
for(int i=1;i<len;i++){
str+=(" "+navigatePageNumbers[i]);
}
//sb+=",list="+list;
str+="]";
return str;
}
}PS: 此类在构造时最多只要3个参数。由于容错需要,list的setter得进行后继处理。
假设你使用了Hibernate,核心代码如下:int totalCount=Integer.valueOf(queryCount.uniqueResult().toString());
Pager pager=new Pager<T>(totalCount, pageNumber,limit);
queryList.setFirstResult((pager.getPageNumber()-1)*limit); //容错处理
queryList.setMaxResults(limit);
pager.setList(queryList.list());
return pager;
对于用其他方式分页的人,同样可以复用Pager类。
最后,欢迎大家拍砖!

解决方案 »

  1.   

    (⊙o⊙)…
    toString()方法用new个String() 拼接那么多字符串 效率差呀
      

  2.   

    省事了
    Pager中添加个方法public int getFirstResultCount(){
          return  (getPageNumber()-1)*limit;
    }会更方便只是查询应该不会涉及到事务处理,楼主也可以吧querylist放到pager类中进行处理。不过楼主为什么把类设计成  Pager<T>??这个怎么用呢
      

  3.   


    也不多啊。我把多的内容都注释了。Pager<T>只是多了个范型罢了。
    querylist放到Pager类中处理,则增加了hibernate与它的耦合。Pager做为一个工具类,应该与数据库无关,也应该与框架无关!
      

  4.   

    有人说toString方法有效率问题,那就改成StringBuffer就行了。
    顺便对页面边界判定进行了一下微调,完整内容如下:
    package cn.asiatelecom.wlan.dao;import java.util.List;/**
     * 用于分页的工具类
     * @author 莫取网名
     */
    public class Pager<T> { private List<T> list; //对象记录结果集
    private int total = 0; // 总记录数
    private int limit = 20; // 每页显示记录数
    private int pages = 1; // 总页数
    private int pageNumber = 1; // 当前页

    private boolean isFirstPage=false;        //是否为第一页
             private boolean isLastPage=false;         //是否为最后一页
             private boolean hasPreviousPage=false;   //是否有前一页
             private boolean hasNextPage=false;       //是否有下一页
        
    private int navigatePages=8; //导航页码数
    private int[] navigatePageNumbers;  //所有导航页号

    public Pager(int total, int pageNumber) {
    init(total, pageNumber, limit);
    }

    public Pager(int total, int pageNumber, int limit) {
    init(total, pageNumber, limit);
    }

    private void init(int total, int pageNumber, int limit){
    //设置基本参数
    this.total=total;
    this.limit=limit;
    this.pages=(this.total-1)/this.limit+1;

    //根据输入可能错误的当前号码进行自动纠正
    if(pageNumber<1){
    this.pageNumber=1;
    }else if(pageNumber>this.pages){
    this.pageNumber=this.pages;
    }else{
    this.pageNumber=pageNumber;
    }

    //基本参数设定之后进行导航页面的计算
    calcNavigatePageNumbers();

    //以及页面边界的判定
    judgePageBoudary();
    }

    /**
     * 计算导航页
     */
    private void calcNavigatePageNumbers(){
    //当总页数小于或等于导航页码数时
    if(pages<=navigatePages){
    navigatePageNumbers=new int[pages];
    for(int i=0;i<pages;i++){
    navigatePageNumbers[i]=i+1;
    }
    }else{ //当总页数大于导航页码数时
    navigatePageNumbers=new int[navigatePages];
    int startNum=pageNumber-navigatePages/2;
    int endNum=pageNumber+navigatePages/2;

    if(startNum<1){
    startNum=1;
    //(最前navigatePages页
    for(int i=0;i<navigatePages;i++){
    navigatePageNumbers[i]=startNum++;
    }
    }else if(endNum>pages){
    endNum=pages;
    //最后navigatePages页
    for(int i=navigatePages-1;i>=0;i--){
    navigatePageNumbers[i]=endNum--;
    }
    }else{
    //所有中间页
    for(int i=0;i<navigatePages;i++){
    navigatePageNumbers[i]=startNum++;
    }
    }
    }
    } /**
     * 判定页面边界
     */
    private void judgePageBoudary(){
    isFirstPage = pageNumber == 1;
    isLastPage = pageNumber == pages && pageNumber!=1;
    hasPreviousPage = pageNumber > 1;
    hasNextPage = pageNumber < pages;
    }


    public void setList(List<T> list) {
    this.list = list;
    } /**
     * 得到当前页的内容
     * @return {List}
     */
    public List<T> getList() {
    return list;
    } /**
     * 得到记录总数
     * @return {int}
     */
    public int getTotal() {
    return total;
    } /**
     * 得到每页显示多少条记录
     * @return {int}
     */
    public int getLimit() {
    return limit;
    } /**
     * 得到页面总数
     * @return {int}
     */
    public int getPages() {
    return pages;
    } /**
     * 得到当前页号
     * @return {int}
     */
    public int getPageNumber() {
    return pageNumber;
    }
    /**
     * 得到所有导航页号 
     * @return {int[]}
     */
    public int[] getNavigatePageNumbers() {
    return navigatePageNumbers;
    } public boolean isFirstPage() {
    return isFirstPage;
    } public boolean isLastPage() {
    return isLastPage;
    } public boolean hasPreviousPage() {
    return hasPreviousPage;
    } public boolean hasNextPage() {
    return hasNextPage;
    } public String toString(){
    StringBuffer sb=new StringBuffer();
    sb.append("[")
    .append("total=").append(total)
    .append(",pages=").append(pages)
    .append(",pageNumber=").append(pageNumber)
    .append(",limit=").append(limit)
    .append(",isFirstPage=").append(isFirstPage)
    .append(",isLastPage=").append(isLastPage)
    .append(",hasPreviousPage=").append(hasPreviousPage)
    .append(",hasNextPage=").append(hasNextPage)
    .append(",navigatePageNumbers=");
    int len=navigatePageNumbers.length;
    if(len>0)sb.append(navigatePageNumbers[0]);
    for(int i=1;i<len;i++){
    sb.append(" "+navigatePageNumbers[i]);
    }
    sb.append(",list.size="+list.size());
    sb.append("]");
    return sb.toString();
    }
    }
      

  5.   

    有人说toString方法有效率问题,那就改成StringBuffer就行了。
    顺便对页面边界判定进行了一下微调,完整内容如下:package test.dao;import java.util.List;/**
     * 用于分页的工具类
     * @author 莫取网名
     */
    public class Pager<T> { private List<T> list; //对象记录结果集
    private int total = 0; // 总记录数
    private int limit = 20; // 每页显示记录数
    private int pages = 1; // 总页数
    private int pageNumber = 1; // 当前页

    private boolean isFirstPage=false;        //是否为第一页
             private boolean isLastPage=false;         //是否为最后一页
             private boolean hasPreviousPage=false;   //是否有前一页
             private boolean hasNextPage=false;       //是否有下一页
        
    private int navigatePages=8; //导航页码数
    private int[] navigatePageNumbers;  //所有导航页号

    public Pager(int total, int pageNumber) {
    init(total, pageNumber, limit);
    }

    public Pager(int total, int pageNumber, int limit) {
    init(total, pageNumber, limit);
    }

    private void init(int total, int pageNumber, int limit){
    //设置基本参数
    this.total=total;
    this.limit=limit;
    this.pages=(this.total-1)/this.limit+1;

    //根据输入可能错误的当前号码进行自动纠正
    if(pageNumber<1){
    this.pageNumber=1;
    }else if(pageNumber>this.pages){
    this.pageNumber=this.pages;
    }else{
    this.pageNumber=pageNumber;
    }

    //基本参数设定之后进行导航页面的计算
    calcNavigatePageNumbers();

    //以及页面边界的判定
    judgePageBoudary();
    }

    /**
     * 计算导航页
     */
    private void calcNavigatePageNumbers(){
    //当总页数小于或等于导航页码数时
    if(pages<=navigatePages){
    navigatePageNumbers=new int[pages];
    for(int i=0;i<pages;i++){
    navigatePageNumbers[i]=i+1;
    }
    }else{ //当总页数大于导航页码数时
    navigatePageNumbers=new int[navigatePages];
    int startNum=pageNumber-navigatePages/2;
    int endNum=pageNumber+navigatePages/2;

    if(startNum<1){
    startNum=1;
    //(最前navigatePages页
    for(int i=0;i<navigatePages;i++){
    navigatePageNumbers[i]=startNum++;
    }
    }else if(endNum>pages){
    endNum=pages;
    //最后navigatePages页
    for(int i=navigatePages-1;i>=0;i--){
    navigatePageNumbers[i]=endNum--;
    }
    }else{
    //所有中间页
    for(int i=0;i<navigatePages;i++){
    navigatePageNumbers[i]=startNum++;
    }
    }
    }
    } /**
     * 判定页面边界
     */
    private void judgePageBoudary(){
    isFirstPage = pageNumber == 1;
    isLastPage = pageNumber == pages && pageNumber!=1;
    hasPreviousPage = pageNumber > 1;
    hasNextPage = pageNumber < pages;
    }


    public void setList(List<T> list) {
    this.list = list;
    } /**
     * 得到当前页的内容
     * @return {List}
     */
    public List<T> getList() {
    return list;
    } /**
     * 得到记录总数
     * @return {int}
     */
    public int getTotal() {
    return total;
    } /**
     * 得到每页显示多少条记录
     * @return {int}
     */
    public int getLimit() {
    return limit;
    } /**
     * 得到页面总数
     * @return {int}
     */
    public int getPages() {
    return pages;
    } /**
     * 得到当前页号
     * @return {int}
     */
    public int getPageNumber() {
    return pageNumber;
    }
    /**
     * 得到所有导航页号 
     * @return {int[]}
     */
    public int[] getNavigatePageNumbers() {
    return navigatePageNumbers;
    } public boolean isFirstPage() {
    return isFirstPage;
    } public boolean isLastPage() {
    return isLastPage;
    } public boolean hasPreviousPage() {
    return hasPreviousPage;
    } public boolean hasNextPage() {
    return hasNextPage;
    } public String toString(){
    StringBuffer sb=new StringBuffer();
    sb.append("[")
    .append("total=").append(total)
    .append(",pages=").append(pages)
    .append(",pageNumber=").append(pageNumber)
    .append(",limit=").append(limit)
    .append(",isFirstPage=").append(isFirstPage)
    .append(",isLastPage=").append(isLastPage)
    .append(",hasPreviousPage=").append(hasPreviousPage)
    .append(",hasNextPage=").append(hasNextPage)
    .append(",navigatePageNumbers=");
    int len=navigatePageNumbers.length;
    if(len>0)sb.append(navigatePageNumbers[0]);
    for(int i=1;i<len;i++){
    sb.append(" "+navigatePageNumbers[i]);
    }
    sb.append(",list.size="+list.size());
    sb.append("]");
    return sb.toString();
    }
    }
      

  6.   

    你能不能把用法写下,就更方便了你的toString没有拼html标签我用的那个工具类直接就可以在jsp页面用pageTool了 
    不过我还是觉得不好用
      

  7.   


    还是那句话,做为一个工具类,它应该与数据库无关,也应该与框架无关,同时也应该要和展现层无关。
    也就是说,无论你是自己手工分页,也无论你是否使用框架,也不管你是用页面来展现,还是用SWING来展现。它都可以通用。关于用法:
    不管怎么样,分页的最终实效是反应在数据库中,则非内存之中(即一般的假分页,一次全查出,再挑选部分记录)。而物理分页无非就2个参数:
    1.要查询的第一条记录
    2.从查询的第一条记录开始的N条记录。然而程序的最终用户从展现层面只知道要看第几页,一页看多少条。
    因此,pageNumber和limit参数便可得知。
    有了用户传来的pageNumber和limit,那么,物理分页的那2个必备参数便也可知了。
    只不过要查询的第一条记录这个参数需要自己简单计算一下。手工分页和使用了ORM框架分页的不同在于,前者得自己拼接SQL语句并设置好2个必备参数,后者则直接调用框架提供的相关函数进行参数传递即可完成。但它们的共同点是形式参数是一致的。至于你说未在Pager类中拼接HTML标签的情况,我只能表示遗憾。在下遗憾的是:咱们思考问题的角度并不太一样。因为在下认为:你在Pager类中加入html标签是完成没有必要的,又或许,你觉得直接在得到某一页时也在其前面加入一个url前缀或许会更好吧?但是这样增加了Pager类与html语言的耦合度。因为你在前台能得到这个分页类的当前页数等结果,进行URL拼接完全可以在展现层来完成。
    关于用法:其实我在一楼就已经给出了。那我就更补充一下吧,使用步骤如下:
    1).不管是否用了条件查询,首先count出相应的总条数
    2).构造一个Pager类(关于limit参数可根据自身前台进行取舍)
    3).根据构造好的Pager类获取已经自动纠正过的pageNumber参数,-1再乘个limit,做为实际要查询的第一条记录的位置
    4).设置要查从起始位置开始,直到第limit条的所有记录.(如果手工分页,则也有可能第二个参数是结尾记录的位置偏移,具体情况视数据库而定)
    5).将[条件]查询出的list设置入pager对象中并返回.
    6).在展现层通过Servlet或Action或直接拿到这个pager对象即可使用,具体如何拼接url的事情,也应该交由展现层来完成即可。int totalCount=Integer.valueOf(queryCount.uniqueResult().toString());
    Pager pager=new Pager(totalCount, pageNumber,limit);
    queryList.setFirstResult((pager.getPageNumber()-1)*limit); //容错处理
    queryList.setMaxResults(limit);
    pager.setList(queryList.list());
    return pager;上述代码是使用了hibernate的一个简单示例。如果你是手工分页,也按使用步骤来即可。
    我想,我说的已经够明白了吧?
      

  8.   

    6).在展现层通过Servlet或Action或直接拿到这个pager对象即可使用,具体如何拼接url的事情,也应该交由展现层来完成即可。
    ==============
    当然了,分页可以放在dao层来完成,也可以放在Service层来完成。而Servlet或Action则去调用service层的代码。个人认为:分页其实也是一种业务需要,因此,可以将其放在业务层。因为DAO层提供相应的[条件查询]list及[条件]统计count,在业务层完全可以根据自己的需要进行方法调用(只不过需要按既定的步骤来罢了,当然了,很多时候,业务都是有既定的流程步骤的).
      

  9.   

    可以实现 Iterator 接口,这样可以在页面上直接使用 c:forEach 进行迭代了。
      

  10.   

        private boolean isFirstPage=false;        //是否为第一页
        private boolean isLastPage=false;         //是否为最后一页
        private boolean hasPreviousPage=false;   //是否有前一页
        private boolean hasNextPage=false;       //是否有下一页放这四个属性的意义是什么?
      

  11.   

    /**
     * [email protected]
     * @desc 分页通用Bean
     */
    public class PaginationBean {
    public static final String PREVIOUS = "previous";
    public static final String NEXT = "next";
    public static final String FIRST = "first";
    public static final String LAST = "last";
    private int maxinum;
    private int perCount = 10;
    private int pageNum;
    private int pageCount;
    private String operate;
    /**
     * 计算一共多少页并为当前多少页赋值
     *最大记录数
     */
    public void countPageCount(int maxinum) {
    this.maxinum = maxinum;
    // 计算一共多少页
    pageNum = maxinum % perCount == 0 ? maxinum / perCount : maxinum
    / perCount + 1;
    // 为当前页数赋值
    if (PREVIOUS.equals(operate)) {
    pageCount--;
    } else if (NEXT.equals(operate)) {
    pageCount++;
    } else if (FIRST.equals(operate)) {
    pageCount = 1;
    } else if (LAST.equals(operate)) {
    pageCount = pageNum;
    }
    if (pageCount < 1)
    pageCount = 1;
    if (pageCount > this.pageNum)
    pageCount = this.pageNum;
    } public String getOperate() {
    return operate;
    } public void setOperate(String operate) {
    this.operate = operate;
    } public int getMaxinum() {
    return maxinum;
    } public int getPageCount() {
    return pageCount;
    } public int getPageNum() {
    return pageNum;
    } public int getPerCount() {
    return perCount;
    } public void setMaxinum(int maxinum) {
    this.maxinum = maxinum;
    } public void setPageCount(int pageCount) {
    this.pageCount = pageCount;
    } public void setPageNum(int pageNum) {
    this.pageNum = pageNum;
    } public void setPerCount(int perCount) {
    this.perCount = perCount;
    }
    }
    ------------------------------------------------------------------------------------
    运用自定义标签的机制写的分页类,这样无需在每个jsp页面需要重复的写分页标签:
    package com.accp.common.taglib;import javax.servlet.jsp.JspWriter;
    import javax.servlet.jsp.tagext.TagSupport;import com.accp.common.util.PageResult;
    import com.accp.common.web.form.BaseForm;public class PaginationTag extends TagSupport {
    private static final long serialVersionUID = -5904339614208817088L;
    private String form = null;

    public int doEndTag() {
    try {
    BaseForm oForm = null;

    //通过参数获得对应的form对象,并从form对象中获得PageResult对象
    //生成分页标签的html代码,返回给页面显示
    if (form!=null && !"".equals(form.trim())){
    oForm = (BaseForm) pageContext.getRequest().getAttribute(form);
    if (null==oForm){
    oForm = (BaseForm) pageContext.getSession().getAttribute(form);
    }
    if (oForm!=null){
    PageResult pageResult = oForm.getPageResult();
    StringBuffer sb = new StringBuffer();

    sb.append("<div style='float:left;color:#03515d;'>")
    .append("共有 "+pageResult.getRecTotal()+" 条记录,当前第 "+pageResult.getPageNo()+"/"+pageResult.getPageTotal()+" 页")
    .append("</div>")
    .append("<div style='float:right;color:#03515d;clear:both;'>")
    .append("<input type='hidden' name=\"pageResult.pageSize\" value=\""+pageResult.getPageSize()+"\" size=\"3\" />&nbsp;\r\n")
    .append("<a href=\'javascript:page_first();\'><img src='images/first.gif' alt='' width='37' height='15' title='首页' style='border: 0px;cursor:pointer;' /></a> ")
    .append("<a href=\'javascript:page_pre();\'><img src='images/back.gif' alt='' width='43' height='15' title='上一页' style='border: 0px;cursor:pointer;' /></a> ")
    .append("<a href=\'javascript:page_next();\'><img src='images/next.gif' alt='' width='43' height='15' title='下一页' style='border: 0px;cursor:pointer;' /></a> ")
    .append("<a href=\'javascript:page_last();\'><img src='images/last.gif' alt='' width='37' height='15' title='尾页' style='border: 0px;cursor:pointer;' /></a> ")
    .append("转到第 <input type='text' name=\"pageResult.pageNo\" maxlength='4'  style='height:16px; width:32px; border:1px solid #999999' value=\""+pageResult.getPageNo()+"\" size=\"3\"/> 页")
    .append("<a href=\"javascript:page_go();\"><img src='images/go.gif' alt='' width='37' height='15' title='跳转' style='border: 0px;cursor:pointer;' /></a>")
    .append("</div>")
    .append("<input type=\"hidden\" name=\"pageResult.orderBy\"  value=\""+pageResult.getOrderBy()+"\" />\r\n")
    .append("<input type=\"hidden\" name=\"pageResult.sort\"  value=\""+pageResult.getSort()+"\" />\r\n")
    .append("<script>\r\n")
    .append(" var pageTotal = "+pageResult.getPageTotal()+";\r\n")
    .append(" var recTotal = "+pageResult.getRecTotal()+";\r\n")
    .append("</script>\r\n");
    sb.append("<script>\r\n");
    sb.append("function page_go()\r\n")
    .append("{\r\n")
    .append(" page_validate(); \r\n")
    .append(" document.forms[0].submit();\r\n")
    .append("}\r\n")
    .append("function page_first()\r\n")
    .append("{\r\n")
    .append(" document.forms[0].elements[\"pageResult.pageNo\"].value = 1;\r\n")
    .append(" document.forms[0].submit();\r\n")
    .append("}\r\n")
    .append("function page_pre()\r\n")
    .append("{\r\n")
    .append(" var pageNo = document.forms[0].elements[\"pageResult.pageNo\"].value;\r\n")
    .append(" document.forms[0].elements[\"pageResult.pageNo\"].value = parseInt(pageNo) - 1;\r\n")
    .append(" page_validate();\r\n")
    .append(" document.forms[0].submit();\r\n")
    .append("}\r\n")
    .append("function page_next()\r\n")
    .append("{\r\n")
    .append(" var pageNo = document.forms[0].elements[\"pageResult.pageNo\"].value;\r\n")
    .append(" document.forms[0].elements[\"pageResult.pageNo\"].value = parseInt(pageNo) + 1;\r\n")
    .append(" page_validate();\r\n")
    .append(" document.forms[0].submit();\r\n")
    .append("}\r\n")
    .append("function page_last()\r\n")
    .append("{\r\n")
    .append(" document.forms[0].elements[\"pageResult.pageNo\"].value = pageTotal;\r\n")
    .append(" document.forms[0].submit();\r\n")
    .append("}\r\n")
    .append("function page_validate()\r\n")
    .append("{\r\n")
    .append(" var pageNo = document.forms[0].elements[\"pageResult.pageNo\"].value;\r\n")
    .append(" if (pageNo<1)pageNo=1;\r\n")
    .append(" if (pageNo>pageTotal)pageNo=pageTotal;\r\n")
    .append(" document.forms[0].elements[\"pageResult.pageNo\"].value = pageNo;\r\n")
    .append(" var pageSize = document.forms[0].elements[\"pageResult.pageSize\"].value;\r\n")
    .append(" if (pageSize<1)pageSize=1;\r\n")
    .append(" document.forms[0].elements[\"pageResult.pageSize\"].value = pageSize;\r\n")
    .append("}\r\n")
    .append("function order_by(field){\r\n")
    .append(" document.forms[0].elements[\"pageResult.orderBy\"].value = field;\r\n")
    .append(" page_first();\r\n")
    .append("}\r\n");
    sb.append("</script>\r\n");
    JspWriter out = pageContext.getOut();
    out.println(sb.toString());
    }
    }
    } catch (Exception e) {
    }
    return EVAL_PAGE;
    } public String getForm() {
    return form;
    } public void setForm(String form) {
    this.form = form;
    }
    }
      

  12.   

    -----------------------------------
    还得加个配置xml:起名为:tag-common.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
    <taglib>
    <tlibversion>1.2</tlibversion>
    <jspversion>1.1</jspversion>
    <shortname>common</shortname>
    <uri>http://www.jb-aptech.com.cn/taglibs/common</uri>
    <tag>
    <name>pager</name>
    <tagclass>com.accp.common.taglib.PaginationTag</tagclass>
    <bodycontent>empty</bodycontent>
    <attribute>
    <name>form</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    </attribute>
    </tag>
    </taglib>
    -----------------------------------------------------
    最后在jsp页面引入<%@ taglib uri="/WEB-INF/tag-common.tld" prefix="tag"%>在分页出加上: 这样有点不太好看,我还是粘贴一个页面代码吧,易读懂
    <%@ page language="java" pageEncoding="GBK"%>
     <%
      String path = request.getContextPath();
     %>
    <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
    <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
    <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>
    <%@ taglib uri="/WEB-INF/jb-common.tld" prefix="jb"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><html:errors/>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    <title>数据字典管理</title>
    <link rel="shortcut icon" href="<%=path %>/images/favicon.ico" />
    <link rel="stylesheet" type="text/css" href="<%=path %>/css/page.css">
    <script src="<%=path %>/js/validate.js" type="text/javascript"></script>
    <script src="<%=path %>/js/icommon.js" type="text/javascript"></script>
    <script type="text/javascript">
    function doSubmitDel(id){
    if ( window.confirm("确定要删除吗?") ){
    window.location.href = "?o=doDel&id=" + id;
    }
    }
    </script>
    </head>
    <body>
    <html:form action="dict" method="post">
    <html:hidden property="o" value="toList" />
    <table width="100%" border="0" cellpadding="0" cellspacing="0">
      <tr>
        <td class="t1"></td>
        <td class="t2">
         <!--导航位置-->
         <div id="nav">
             当前位置:基础数据 >> 数据字典管理管理
            </div>
            <div align="right">
             <button class="btn" onclick="javascript:doSubmit('toAdd');">新建</button>
    <button class="btn" onclick="javascript:doSubmit('toList');">查询</button>
            </div>
        </td>
        <td class="t3"></td>
      </tr>
      <tr>
        <td class="t4"></td>
        <td>
         <table class="query" border="0" cellPadding="3"
    cellSpacing="0">
    <tr>
    <th>类别</th>
    <td><html:text maxlength="20" property="item.dictType" /></td>
    <th>条目</th>
    <td><html:text maxlength="20" property="item.dictItem" /></td>
    <th>值</th>
    <td><html:text maxlength="20" property="item.dictValue" /></td>
    </tr>
    </table>
         <!--数据展示区-->
         <table class="show" border="0" cellpadding="0" cellspacing="1">
              <!--标题栏-->
      <tr class="title">
                <td width="10%" onclick="order_by('dictId');">编号</td>
    <td width="20%" onclick="order_by('dictType');">类别</td>
    <td width="25%" onclick="order_by('dictItem');">条目</td>
    <td width="25%" onclick="order_by('dictValue');">值</td>
    <td width="10%" onclick="order_by('dictIsEditable');">是否可编辑</td>
    <td width="10%" class="op">操作</td>
              </tr>
              <logic:iterate id="item" name="dictForm" property="pageResult.list"
    type="com.accp.crm.basedate.entity.Dict">
      <!--循环输出数据-->
              <tr class="row" onmouseover="changeto()" onmouseout="changeback()">
                <td><bean:write name="item" property="dictId"/></td>
    <td><bean:write name="item" property="dictType"/></td>
    <td><bean:write name="item" property="dictItem"/></td>
    <td><bean:write name="item" property="dictValue"/></td>
    <td><%
    switch(Byte.parseByte(item.getDictIsEditable().toString())){case 0:out.print("否");break;
    case 1:out.print("是");break;
    default:break;
    }%>&nbsp;
    </td>
    <td>
    <c:if test="${item.dictIsEditable==1}">
    <img onclick="window.location.href='?o=toEdit&amp;id=${item.dictId }';" title="编辑" 
    src="<%=path %>/images/bt_edit.gif" alt="" />  
    <img onclick="doSubmitDel('${item.dictId }');" title="删除"
    src="<%=path %>/images/bt_del.gif" alt="" />
    </c:if>
    &nbsp;
    </td>
              </tr>
              </logic:iterate>
              <logic:empty name="dictForm" property="pageResult.list">
    <tr class="row">
    <td colspan="6">没有记录</td>
    </tr>
      </logic:empty>
            </table>
        </td>
        <td class="t5"></td>
      </tr>
      <tr>
        <td class="t6"></td>
        <td class="t7">
            <!--页数导航-->
            <jb:pager form="dictForm" />
        </td>
        <td class="t8"></td>
      </tr>
    </table>
    <script>
    build_validate("item.dictType","条件不能包含特殊字符","Patrn");
    build_validate("item.dictItem","条件不能包含特殊字符","Patrn");
    build_validate("item.dictValue","条件不能包含特殊字符","Patrn");
    </script>
    </html:form>
    </body>
    </html>
    ---------------------
    ok 好了,次分页不论项目,都可以通用,无需大的变动
      

  13.   

    TO 24&25楼的兄弟,在下只想问一句:如果展现层不用页面,改用SWING,你的这一段自定义标签库还有用吗?
      

  14.   

    没用了,当然要用EXT的话,也同样不用而且功能还强大,标题排序,单元格数据修改都可以实现
      

  15.   


    EXT也是有不足之处的。除非所做的系统是在局域网中使用的,否则的话,加载东西太多,会影响响应速度。
    同时EXT也不具备导航页码的功能。而借助PAGER类,同样能在有EXT中的系统中使用。利用JSON方式进行即可。
      

  16.   

    是的json是个不错的东西,轻量级的数据交互东西,数组到json再到数组
      

  17.   

    应该是控制翻页按钮disabled属性的。
      

  18.   

    顶个  这东西到时用着了 来copy一下
      

  19.   

    思路可取。感谢楼主
    用Page类来封装list,我之前怎么没想到这一点,搞到我要分页的时候,又要返回list又要返回分页参数挺郁闷的啊。。
      

  20.   

    用的时候,可以再进行一下包装,实现数据的自动装载,当然,这必然要与DAO层耦合了。。
      

  21.   

    参考一下。顺便分享一下小弟写的纯js脚本分页
    http://topic.csdn.net/u/20101223/16/5a623402-66c1-40ce-bce4-c64d3531b295.html
      

  22.   

    可惜是Java的,要是C#的就好了!
      

  23.   


    JAVA和C#本身区别不大。思路基本可以复制。
      

  24.   

    分页在java或c#代码实现都差不多,关键大多不一样的地方是在前台页面。
      

  25.   

    public String toString()方法web获取到如何使用呢。。还要写算法来提取参数?