掌握 JSTL 核心標簽用法,理解 JavaWeb MVC 分層思想,搭建可復用的 BaseServlet 分發器,完成用戶列表的分頁展示,為後續註冊、登錄、商品管理奠定架構基礎。
下載 jakarta-taglibs-standard-1.1.1.zip,將 jstl.jar 和 standard.jar 放入 WEB-INF/lib。
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="https://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="sql" uri="https://java.sun.com/jsp/jstl/sql" %>
| 標簽 | 用途 | 範例 |
|---|---|---|
<c:out> | 安全輸出,防 XSS | <c:out value="${user.name}" default="匿名" /> |
<c:set> | 設置變量 | <c:set var="total" value="${100+200}" /> |
<c:if> | 條件判斷 | <c:if test="${user.type == 1}">管理員</c:if> |
<c:choose> | 多條件分支 | 配合 <c:when>/<c:otherwise> |
<c:forEach> | 迭代集合/Map/區間 | <c:forEach items="${list}" var="item" varStatus="s">${s.index}</c:forEach> |
<c:url> | URL 重寫(自動加 sessionId) | <c:url value="/user.do" var="url"><c:param name="method" value="list"/></c:url> |
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 依賴注入(簡易版,實際建議用 Spring)
DaoUtil.daoInject(this);
// 2. 獲取 method 參數決定調用哪個業務方法
String methodName = req.getParameter("method");
if (methodName == null || methodName.isEmpty()) return;
try {
Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
String viewPath = (String) method.invoke(this, req, resp);
// 3. 統一視圖解析:client: 前綴 -> 重定向;否則 -> 轉發
if (viewPath.startsWith("client:")) {
resp.sendRedirect(req.getContextPath() + "/WEB-INF/" + viewPath.substring(7));
} else {
req.getRequestDispatcher("/WEB-INF/" + viewPath).forward(req, resp);
}
} catch (Exception e) {
throw new ServletException("分發失敗", e);
}
}
}
public class UserServlet extends BaseServlet {
@Dao // 自定義注解,配合 DaoUtil 實現注入
private UserDao userDao;
public String list(HttpServletRequest req, HttpServletResponse resp) {
Pager pagers = userDao.find(null, null, null); // 分頁查詢所有用戶
req.setAttribute("pagers", pagers); // 存入請求域
return "user/list.jsp"; // 邏輯視圖名
}
}
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<table border="1" cellpadding="5" cellspacing="0">
<tr><th>ID</th><th>用戶名</th><th>暱稱</th><th>類型</th><th>操作</th></tr>
<c:forEach items="${pagers.datas}" var="u">
<tr>
<td>${u.id}</td>
<td>${u.username}</td>
<td>${u.nickname}</td>
<td>
<c:choose>
<c:when test="${u.type == 1}">管理員</c:when>
<c:when test="${u.type == 2}">普通用戶</c:when>
<c:otherwise>未知</c:otherwise>
</c:choose>
</td>
<td><a href="user.do?method=view&id=${u.id}">查看</a> | <a href="user.do?method=edit&id=${u.id}">修改</a> | <a href="user.do?method=delete&id=${u.id}">刪除</a></td>
</tr>
</c:forEach>
</table>
<!-- 引入分頁片段 -->
<jsp:include page="../inc/pager.jsp">
<jsp:param name="items" value="${pagers.totalRecord}"/>
<jsp:param name="params" value="method=list"/>
<jsp:param name="url" value="user.do"/>
</jsp:include>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="pg" uri="https://jsptags.com/tags/navigation/pager" %>
<pg:pager items="${param.items}" maxpageitems="10" maxindexpages="10" export="curPage=pageNumber" url="${param.url}">
<c:forEach items="${param.params}" var="p">
<pg:param name="${p}"/>
</c:forEach>
<pg:first><a href="${pageUrl}">首頁</a></pg:first>
<pg:prev><a href="${pageUrl}">上一頁</a></pg:prev>
<pg:pages>
<c:choose>
<c:when test="${curPage == pageNumber}">[${pageNumber}]</c:when>
<c:otherwise><a href="${pageUrl}">${pageNumber}</a></c:otherwise>
</c:choose>
</pg:pages>
<pg:next><a href="${pageUrl}">下一頁</a></pg:next>
<pg:last><a href="${pageUrl}">尾頁</a></pg:last>
</pg:pager>
新增功能(如註冊、登錄、修改密碼)只需在 UserServlet 中增加對應方法(register(), login()),前端請求 user.do?method=register 即可自動分發。相比早期一個 Servlet 對應一個功能的寫法,邏輯更內聚,維護成本大幅降低。
