1. 概述

JavaServer Pages 标签库 (JSTL) 是一套用于实现常见操作的标签集,包括循环、条件格式化等功能。本文将详细介绍如何配置 JSTL 及使用其各类标签。

2. 环境配置

要启用 JSTL 功能,需在项目中添加依赖库。对于 Maven 项目,在 pom.xml 中添加:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

添加依赖后,最后一步是在 JSP 中通过 taglib 指令引入核心标签和其他标签的命名空间:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

接下来我们将介绍 JSTL 的五大类标签。

3. 核心标签

JSTL 核心标签库包含执行基础操作的标签,如输出值、变量声明、异常处理、循环和条件判断等。

3.1. <c:out> 标签

***<c:out> 用于显示变量中的值或隐式表达式的结果。**

它有三个属性:valuedefaultescapeXMLescapeXML 属性控制是否对 value 中的 XML 标签进行转义。

示例用法:

<c:out value="${pageTitle}"/>

3.2. <c:set> 标签

<c:set> 用于在 JSP 中声明作用域变量。可通过 varvalue 属性分别指定变量名和值。

示例:

<c:set value="JSTL Core Tags Example" var="pageTitle"/>

3.3. <c:remove> 标签

<c:remove> 用于移除作用域变量(相当于将变量设为 null)。它接受 varscope 属性,scope 默认为所有作用域。

示例:

<c:remove var="pageTitle"/>

3.4. <c:catch> 标签

<c:catch> 捕获其标签体内抛出的异常。异常对象会存储在 var 属性指定的变量中。

典型用法:

<c:catch var ="exceptionThrown">
    <% int x = Integer.valueOf("a");%>
</c:catch>

检查异常是否发生:

<c:if test = "${exceptionThrown != null}">
    <p>异常信息:${exceptionThrown} <br />
      异常详情:${exceptionThrown.message}
    </p>
</c:if>

3.5. <c:if> 标签

<c:if> 是条件标签,仅当 test 属性表达式为 true 时才执行其内容。评估结果可存储在 var 属性中。

3.6. <c:choose><c:when><c:otherwise> 标签

<c:choose> 是实现 switch 或 if-else 逻辑的父标签,包含两个子标签:

  • <c:when>:相当于 if/else-if
  • <c:otherwise>:相当于 else

<c:when> 通过 test 属性指定判断条件。示例:

<c:set value="<%= Calendar.getInstance().get(Calendar.SECOND)%>" var="seconds"/>
<c:choose>
    <c:when test="${seconds le 30 }">
        <c:out value="${seconds} 小于 30"/>
    </c:when>
    <c:when test="${seconds eq 30 }">
        <c:out value="${seconds} 等于 30"/>
    </c:when>
    <c:otherwise>
        <c:out value="${seconds} 大于 30"/>
    </c:otherwise>
</c:choose>

3.7. <c:import> 标签

<c:import> 用于获取并展示绝对或相对 URL 的内容。

通过 urlvar 属性分别指定 URL 和存储内容的变量。示例:

<c:import var = "data" url = "http://www.example.com"/>

3.8. <c:forEach> 标签

<c:forEach> 类似 Java 的 for/while/do-while 循环。items 属性指定要迭代的集合,beginend 指定起始和结束索引(从 0 开始)。

step 属性控制每次迭代的索引增量。示例:

<c:forEach var = "i" items="1,4,5,6,7,8,9">
    项目 <c:out value = "No. ${i}"/><p>
</c:forEach>

3.9. <c:forTokens> 标签

<c:forTokens> 用于分割字符串并迭代各部分。

类似 <c:forEach>,但增加了 delim 属性指定分隔符。示例:

<c:forTokens 
  items = "Patrick:Wilson:Ibrahima:Chris" 
  delims = ":" var = "name">
    <c:out value = "姓名: ${name}"/><p>
</c:forTokens>

3.10. <c:url><c:param> 标签

<c:url> 用于格式化 URL 并进行正确的请求编码。格式化后的 URL 存储在 var 属性中。

<c:param> 是其子标签,用于添加 URL 参数。示例:

<c:url value = "/core_tags" var = "myURL">
    <c:param name = "parameter_1" value = "1234"/>
    <c:param name = "parameter_2" value = "abcd"/>
</c:url>

3.11. <c:redirect> 标签

<c:redirect> 执行 URL 重写并重定向用户到指定页面。典型用法:

<c:redirect url="/core_tags"/>

4. 格式化标签

JSTL 格式化标签库提供便捷方式格式化文本、数字、日期、时间等变量,优化显示效果。

这些标签还能增强网站国际化能力。使用前需添加 taglib:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

4.1. <fmt:formatDate> 标签

<fmt:formatDate> 用于格式化日期或时间。value 属性指定日期,type 属性可选 datetimeboth

pattern 属性可自定义格式模式。示例:

<c:set var="now" value="<%= new java.util.Date()%>"/>
<fmt:formatDate type="time" value="${now}"/>

4.2. <fmt:parseDate> 标签

<fmt:parseDate><fmt:formatDate> 类似,但可指定日期解析器期望的格式模式。

解析日期示例:

<c:set var="today" value="28-03-2018"/>
<fmt:parseDate value="${today}" var="parsedDate" pattern="dd-MM-yyyy"/>

4.3. <fmt:formatNumber> 标签

<fmt:formatNumber> 按指定模式或精度渲染数字,type 属性可选 numbercurrencypercentage。示例:

<c:set var="fee" value="35050.1067"/>
<fmt:formatNumber value="${fee}" type="currency"/>

4.4. <fmt:parseNumber> 标签

<fmt:parseNumber><fmt:formatNumber> 类似,但可指定数字解析器期望的格式模式。

用法示例:

<fmt:parseNumber var="i" type="number" value="${fee}"/>

4.5. <fmt:bundle> 标签

<fmt:bundle><fmt:message> 的父标签,通过 basename 属性指定资源包,使其对子标签可用。

支持国际化,可指定区域相关对象。典型用法:

<fmt:bundle basename="com.baeldung.jstl.bundles.CustomMessage" prefix="verb.">
    <fmt:message key="go"/><br/>
    <fmt:message key="come"/><br/>
    <fmt:message key="sit"/><br/>
    <fmt:message key="stand"/><br/>
</fmt:bundle>

4.6. <fmt:setBundle> 标签

<fmt:setBundle> 在 JSP 中加载资源包并使其在整个页面可用。加载的资源包存储在 var 属性中。示例:

<fmt:setBundle basename="com.baeldung.jstl.bundles.CustomMessage" var="lang"/>

4.7. <fmt:setLocale> 标签

<fmt:setLocale> 为声明后的 JSP 部分设置区域。典型用法:

<fmt:setLocale value="fr_FR"/>

fr_FR 表示法语区域。

4.8. <fmt:timeZone> 标签

<fmt:timeZone> 是父标签,指定其内部标签的时间格式化/解析操作使用的时区。

时区通过 value 属性指定。示例:

<fmt:timeZone value="${zone}">
    <fmt:formatDate value="${now}" timeZone="${zn}" 
      type="both"/>
</fmt:timeZone>

4.9. <fmt:setTimeZone> 标签

<fmt:setTimeZone>value 属性指定的时区复制到 var 属性指定的作用域变量。示例:

<fmt:setTimeZone value="GMT+9"/>

4.10. <fmt:message> 标签

<fmt:message> 用于显示国际化消息。需通过 key 属性指定消息的唯一标识符。

可通过 bundle 属性指定特定的资源包。示例:

<fmt:setBundle basename = "com.baeldung.jstl.bundles.CustomMessage" var = "lang"/>
<fmt:message key="verb.go" bundle="${lang}"/>

4.11. <fmt:requestEncoding> 标签

<fmt:requestEncoding>post 类型的表单指定编码类型。

编码名称通过 value 属性指定。示例:

<fmt:requestEncoding value = "UTF-8" />

5. XML 标签

JSTL XML 标签库提供在 JSP 中操作 XML 数据的便捷方式。使用前需添加:

<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

5.1. <x:out> 标签

<x:out> 类似 JSP 的 <%= %> 脚本标签,但专用于 XPath 表达式。

selectescapeXML 属性分别指定 XPath 表达式和是否转义特殊 XML 字符。简单示例:

<x:out select="$output/items/item[1]/name"/>

$output 指预加载的 XSL 文件。

5.2. <x:parse> 标签

<x:parse> 解析 xmldoc 属性指定的 XML 数据。典型示例:

<x:parse xml="${xmltext}" var="output"/>

5.3. <x:set> 标签

<x:set>select 属性的 XPath 表达式结果存储到 var 属性指定的变量中。示例:

<x:set var="fragment" select="$output//item"/>

5.4. <x:if> 标签

<x:if>select 属性的 XPath 表达式为 true 时处理其内容。评估结果可存储在 var 属性中。

简单用法:

<x:if select="$output//item">
    文档至少包含一个 <item> 元素。
</x:if>

5.5. <x:forEach> 标签

<x:forEach> 遍历 XML 文档中的节点。XML 文档通过 select 属性指定。

类似 <c:forEach>,有 beginendstep 属性。示例:

<ul class="items">
    <x:forEach select="$output/items/item/name" var="item">
        <li>项目名称: <x:out select="$item"/></li>
    </x:forEach>
</ul>

5.6. <x:choose><x:when><x:otherwise> 标签

<x:choose> 是实现 switch 或 if/else-if/else 逻辑的父标签,无属性,包含 <x:when><x:otherwise> 子标签。

  • <x:when>:相当于 if/else-if,通过 select 属性指定判断条件
  • <x:otherwise>:相当于 else/default,无属性

示例:

<x:choose>
    <x:when select="$output//item/category = 'Sneakers'">
        项目类别是运动鞋
    </x:when>
    <x:when select="$output//item/category = 'Heels'">
        项目类别是高跟鞋
    </x:when>
    <x:otherwise>
       未知类别。
    </x:otherwise>
</x:choose>

5.7. <x:transform><x:param> 标签

<x:transform> 通过应用 XSL 样式表转换 JSP 中的 XML 文档。

待转换的 XML 文档/字符串通过 doc 属性指定,XSL 样式表通过 xslt 属性指定。

<x:param> 是其子标签,用于设置转换样式表中的参数。示例:

<c:import url="/items_xml" var="xslt"/>
<x:transform xml="${xmltext}" xslt="${xslt}">
    <x:param name="bgColor" value="blue"/>
</x:transform>

6. SQL 标签

JSTL SQL 标签库提供执行关系数据库操作的标签。

使用前需添加:

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

支持 MySQL、Oracle 和 SQL Server 等数据库。

6.1. <sql:setDataSource> 标签

<sql:setDataSource> 定义 JDBC 配置变量。

配置变量存储在 driverurluserpassworddataSource 属性中。示例:

<sql:setDataSource var="dataSource" driver="com.mysql.cj.jdbc.Driver"
  url="jdbc:mysql://localhost/test" user="root" password=""/>

var 属性标识关联的数据库。

6.2. <sql:query> 标签

<sql:query> 执行 SQL SELECT 语句,结果存储在 var 属性指定的作用域变量中。典型用法:

<sql:query dataSource="${dataSource}" var="result">
    SELECT * from USERS;
</sql:query>

sql 属性保存要执行的 SQL 命令。其他属性包括 maxRowsstartRowdataSource

6.3. <sql:update> 标签

<sql:update> 类似 <sql:query>,但只执行不需要返回值的 INSERT、UPDATE 或 DELETE 操作。示例:

<sql:update dataSource="${dataSource}" var="count">
    INSERT INTO USERS(first_name, last_name, email) VALUES
      ('Grace', 'Adams', 'grace@example.com');
</sql:update>

var 属性存储受 SQL 语句影响的行数。

6.4. <sql:param> 标签

<sql:param> 是子标签,用于在 <sql:query><sql:update> 中为 SQL 语句的占位符提供值。示例:

<sql:update dataSource = "${dataSource}" var = "count">
    DELETE FROM USERS WHERE email = ?
    <sql:param value = "grace@example.com" />
</sql:update>

value 属性指定要提供的值。

6.5. <sql:dateParam> 标签

<sql:dateParam><sql:query><sql:update> 中为 SQL 语句的占位符提供日期时间值。示例:

<sql:update dataSource = "${dataSource}" var = "count">
    UPDATE Users SET registered = ? WHERE email = ?
    <sql:dateParam value = "<%=registered%>" type = "DATE" />
    <sql:param value = "<%=email%>" />
</sql:update>

类似 <sql:param>,但增加 type 属性,可选 datetimetimestamp

6.6. <sql:transaction> 标签

<sql:transaction> 通过组合 <sql:query><sql:update> 创建事务操作。示例:

<sql:transaction dataSource = "${dataSource}">
    <sql:update var = "count">
        UPDATE Users SET first_name = 'Patrick-Ellis' WHERE
          email='patrick@example.com'
    </sql:update>
    <sql:update var = "count">
        UPDATE Users SET last_name = 'Nelson' WHERE 
          email ='patrick@example.com'
    </sql:update>
    <sql:update var = "count">
        INSERT INTO Users(first_name, last_name, email) 
          VALUES ('Grace', 'Adams', 'grace@example.com');
    </sql:update>
</sql:transaction>

确保所有数据库操作要么全部成功提交,要么在出错时全部回滚。

7. JSTL 函数

JSTL 函数是 JSP 中数据处理的工具集。虽然部分函数支持多种数据类型,但大多数专用于字符串操作。使用前需添加:

<%@ taglib prefix = "fn"
  uri = "http://java.sun.com/jsp/jstl/functions" %>

7.1. fn:contains()fn:containsIgnoreCase()

fn:contains() 检查字符串是否包含指定子串:

<c:set var = "string1" value = "This is first string"/>
<c:if test = "${fn:contains(string1, 'first')}">
    <p>找到 'first'<p>
</c:if>

fn:containsIgnoreCase() 是不区分大小写的变体:

<c:if test = "${fn:containsIgnoreCase(string1, 'first')}">
    <p>找到 'first'<p>
</c:if>
<c:if test = "${fn:containsIgnoreCase(string1, 'FIRST')}">
    <p>找到 'FIRST'<p>
</c:if>

7.3. fn:endsWith() 函数

fn:endsWith() 检查字符串后缀是否匹配指定子串:

<c:if test = "${fn:endsWith(string1, 'string')}">
    <p>字符串以 'string' 结尾<p>
</c:if>

7.4. fn:escapeXml() 函数

fn:escapeXml() 转义输入字符串中的 XML 标记:

<p>${fn:escapeXml(string1)}</p>

7.5. fn:indexOf() 函数

fn:indexOf() 返回子串首次出现的索引:

<p>索引位置: ${fn:indexOf(string1, "first")}</p>

7.6. fn:join() 函数

fn:join() 将数组所有元素连接为单个字符串:

<c:set var = "string3" value = "${fn:split(string1, ' ')}" />
<c:set var = "string4" value = "${fn:join(string3, '-')}" />

7.7. fn:length() 函数

fn:length() 返回集合元素数或字符串字符数:

<p>长度: ${fn:length(string1)}</p>

7.8. fn:replace() 函数

fn:replace() 替换字符串中所有出现的子串:

<c:set var = "string3" value = "${fn:replace(string1, 'first', 'third')}" />

7.9. fn:split() 函数

fn:split() 按指定分隔符分割字符串:

<c:set var = "string3" value = "${fn:split(string1, ' ')}" />

7.10. fn:startsWith() 函数

fn:startsWith() 检查字符串前缀是否匹配指定子串:

<c:if test = "${fn:startsWith(string1, 'This')}">
    <p>字符串以 'This' 开头</p>
</c:if>

7.11. fn:substring() 函数

fn:substring() 从源字符串创建子串:

<c:set var = "string3" value = "${fn:substring(string1, 5, 15)}" />

7.12. fn:substringAfter() 函数

fn:substringAfter() 返回子串首次出现后的字符串部分:

<c:set var = "string3" value = "${fn:substringAfter(string1, 'is')}" />

7.13. fn:substringBefore() 函数

fn:substringBefore() 返回子串首次出现前的字符串部分:

<c:set var = "string3" value = "${fn:substringBefore(string1, 'is')}" />

7.14. fn:toLowerCase() 函数

fn:toLowerCase() 将字符串转为小写:

<c:set var = "string3" value = "${fn:toLowerCase(string1)}" />

7.15. fn:toUpperCase() 函数

fn:toUpperCase() 将字符串转为大写:

<c:set var = "string3" value = "${fn:toUpperCase(string1)}" />

7.16. fn:trim() 函数

fn:trim() 移除字符串首尾空白:

<c:set var = "string1" value = "This is first String    "/>

9. 总结

本文全面介绍了 JSTL 各类标签及其使用方法。通过合理运用这些标签,可以显著提升 JSP 开发效率,减少脚本代码,增强可维护性。

代码示例可在 GitHub 获取。


原始标题:A Guide to the JSTL Library

« 上一篇: Spring Boot CLI 介绍
» 下一篇: Java Weekly, 第224期