JSTL (JSP Standard Tag Library) 是 JSP 頁面開發的標準工具箱,將格式化、字符串操作、流程控制等通用邏輯封裝為聲明式標簽,大幅減少 Scriptlet 代碼。本文系統整理 fmt 格式化、fn 函數庫、c 核心流程控制 三大模塊高頻用法,附帶實戰片段,作為開發時的「隨身速查表」。
<fmt:formatNumber><!-- 百分比輸出:0.85 → 85% -->
<fmt:formatNumber value="${user.adoptRate}" type="percent" />
<!-- 貨幣格式:1234.5 → ¥1,234.50 -->
<fmt:formatNumber value="${order.amount}" type="currency" currencySymbol="¥" />
<!-- 保留 2 位小數 -->
<fmt:formatNumber value="${ratio}" maxFractionDigits="2" />
<fmt:formatDate>| type 屬性 | 輸出示例 | 說明 |
|---|---|---|
| date | 2024-03-15 | 僅日期 |
| time | 14:30:45 | 僅時間 |
| both | 2024-03-15 14:30:45 | 日期+時間 |
<!-- 自定義模式(推薦:統一項目格式) -->
<fmt:formatDate value="${createTime}" pattern="yyyy-MM-dd HH:mm:ss" />
<fmt:formatDate value="${createTime}" pattern="yyyy年MM月dd日 EEEE" /> <!-- 2024年03月15日 星期五 -->
<!-- 時區控制 -->
<fmt:formatDate value="${utcTime}" timeZone="GMT+8" pattern="yyyy-MM-dd HH:mm:ss" />
<fmt:parseNumber> / <fmt:parseDate><fmt:parseNumber value="1,234.56" type="currency" var="parsedNum" /> <!-- var 存入變量 --> <fmt:parseDate value="2024-03-15" pattern="yyyy-MM-dd" var="parsedDate" />
<fmt:bundle> + <fmt:message><fmt:bundle basename="i18n.messages">
<fmt:message key="welcome" /> <!-- 輸出 messages_zh_CN.properties 中 welcome 值 -->
</fmt:bundle>
命名空間:xmlns:fn="https://java.sun.com/jsp/jstl/functions"
| 函數 | 簽名 | 說明 | 示例 |
|---|---|---|---|
| contains | boolean contains(string, substring) | 包含判斷(區分大小寫) | ${fn:contains(name, 'admin')} |
| containsIgnoreCase | boolean containsIgnoreCase(string, substring) | 忽略大小寫包含 | ${fn:containsIgnoreCase(email, 'GMAIL')} |
| startsWith | boolean startsWith(string, prefix) | 前綴匹配 | ${fn:startsWith(url, 'https')} |
| endsWith | boolean endsWith(string, suffix) | 後綴匹配 | ${fn:endsWith(fileName, '.pdf')} |
| substring | String substring(string, begin, end) | 截取 [begin, end) | ${fn:substring(id, 0, 6)} |
| substringBefore | String substringBefore(string, separator) | 分隔符前部分 | ${fn:substringBefore(email, '@')} |
| substringAfter | String substringAfter(string, separator) | 分隔符後部分 | ${fn:substringAfter(url, '://')} |
| replace | String replace(string, before, after) | 全量替換 | ${fn:replace(content, '<', '<')} |
| split | String[] split(string, separator) | 分割為數組 | ${fn:split(tags, ',')} |
| join | String join(array, separator) | 數組連接為字符串 | ${fn:join(roles, ', ')} |
| length | int length(item) | 集合/數組/字符串長度 | ${fn:length(userList) > 0} |
| toUpperCase | String toUpperCase(string) | 轉大寫 | ${fn:toUpperCase(code)} |
| toLowerCase | String toLowerCase(string) | 轉小寫 | ${fn:toLowerCase(domain)} |
| trim | String trim(string) | 去首尾空白 | ${fn:trim(input)} |
| escapeXml | String escapeXml(string) | 轉義 XML/HTML 特殊字符 | ${fn:escapeXml(userInput)} |
| indexOf | int indexOf(string, substring) | 首次出現索引 | ${fn:indexOf(str, 'error') != -1} |
<c:if> / <c:choose><c:if test="${not empty user.avatar}">
<img src="${user.avatar}" />
</c:if>
<c:choose>
<c:when test="${user.role == 'ADMIN'}">管理員</c:when>
<c:when test="${user.role == 'VIP'}">會員</c:when>
<c:otherwise>普通用戶</c:otherwise>
</c:choose>
<c:forEach><!-- 列表遍歷 -->
<c:forEach items="${articleList}" var="article" varStatus="status">
${status.count}. ${article.title} <br/>
</c:forEach>
<!-- 數字範圍 -->
<c:forEach begin="1" end="10" step="2" var="i">
${i}
</c:forEach>
<!-- 分割字符串遍歷(配合 fn:split) -->
<c:forEach items="${fn:split(searchKeywords, ',')}" var="kw">
<span class="tag">${kw}</span>
</c:forEach>
<c:set> / <c:remove><c:set var="pageSize" value="20" scope="session" />
<c:set target="${map}" property="key" value="newValue" /> <!-- Map/Bean 設置屬性 -->
<c:remove var="tempVar" scope="request" />
<c:url> / <c:param><c:url value="/search" var="searchUrl">
<c:param name="q" value="${keyword}" />
<c:param name="page" value="${pageNum}" />
</c:url>
<a href="${searchUrl}">搜索</a>
<c:if test="${not empty searchForm.keywords}">
<c:set var="kwArray" value="${fn:split(searchForm.keywords, ',')}" />
<c:forEach items="${kwArray}" var="kw" varStatus="vs">
<span class="badge badge-${vs.index % 5 + 1}">
${fn:escapeXml(kw)} <!-- 防 XSS -->
</span>
</c:forEach>
</c:if>
web.xml version="3.0+"、JSP 頁面 isELIgnored="false"、引入 jstl-1.2.jar(非 1.0/1.1)。<c:forEach> 直接支持數組,無需轉換。timeZone 屬性。JSTL 標簽庫雖屬「上古」技術,但在存量 JSP 系統、傳統 MVC 專案、甚至 Thymeleaf/FreeMarker 模板中,其聲明式風格與 fn 函數庫仍具極高參考價值。熟練掌握上述核心標簽,能讓視圖層代碼乾淨、安全、易維護。