分頁是 Web 開發最基礎也最高頻的需求。本文通過一個「登錄後分頁展示用戶列表」的完整案例,演示基於 **Servlet + Session + JSTL/EL** 的服務端分頁核心邏輯,零框架依賴,適合初學者建立分頁思維模型。
PageServlet 接收請求index.jsp 渲染展示public class User {
private String username;
private String password;
// getter/setter 省略
}
public class PageServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 獲取數據(實際應從 DB 查詢)
List<User> list = new ArrayList<>();
for (int i = 1; i < 7; i++) {
User u = new User();
u.setUsername("第" + i + "個用戶名");
u.setPassword("第" + i + "密碼");
list.add(u);
}
// 2. 存入 Session 供 JSP 讀取
HttpSession session = request.getSession();
session.setAttribute("userList", list);
// 3. 解析當前頁碼,防非法值
int pageNos = 1;
String param = request.getParameter("pageNos");
if (param != null) {
try {
int p = Integer.parseInt(param);
if (p >= 1) pageNos = p;
} catch (NumberFormatException ignored) {}
}
session.setAttribute("pageNos", pageNos);
// 4. 總頁數(實際應由 COUNT(*) 計算)
int countPage = 3; // 假設每頁 2 條,共 6 條
session.setAttribute("countPage", countPage);
// 5. 轉發
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<body>
<!-- 1. 列表渲染:利用 begin/end 實現切片 -->
<c:forEach items="${userList}" var="user"
begin="${(pageNos-1)*2}" end="${pageNos*2-1}">
<center><div>${user.username}</div></center>
<center><div>${user.password}</div></center>
</c:forEach>
<!-- 2. 分頁導航 -->
<center>
<c:if test="${pageNos > 1}">
<a href="pageServlet?pageNos=1">首頁</a>
<a href="pageServlet?pageNos=${pageNos-1}">上一頁</a>
</c:if>
<c:if test="${pageNos < countPage}">
<a href="pageServlet?pageNos=${pageNos+1}">下一頁</a>
<a href="pageServlet?pageNos=${countPage}">末頁</a>
</c:if>
</center>
<!-- 3. 頁碼跳轉表單 -->
<form action="pageServlet">
<h4 align="center">
共 ${countPage} 頁
<input type="text" value="${pageNos}" name="pageNos" size="1"> 頁
<input type="submit" value="go">
</h4>
</form>
</body>
| 技術點 | 說明 |
|---|---|
<c:forEach> begin/end | 實現內存分頁切片。begin 從 0 計數,第 N 頁 (每頁 size 條) 對應 begin=(N-1)*size, end=N*size-1。 |
| Session 存儲 | 簡化演示用。生產環境**大數據量嚴禁全量放 Session**,應改為: 1. 數據庫分頁查詢 + 只存當前頁數據 2. 或 Redis 緩存分頁結果 |
| 參數校驗 | Servlet 中對 pageNos 做非空、數字、邊界校驗,防注入與異常。 |
| JSTL 引入 | 必須在 JSP 頂部聲明 <%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>,且項目需包含 jstl.jar、standard.jar。 |
LIMIT offset, size、Oracle ROWNUM、SQL Server OFFSET FETCH,避免全表掃描。PageResult<T> { List<T> data; long total; int pageNum; int pageSize; } 統一前後端契約。page:list:pageNum:pageSize。LIMIT 1000000, 20 性能劣化,改用「游標分頁」或「延遲關聯」優化。本文通過最樸素的 Servlet + JSP 實現,還原了分頁的本質:**數據切片 + 狀態傳遞 + UI 導航**。掌握這套核心邏輯後,無論遷移到 Spring MVC、Spring Boot、MyBatis-Plus 分頁插件,還是前後端分離架構下的 RESTful 分頁 API,其底層思維模型始終一致。