欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SSM框架利用自定义标签分页

程序员文章站 2022-06-22 11:54:33
分页通常是令人头疼的一件事,然而,这里将介绍一种新方法 这是一种巧妙地方法: 后端自定义JSP标签,这样在前端方面做分页会变得很简单 这里需要一种新技术:自定义标签 举例:在JSP动态页面技术中:我们都知道有c标签: 只需要在头导入: 使用示例: 这些都是基本知识: 那么是否可以自定义标签呢? 可以 ......

分页通常是令人头疼的一件事,然而,这里将介绍一种新方法

这是一种巧妙地方法:

后端自定义jsp标签,这样在前端方面做分页会变得很简单

这里需要一种新技术:自定义标签

 

举例:在jsp动态页面技术中:我们都知道有c标签:

只需要在头导入:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

使用示例:

<c:foreach items="${industry}" var="item">
    <option value="${item.id}"
            <c:if test="${item.id == xxx}"> 
              xxx
            </c:if>>${item.item_name }
        </option>
</c:foreach>

 

这些都是基本知识:

那么是否可以自定义标签呢?

可以:我随便写一堆:yiqing标签库,uri随意写为:yiqing is handsome

<%@ taglib prefix="yiqing" uri="yiqingishandsome"%>

然而,如果你在jsp页面搞这么一个东西,会红线报错

 

如何让他不报错呢?

可以:写一个tld文件:

commons.tld:

<?xml version="1.0" encoding="utf-8" ?>
<!doctype taglib
  public "-//sun microsystems, inc.//dtd jsp tag library 1.2//en"
  "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
    <tlib-version>2.0</tlib-version>
    <jsp-version>1.2</jsp-version>
    <short-name>common</short-name>
    <uri>yiqingishandsome</uri>
    <display-name>common tag</display-name>
    <description>common tag library</description>

    <tag>
        <name>page</name>
        <tag-class>org.dreamtech.common.utils.navigationtag</tag-class>
        <body-content>jsp</body-content>
        <description>create navigation for paging</description>
        <attribute>
            <name>bean</name>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>number</name>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>url</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

 

这里要保证两处的uri一致,name属性是标签库内的page标签

下边的attribute配置是为了后面使用该标签库来实现分页的

这里有三个属性:先解释一下:

bean和number是可以选择的参数,具体意义下面介绍

url是必须的参数:分页跳转的url(交给哪个controller来处理)

 

这里还看到一个class属性:这个就是核心的类,处理标签分页功能的类:

注意:

1.这里的这个分页核心类是根据bootstrap前端框架编写的,其他前端框架可能不适用

   不过,只需要略修改下代码就可以通用

2.需要有tomcat的支持包(相当于废话)

package org.dreamtech.common.utils;

import java.io.ioexception;
import java.util.map;

import javax.servlet.http.httpservletrequest;
import javax.servlet.jsp.jspexception;
import javax.servlet.jsp.jspwriter;
import javax.servlet.jsp.tagext.tagsupport;


/**
 * 显示格式 上一页 1 2 3 4 5 下一页
 */
public class navigationtag extends tagsupport {
    static final long serialversionuid = 2372405317744358833l;
    
    /**
     * request 中用于保存page<e> 对象的变量名,默认为“page”
     */
    private string bean = "page";
    
    /**
     * 分页跳转的url地址,此属性必须
     */
    private string url = null;
    
    /**
     * 显示页码数量
     */
    private int number = 5;
    
    @override
    public int dostarttag() throws jspexception {
        jspwriter writer = pagecontext.getout();
        httpservletrequest request = (httpservletrequest) pagecontext.getrequest();
        page page = (page)request.getattribute(bean); 
        if (page == null) 
            return skip_body;
        url = resolveurl(url, pagecontext);
        try {
            //计算总页数
            int pagecount = page.gettotal() / page.getsize();
            if (page.gettotal() % page.getsize() > 0) {
                pagecount++;
            }
            writer.print("<nav><ul class=\"pagination\">");
            //显示“上一页”按钮
            if (page.getpage() > 1) {
                string preurl = append(url, "page", page.getpage() - 1);
                preurl = append(preurl, "rows", page.getsize());
                writer.print("<li><a href=\"" + preurl + "\">上一页</a></li>");
            } else {
                writer.print("<li class=\"disabled\"><a href=\"#\">上一页</a></li>");
            }
            //显示当前页码的前2页码和后两页码 
            //若1 则 1 2 3 4 5, 若2 则 1 2 3 4 5, 若3 则1 2 3 4 5,
            //若4 则 2 3 4 5 6 ,若10  则 8 9 10 11 12
            int indexpage = (page.getpage() - 2 > 0)? page.getpage() - 2 : 1;  
            for(int i=1; i <= number && indexpage <= pagecount; indexpage++, i++) {
                if(indexpage == page.getpage()) {
                    writer.print( "<li class=\"active\"><a href=\"#\">"+indexpage+"<span class=\"sr-only\">(current)</span></a></li>");
                    continue;
                }
                string pageurl  = append(url, "page", indexpage);
                pageurl = append(pageurl, "rows", page.getsize());
                writer.print("<li><a href=\"" + pageurl + "\">"+ indexpage +"</a></li>");
            }
            //显示“下一页”按钮
            if (page.getpage() < pagecount) {
                string nexturl  = append(url, "page", page.getpage() + 1);
                nexturl = append(nexturl, "rows", page.getsize());
                writer.print("<li><a href=\"" + nexturl + "\">下一页</a></li>");
            } else {
                writer.print("<li class=\"disabled\"><a href=\"#\">下一页</a></li>");
            }
            writer.print("</nav>");
        } catch (ioexception e) {
            e.printstacktrace();
        }
        return skip_body;
    }
    
    private string append(string url, string key, int value) {

        return append(url, key, string.valueof(value));
    }
    
    /**
     * 为url 参加参数对儿
     * 
     * @param url
     * @param key
     * @param value
     * @return
     */
    private string append(string url, string key, string value) {
        if (url == null || url.trim().length() == 0) {
            return "";
        }

        if (url.indexof("?") == -1) {
            url = url + "?" + key + "=" + value;
        } else {
            if(url.endswith("?")) {
                url = url + key + "=" + value;
            } else {
                url = url + "&amp;" + key + "=" + value;
            }
        }
        
        return url;
    }
    
    /**
     * 为url 添加翻页请求参数
     * 
     * @param url
     * @param pagecontext
     * @return
     * @throws javax.servlet.jsp.jspexception
     */
    private string resolveurl(string url, javax.servlet.jsp.pagecontext pagecontext) throws jspexception{
        //urlsupport.resolveurl(url, context, pagecontext)
        map params = pagecontext.getrequest().getparametermap();
        for (object key:params.keyset()) {
            if ("page".equals(key) || "rows".equals(key)) continue;
            object value = params.get(key);
            if (value == null) continue;
            if (value.getclass().isarray()) {
                url = append(url, key.tostring(), ((string[])value)[0]);
            } else if (value instanceof string) {
                url = append(url, key.tostring(), value.tostring());
            }
        }
        return url;
    }
    
    

    /**
     * @return the bean
     */
    public string getbean() {
        return bean;
    }

    /**
     * @param bean the bean to set
     */
    public void setbean(string bean) {
        this.bean = bean;
    }

    /**
     * @return the url
     */
    public string geturl() {
        return url;
    }

    /**
     * @param url the url to set
     */
    public void seturl(string url) {
        this.url = url;
    }

    public void setnumber(int number) {
        this.number = number;
    }
    
}

 

 

当然,也需要有个分页page实体类:

package org.dreamtech.common.utils;

import java.util.list;

public class page<t> {
    
    private int total;
    private int page;
    private int size;
    private list<t> rows;
    public int gettotal() {
        return total;
    }
    public void settotal(int total) {
        this.total = total;
    }
    public int getpage() {
        return page;
    }
    public void setpage(int page) {
        this.page = page;
    }
    public int getsize() {
        return size;
    }
    public void setsize(int size) {
        this.size = size;
    }
    public list<t> getrows() {
        return rows;
    }
    public void setrows(list<t> rows) {
        this.rows = rows;
    }
    
    
    
}

 

 

ok,这时候我在前端jsp页面只需要写这一行即可完成分页:

                            <yiqing:page url="${pagecontext.request.contextpath }/xxxx" />

 

 

接下来做一个实际使用的示例:

前端发送查询条件进行客户查询:

 

前端jsp页面的查询表单:(jsp代码就不给了,没什么意义)

SSM框架利用自定义标签分页

 

传递过来了一个查询对象:

分别是客户名称模糊输入,选择的来源行业以及级别

 

SSM框架利用自定义标签分页
public class queryvo {

    // 客户信息
    private string custname;
    private string custsource;
    private string custindustry;
    private string custlevel;

    // 当前页信息
    private integer page;

    // 每页数
    private integer size = 10;

    private integer startrow = 0;

    public integer getstartrow() {
        return startrow;
    }

    public void setstartrow(integer startrow) {
        this.startrow = startrow;
    }

    public string getcustname() {
        return custname;
    }

    public void setcustname(string custname) {
        this.custname = custname;
    }

    public string getcustsource() {
        return custsource;
    }

    public void setcustsource(string custsource) {
        this.custsource = custsource;
    }

    public string getcustindustry() {
        return custindustry;
    }

    public void setcustindustry(string custindustry) {
        this.custindustry = custindustry;
    }

    public string getcustlevel() {
        return custlevel;
    }

    public void setcustlevel(string custlevel) {
        this.custlevel = custlevel;
    }

    public integer getpage() {
        return page;
    }

    public void setpage(integer page) {
        this.page = page;
    }

    public integer getsize() {
        return size;
    }

    public void setsize(integer size) {
        this.size = size;
    }

}
view code

 

controller层:

        page<customer> page = customerservice.selectpagebyqueryvo(vo);
        model.addattribute("page", page);

 

service层:这里的startrow和下面的

    public page<customer> selectpagebyqueryvo(queryvo vo) {
        page<customer> page = new page<customer>();
        vo.setsize(5);
        page.setsize(5);
        if (vo != null) {
            if (vo.getpage() != null) {
                vo.setstartrow((vo.getpage() - 1) * vo.getsize());
                page.setpage(vo.getpage());
            }
            page.settotal(customerdao.customercountbyqueryvo(vo));
            page.setrows(customerdao.selectcustomerlistbyqueryvo(vo));
        }
        // 每页
        page.setsize(5);

        return page;
    }

 

dao层映射:

    <select id="selectcustomerlistbyqueryvo" parametertype="queryvo"
        resulttype="customer">
        select * from customer
        <where>
            <if test="custname!=null and custname!=''">
                cust_name like "%"#{custname}"%"
            </if>
            <if test="custsource!=null and custsource!=''">
                and cust_source = #{custsource}
            </if>
            <if test="custindustry!=null and custindustry!=''">
                and cust_industry = #{custindustry}
            </if>
            <if test="custlevel!=null and custlevel!=''">
                and cust_level = #{custlevel}
            </if>
        </where>
        limit #{startrow},#{size}
    </select>

 

 

这样就可以查到信息了:

并且右下角自动分页

分页很智能,当前页总是显示在中间一格,最后一页和第一页无法点击的细节也有

SSM框架利用自定义标签分页