首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

自訂 JSP 分頁標籤:從零打造可重用的分頁元件

     編輯:Java 相關知識

在開發 S2SH(Struts2 + Spring + Hibernate)專案時,分頁功能幾乎是每個列表頁面的標配。為了避免在每個 JSP 中重複撰寫分頁邏輯,將其封裝為自訂標籤(Custom Tag)不僅能提升開發效率,還能確保介面風格一致。本文將完整記錄如何從零開始建立一個功能完整、參數靈活的分頁標籤,供團隊內部複用。

一、標籤使用示例

在 JSP 頁面引入標籤庫:

<%@ taglib uri="/htdz-tag" prefix="htdz-tag" %>

在需要顯示分頁控件的位置插入標籤:

<htdz-tag:PagerTag 
    pagesize="${pagesize}" 
    rowcount="${rowcount}" 
    currpagenum="${currpagenum}" 
    action="${action}" 
    className="button_small" />

參數說明:

  • pagesize:每頁筆數(必填)
  • rowcount:總筆數(必填)
  • currpagenum:當前頁碼(必填)
  • action:表單提交或連結的目標 URL(必填)
  • className:按鈕 CSS 樣式類名(選填,預設為 button_small)

二、建立 TLD 標籤描述檔

在 WEB-INF/tags/htdz-tag.tld 定義標籤元資料:

<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="https://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://java.sun.com/xml/ns/j2ee https://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">
    <description>htdz 分頁標籤庫</description>
    <display-name>htdz-tag</display-name>
    <tlib-version>1.0</tlib-version>
    <short-name>htdz-tag</short-name>
    <uri>/htdz-tag</uri>

    <tag>
        <description>分頁控件,支援首頁、上一頁、下一頁、尾頁、頁碼跳轉</description>
        <name>PagerTag</name>
        <tag-class>com.htdz.util.tag.PagerTag</tag-class>
        <body-content>JSP</body-content>

        <attribute>
            <name>pagesize</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>rowcount</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>currpagenum</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>action</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>className</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

三、實作標籤處理類 PagerTag.java

核心邏輯繼承 TagSupport,在 doStartTag() 中完成參數驗證、總頁數計算、按鈕狀態判斷與 HTML 生成:

public class PagerTag extends TagSupport {
    private static final String DEFAULT_BUTTON_CLASS = "button_small";
    private static final String DISABLE_BUTTON_CLASS = "button_small_disable";

    private int pagesize;
    private int rowcount;
    private int currpagenum;
    private String action;
    private String className;

    // Setter 方法省略...

    @Override
    public int doStartTag() throws JspException {
        // 1. 參數驗證
        validateAttributes();

        // 2. 套用預設樣式
        if (className == null || className.isEmpty()) {
            className = DEFAULT_BUTTON_CLASS;
        }

        // 3. 計算總頁數
        int totalPages = getTotalPages(rowcount);
        if (rowcount == 0) {
            currpagenum = 1;
            totalPages = 1;
        }

        // 4. 判斷按鈕啟用/停用狀態
        boolean noUp = (currpagenum == 1);
        boolean noDown = (currpagenum == totalPages);
        String btnClass1 = noUp ? DISABLE_BUTTON_CLASS : className;
        String btnClass2 = noDown ? DISABLE_BUTTON_CLASS : className;

        // 5. 組裝 HTML
        StringBuffer html = new StringBuffer();
        html.append(currpagenum).append("/").append(totalPages).append("頁");

        appendButton(html, "首頁", "first", btnClass1, noUp);
        appendButton(html, "上一頁", "up", btnClass1, noUp);
        appendButton(html, "下一頁", "down", btnClass2, noDown);
        appendButton(html, "尾頁", "last", btnClass2, noDown);

        html.append(currpagenum).append("/").append(totalPages).append("頁  ");
        html.append("<input type=\"text\" maxlength=\"3\" id=\"text\" size=\"3\" onkeypress=\"return checkInput(event);\" />頁");
        html.append("<input class=\"").append(className).append("\" type=\"button\" value=\"GO\" onclick=\"turnPage('to','")
            .append(currpagenum).append("','").append(totalPages).append("','").append(action).append("')\" />");

        try {
            pageContext.getOut().println(html.toString());
        } catch (IOException e) {
            throw new JspException("分頁標籤輸出失敗: " + e.getMessage());
        }
        return SKIP_BODY;
    }

    private void appendButton(StringBuffer html, String label, String direction, String cssClass, boolean disabled) {
        html.append("<input class=\"").append(cssClass)
            .append("\" type=\"button\" value=\"").append(label)
            .append("\" onclick=\"turnPage('").append(direction).append("','")
            .append(currpagenum).append("','").append(totalPages).append("','")
            .append(action).append("')\" ");
        if (disabled) html.append("disabled=\"true\" ");
        html.append("/>");
    }

    private int getTotalPages(int rowcount) {
        return (rowcount % pagesize == 0) ? rowcount / pagesize : rowcount / pagesize + 1;
    }

    private void validateAttributes() throws JspException {
        if (pagesize <= 0) throw new JspException("pagesize 必須大於 0");
        if (rowcount < 0) throw new JspException("rowcount 不能為負數");
        if (currpagenum <= 0) throw new JspException("currpagenum 必須大於 0");
        if (action == null || action.isEmpty()) throw new JspException("action 不能為空");
    }
}

四、後端 Action 整合範例

以 Struts2 Action 為例,在查詢方法中設定分頁所需屬性:

public class UserAction extends ActionSupport {
    private UserService userService;
    private List<User> users;
    private int pagesize = PagerTag.USER_PAGESIZE; // 靜態常數 5
    private int rowcount;
    private int currpagenum = 1;
    private String action = "findUser.action";

    public String findUser() {
        HttpServletRequest request = ServletActionContext.getRequest();
        String pagenum = request.getParameter("pagenum");
        if (pagenum != null && !pagenum.isEmpty()) {
            currpagenum = Integer.parseInt(pagenum);
        }

        users = userService.findUser(currpagenum, pagesize);
        if (!users.isEmpty()) {
            rowcount = userService.getCount();
            request.setAttribute("users", users);
            request.setAttribute("rowcount", rowcount);
            request.setAttribute("currpagenum", currpagenum);
            request.setAttribute("pagesize", pagesize);
            request.setAttribute("action", action);
            return SUCCESS;
        } else {
            addActionMessage("無記錄!");
            return INPUT;
        }
    }
    // Getter/Setter 省略
}

五、Service 與 DAO 分頁查詢

UserService 只負責轉呼叫 DAO:

public List<User> findUser(int pageNum, int pageSize) {
    return userDao.findUser(pageNum, pageSize);
}
public int getCount() { return userDao.getCount(); }

UserDao 使用 Hibernate 的 setFirstResult / setMaxResults 實現實體分頁:

public List<User> findUser(int pageNum, int pageSize) {
    Session session = getSession();
    try {
        Query query = session.createQuery("from User");
        query.setFirstResult(pageSize * (pageNum - 1));
        query.setMaxResults(pageSize);
        return query.list();
    } finally {
        session.close();
    }
}
public int getCount() {
    Session session = getSession();
    try {
        Long count = (Long) session.createQuery("select count(id) from User").uniqueResult();
        return count.intValue();
    } finally {
        session.close();
    }
}

六、前端 JavaScript 輔助函式

頁面需引入 turnPage(direction, curr, total, action) 與 checkInput(event) 兩個函式,分別處理翻頁導向與輸入框數字驗證,這裡不再贅述。

七、總結

透過自訂標籤將分頁邏輯集中化,後續新增列表頁面時,只需在 Action 傳入四個必要屬性,JSP 一行標籤即可完成專業級分頁控件渲染。若專案後期需調整樣式或增加「每頁筆數下拉選單」等功能,僅需修改 PagerTag.java 與 TLD,即可全站生效,極大降低維護成本。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved