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

Java Web 分頁顯示實戰:DAO/Service/Controller/JSP 全層實現與 EL/JSTL 渲染完整示例

     編輯:Java 相關知識

前言

分頁是 Web 應用最基礎的數據展示需求。本文提供一個基於「表現層-控制層-DAO層-數據庫」經典架構的完整分頁示例,涵蓋總頁數計算、分頁查詢、Servlet 控制器、JSP+EL/JSTL 渲染,代碼可直接運行並擴展。

數據庫準備

CREATE TABLE books (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    number VARCHAR(50)
);
-- 插入測試數據 20+ 條

DAO 層

public class BookDao {
    // 連接工具類略 (JDBCUtils: getConnection/close)
    
    /** 計算總頁數 */
    public int getTotalPages(int pageSize) {
        String sql = "SELECT COUNT(*) FROM books";
        try (Connection conn = JDBCUtils.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql);
             ResultSet rs = ps.executeQuery()) {
            if (rs.next()) {
                int total = rs.getInt(1);
                return (total + pageSize - 1) / pageSize; // 向上取整
            }
        } catch (SQLException e) { throw new RuntimeException(e); }
        return 0;
    }

    /** 分頁查詢 */
    public List<Book> findByPage(int pageNo, int pageSize) {
        String sql = "SELECT id, name, number FROM books ORDER BY id LIMIT ?, ?";
        List<Book> list = new ArrayList<>();
        try (Connection conn = JDBCUtils.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setInt(1, (pageNo - 1) * pageSize); // offset
            ps.setInt(2, pageSize);
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    Book b = new Book();
                    b.setId(rs.getInt("id"));
                    b.setName(rs.getString("name"));
                    b.setNumber(rs.getString("number"));
                    list.add(b);
                }
            }
        } catch (SQLException e) { throw new RuntimeException(e); }
        return list;
    }
}

實體類

public class Book {
    private int id; private String name; private String number;
    // Getter/Setter
}

Servlet 控制器

@WebServlet("/listBooks")
public class ListBooksServlet extends HttpServlet {
    private BookDao dao = new BookDao();
    private static final int PAGE_SIZE = 5;

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int pageNo = 1;
        String param = req.getParameter("pageNo");
        if (param != null) {
            try { pageNo = Integer.parseInt(param); } 
            catch (NumberFormatException ignored) {}
        }
        // 邊界校驗
        int totalPages = dao.getTotalPages(PAGE_SIZE);
        if (pageNo < 1) pageNo = 1;
        if (pageNo > totalPages) pageNo = totalPages;

        List<Book> books = dao.findByPage(pageNo, PAGE_SIZE);

        req.setAttribute("books", books);
        req.setAttribute("pageNo", pageNo);
        req.setAttribute("totalPages", totalPages);
        req.getRequestDispatcher("/booklist.jsp").forward(req, resp);
    }
}

JSP 頁面 (booklist.jsp)

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<html><head><title>圖書列表</title>
<style> table{border-collapse:collapse;width:60%;margin:20px auto;} th,td{border:1px solid #ccc;padding:8px;text-align:center;} .page{text-align:center;margin:20px;} .page a{margin:0 5px;padding:2px 8px;border:1px solid #ccc;text-decoration:none;} .page span{margin:0 5px;} </style>
</head><body>
<h2 style="text-align:center">圖書信息</h2>
<table>
    <tr><th>書號</th><th>書名</th><th>庫存量</th></tr>
    <c:forEach items="${books}" var="book">
        <tr>
            <td>${book.id}</td>
            <td>${book.name}</td>
            <td>${book.number}</td>
        </tr>
    </c:forEach>
</table>

<div class="page">
    <c:if test="${pageNo > 1}">
        <a href="listBooks?pageNo=1">首頁</a>
        <a href="listBooks?pageNo=${pageNo-1}">上一頁</a>
    </c:if>
    <span>第 ${pageNo} 頁 / 共 ${totalPages} 頁</span>
    <c:if test="${pageNo < totalPages}">
        <a href="listBooks?pageNo=${pageNo+1}">下一頁</a>
        <a href="listBooks?pageNo=${totalPages}">末頁</a>
    </c:if>
    <form action="listBooks" method="get" style="display:inline;margin-left:10px;">
        跳轉 <input type="number" name="pageNo" value="${pageNo}" min="1" max="${totalPages}" size="3">
        <input type="submit" value="Go">
    </form>
</div>
</body></html>

關鍵技術點總結

層級核心邏輯
數據庫MySQL LIMIT offset, pageSize;Oracle 用 ROWNUM 子查詢/分析函數;SQL Server 用 OFFSET FETCH
DAO總記錄數 → 總頁數;PreparedStatement 防注入;try-with-resources 保證資源關閉
Servlet參數解析+邊界校驗;設置屬性轉發 JSP;無業務邏輯
JSP<c:forEach> 渲染列表;<c:if> 控制分頁鏈接顯隱;EL 表達式 ${...} 取值

進階擴展方向

  1. 通用分頁工具類: 封裝 Page<T> 對象 (records, total, pageNo, pageSize, totalPages),Service 返回 Page,Controller 僅傳遞。
  2. MyBatis 分頁插件: PageHelper 一行代碼實現物理分頁:PageHelper.startPage(pageNo, pageSize); List<Book> list = mapper.selectAll(); PageInfo<Book> page = new PageInfo<>(list);
  3. 前端分頁組件: Vue/React + ElementUI/Ant Design 分頁組件,AJAX 獲取 JSON 數據,前後端分離模式。
  4. 緩存總數: 高併發場景下,總記錄數緩存到 Redis,定時/事件驅動更新,減輕數據庫壓力。

總結

本示例展示了 Java Web 分頁的「最小完整閉環」。理解 總數統計 → 物理分頁 SQL → 參數校驗 → 屬性傳遞 → EL/JSTL 渲染 流程,即可靈活應對各類分頁需求。現代項目建議引入 PageHelper 或前後端分離架構,將分頁邏輯下沉到框架/組件層。

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