在jsp技术中,自定义标签是一个非常重要的知识点。很多人学完自定义标签后,在做项目时还是不知道在哪些地方可以用得上。其实我们在很多情况下可以用到,今天就给大家分享一个业务系统中高频使用到的一个功能“分页”。

分页看起来很简单,实际上,之中设计到的业务逻辑还是比较多的。

首先我们都知道,一个分页功能会包含当前页,总页数,总记录数,当前页记录集等等一些必要信息。那么在设计之初,我们把分页抽象为一个对象。

分页对象

package cn.gson.mvc.model;

import java.util.List;

/**
 * 分页对象
 * @author 夏悸
 *
 * @param <T>
 */
public class Pager<T> {

    /**
     * 当前页码
     */
    private Integer page = 1;

    /**
     * 页大小
     */
    private Integer pageSize = 10;

    /**
     * 当前页的数据
     */
    private List<T> rows;

    /**
     * 总记录数
     */
    private Long total;

    /**
     * 总页数
     */
    private Integer totalPage;

    public Pager(Integer page) {
        this.page = page;
    }

    public Pager(Integer page, Integer pageSize) {
        this.page = page;
        this.pageSize = pageSize;
    }
    
    /**
     * 获取分页参数
     * @return
     */
    public int getStart() {
        return (this.page - 1) * this.pageSize;
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = Math.max(page, 1);
    }

    public List<T> getRows() {
        return rows;
    }

    public void setRows(List<T> rows) {
        this.rows = rows;
    }

    public Long getTotal() {
        return total;
    }

    public void setTotal(Long total) {
        this.total = total;
    }

    public Integer getTotalPage() {
        return (int) Math.ceil(total / pageSize);
    }

    public void setTotalPage(Integer totalPage) {
        this.totalPage = totalPage;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public Integer getPageSize() {
        return pageSize;
    }
}

自定义pager标签

要自定义jsp标签,我们需要些一个类SimpleTagSupport,然后在doTag方法中实现我们的分页逻辑

package cn.gson.mvc.tag;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

import cn.gson.mvc.common.StringUtils;
import cn.gson.mvc.model.Pager;

/**
 * 分页标签
 * 
 * @author 夏悸
 *
 */
public class PagerTag extends SimpleTagSupport {

    private String url;

    private Pager<?> pager;

    @Override
    public void doTag() throws JspException, IOException {
        StringBuffer sb = new StringBuffer("<div class=\"page\">");
        String queryStr = this.getParamStr();
        if (pager.getPage() == 1) {
            sb.append("<a class=\"disable\">首页</a>");
            sb.append("<a class=\"disable\">上一页</a>");
        } else {
            sb.append("<a href=\"" + url + "?p=1" + queryStr + "\">首页</a>");
            sb.append("<a href=\"" + url + "?p=" + (pager.getPage() - 1) + queryStr + "\">上一页</a>");
        }

        if (pager.getPage() == pager.getTotalPage()) {
            sb.append("<a class=\"disable\">下一页</a>");
            sb.append("<a class=\"disable\">尾页</a>");
        } else {
            sb.append("<a href=\"" + url + "?p=" + (pager.getPage() + 1) + queryStr + "\">下一页</a>");
            sb.append("<a href=\"" + url + "?p=" + pager.getTotalPage() + queryStr + "\">尾页</a>");
        }

        sb.append(String.format("%s/%s(共有%s条)", pager.getPage(), pager.getTotalPage(), pager.getTotal()));
        sb.append("</div>");

        getJspContext().getOut().write(sb.toString());
    }

    public String getParamStr() throws UnsupportedEncodingException {
        PageContext pageContext = (PageContext) this.getJspContext();
        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
        Enumeration<String> pnames = request.getParameterNames();

        List<String> params = new ArrayList<>();

        while (pnames.hasMoreElements()) {
            String name = (String) pnames.nextElement();
            if (!"p".equalsIgnoreCase(name)) {
                String[] values = request.getParameterValues(name);
                for (String value : values) {
                    if (!StringUtils.isEmpty(value)) {
                        params.add(name + "=" + URLEncoder.encode(value, "UTF-8"));
                    }
                }
            }
        }

        StringBuffer sb = new StringBuffer();
        if (params.size() > 0) {
            sb.append("&");
            for (String item : params) {
                sb.append(item).append("&");
            }
            sb.deleteCharAt(sb.length() - 1);
        }

        return sb.toString();
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setPager(Pager<?> pager) {
        this.pager = pager;
    }
}

定义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">
    <tlib-version>2.0</tlib-version>
    <short-name>myTag</short-name>
    <uri>http://www.gson.cn/tags</uri>

    <tag>
        <name>pager</name>
        <tag-class>cn.gson.mvc.tag.PagerTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <description>分页请求</description>
            <!-- 属性名称,必须要和类中定义的属性名一致 -->
            <name>url</name>
            <!-- 属性是否是必须的 -->
            <required>true</required>
            <!-- 属性值是否可以用表达式 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <description>分页对象</description>
            <name>pager</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

</taglib>

在jsp中使用自定义标签

1、首页在jsp头部通过jsp指定导入自定义一标签

<%@ taglib uri="http://www.gson.cn/tags"  prefix="myTag"%>

2、调用标签

<myTag:pager pager="${pager }" url="user/list"/>

重点是上面的pager属性,怎么出来。
当我们发生请求到servlet中请求分页数据,在servlet中我们对数据分页所需要的用到的所有数据进行封装

servlet的处理

package cn.gson.mvc.controller.user;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.gson.mvc.model.Pager;
import cn.gson.mvc.model.bean.User;
import cn.gson.mvc.model.dao.UserDao;

@WebServlet("/user/list")
public class UserListController extends HttpServlet {

    private static final long serialVersionUID = 1L;
    
    private UserDao udao = new UserDao();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            String p = req.getParameter("p");
            String userName = req.getParameter("userName");
            String tel = req.getParameter("tel");

            int page = 1;
            if (p != null) {
                page = Integer.parseInt(p);
            }
            Pager<User> pager = new Pager<>(page);
            
            udao.findAll(pager, userName, tel);

            req.setAttribute("pager", pager);

            req.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(req, resp);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

可以看到在servlet中我们创建了pager对象,并且把pager对象传入到了Dao中,所以我们dao中其实要做的事情就是去完善pager中除了page之外的其他属性,主要是rows和total。

最终效果

QQ20170414-203847@2x.png

QQ20170414-203937@2x.png

QQ20170414-203930@2x.png