JSTL标签库详解
JSTL概述
JSTL(JavaServer Pages Standard Tag Library,JSP标准标签库)是一个用于JSP页面的标准标签库,提供了在JSP页面中进行通用操作的标签集合,如流程控制、循环、数据格式化、XML操作和数据库访问等。
使用JSTL可以减少JSP页面中的Java脚本代码,使页面更加简洁和易于维护,同时增强了代码的可读性和重用性。
JSTL的分类
JSTL标签库分为以下几个主要部分:
- 核心标签库(Core):提供流程控制、变量操作等基础功能
- 格式化标签库(Formatting):处理数据格式化,如日期、数字等
- SQL标签库(SQL):提供数据库访问功能
- XML标签库(XML):处理XML文档
- 函数标签库(Functions):提供字符串操作、集合操作等常用函数
JSTL的安装与配置
1. 下载JSTL库
要使用JSTL,需要下载JSTL的JAR包:
- JSTL API:
javax.servlet.jsp.jstl-api.jar - JSTL实现:
jstl-impl.jar(GlassFish实现)或taglibs-standard-impl.jar(Apache实现)
2. 添加依赖
Maven项目:在pom.xml中添加依赖:
<dependencies>
<!-- JSTL API -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
<version>1.2.1</version>
</dependency>
<!-- JSTL实现 -->
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.servlet.jsp.jstl</artifactId>
<version>1.2.5</version>
</dependency>
</dependencies>Gradle项目:在build.gradle中添加依赖:
dependencies {
// JSTL API
implementation 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1'
// JSTL实现
implementation 'org.glassfish.web:javax.servlet.jsp.jstl:1.2.5'
}3. 在JSP页面中引入JSTL
在需要使用JSTL的JSP页面顶部添加标签库声明:
<%-- 引入核心标签库 --%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- 引入格式化标签库 --%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%-- 引入XML标签库 --%>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<%-- 引入SQL标签库 --%>
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
<%-- 引入函数标签库 --%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>核心标签库(Core)
核心标签库是最常用的JSTL标签,提供了流程控制、变量操作和URL处理等功能。
1. 变量操作标签
<c:set> - 设置变量
用于设置变量值或对象属性。
语法:
<%-- 设置变量到指定作用域 --%>
<c:set var="变量名" value="变量值" scope="作用域"/>
<%-- 设置对象属性 --%>
<c:set target="目标对象" property="属性名" value="属性值"/>
<%-- 使用标签体设置值 --%>
<c:set var="变量名" scope="作用域">
变量值内容
</c:set>作用域:page、request、session、application
示例:
<%-- 设置字符串变量到请求作用域 --%>
<c:set var="message" value="Hello JSTL" scope="request"/>
<%-- 设置对象属性 --%>
<c:set target="${user}" property="username" value="admin"/>
<%-- 使用标签体设置多行文本 --%>
<c:set var="welcomeMessage">
Welcome to our website!
Enjoy your stay.
</c:set><c:remove> - 移除变量
从指定作用域中移除变量。
语法:
<c:remove var="变量名" scope="作用域"/>示例:
<c:remove var="message" scope="request"/><c:out> - 输出变量
输出变量内容,可自动进行HTML转义,防止XSS攻击。
语法:
<c:out value="变量值" default="默认值" escapeXml="true|false"/>示例:
<%-- 基本输出 --%>
<c:out value="${message}"/>
<%-- 带默认值的输出 --%>
<c:out value="${username}" default="Guest"/>
<%-- 禁用HTML转义 --%>
<c:out value="${htmlContent}" escapeXml="false"/>2. 流程控制标签
<c:if> - 条件判断
简单的条件判断,相当于Java中的if语句。
语法:
<c:if test="条件表达式" var="变量名" scope="作用域">
条件为真时执行的内容
</c:if>示例:
<c:if test="${user.role == 'admin'}">
<p>欢迎管理员!</p>
<button>管理系统</button>
</c:if>
<%-- 将判断结果保存到变量 --%>
<c:if test="${cart.totalItems > 0}" var="hasItems" scope="request">
<p>您的购物车中有商品</p>
</c:if><c:choose>、<c:when>、<c:otherwise> - 多条件判断
相当于Java中的switch-case语句,用于多条件分支判断。
语法:
<c:choose>
<c:when test="条件表达式1">
条件1为真时执行的内容
</c:when>
<c:when test="条件表达式2">
条件2为真时执行的内容
</c:when>
<c:otherwise>
所有条件都为假时执行的内容
</c:otherwise>
</c:choose>示例:
<c:choose>
<c:when test="${score >= 90}">
<p>成绩优秀!</p>
</c:when>
<c:when test="${score >= 80}">
<p>成绩良好!</p>
</c:when>
<c:when test="${score >= 60}">
<p>成绩及格!</p>
</c:when>
<c:otherwise>
<p>成绩不及格!</p>
</c:otherwise>
</c:choose>3. 循环标签
<c:forEach> - 循环迭代
用于循环迭代集合、数组或特定范围的数字。
语法:
<%-- 迭代集合或数组 --%>
<c:forEach items="集合或数组" var="当前元素" varStatus="状态变量" begin="开始索引" end="结束索引" step="步长">
循环体内容
</c:forEach>
<%-- 迭代数字范围 --%>
<c:forEach var="变量" begin="起始值" end="结束值" step="步长" varStatus="状态变量">
循环体内容
</c:forEach>varStatus属性:提供当前循环状态的对象,包含以下属性:
index:当前元素的索引(从0开始)count:当前循环的次数(从1开始)first:是否是第一次循环last:是否是最后一次循环begin:循环开始的索引end:循环结束的索引step:循环的步长
示例:
<%-- 迭代集合 --%>
<c:forEach items="${products}" var="product">
<div class="product">
<h3>${product.name}</h3>
<p>价格:${product.price}</p>
</div>
</c:forEach>
<%-- 使用状态变量 --%>
<c:forEach items="${users}" var="user" varStatus="status">
<tr class="${status.even ? 'even' : 'odd'}">
<td>${status.count}</td>
<td>${user.username}</td>
<td>${user.email}</td>
</tr>
</c:forEach>
<%-- 迭代数字范围 --%>
<c:forEach var="i" begin="1" end="10" step="2">
<p>第${i}个元素</p>
</c:forEach><c:forTokens> - 分隔字符串迭代
根据指定分隔符分割字符串并进行迭代。
语法:
<c:forTokens items="要分割的字符串" delims="分隔符" var="当前元素" varStatus="状态变量">
循环体内容
</c:forTokens>示例:
<%-- 分割逗号分隔的字符串 --%>
<c:forTokens items="Java,Python,C++,JavaScript" delims="," var="language">
<p>${language}</p>
</c:forTokens>
<%-- 使用多个分隔符 --%>
<c:forTokens items="apple;orange,banana pear" delims=";, " var="fruit">
<p>${fruit}</p>
</c:forTokens>4. URL操作标签
<c:url> - 构建URL
用于构建URL,可以自动进行URL重写,支持会话跟踪。
语法:
<%-- 直接输出URL --%>
<c:url value="目标URL" context="上下文路径" var="变量名" scope="作用域">
<c:param name="参数名" value="参数值"/>
...
</c:url>示例:
<%-- 基本URL构建 --%>
<c:url value="/user/profile"/>
<%-- 保存到变量 --%>
<c:url value="/product/detail" var="productUrl">
<c:param name="id" value="123"/>
<c:param name="category" value="electronics"/>
</c:url>
<a href="${productUrl}">查看产品详情</a>
<%-- 跨上下文路径 --%>
<c:url value="/login" context="/auth"/><c:redirect> - 页面重定向
用于重定向到另一个页面。
语法:
<c:redirect url="目标URL" context="上下文路径">
<c:param name="参数名" value="参数值"/>
...
</c:redirect>示例:
<%-- 基本重定向 --%>
<c:redirect url="/login"/>
<%-- 带参数的重定向 --%>
<c:redirect url="/dashboard">
<c:param name="message" value="登录成功"/>
</c:redirect><c:import> - 引入外部资源
用于引入外部资源的内容,可以是同服务器或远程服务器的资源。
语法:
<c:import url="资源URL" context="上下文路径" var="变量名" scope="作用域" charEncoding="字符编码">
<c:param name="参数名" value="参数值"/>
...
</c:import>示例:
<%-- 引入本地资源 --%>
<c:import url="/includes/header.jsp"/>
<%-- 引入远程资源 --%>
<c:import url="https://api.example.com/data" var="remoteData"/>
<div>${remoteData}</div>
<%-- 带参数的引入 --%>
<c:import url="/data/report" var="reportContent">
<c:param name="type" value="daily"/>
<c:param name="date" value="2023-05-01"/>
</c:import>格式化标签库(Formatting)
格式化标签库用于格式化数字、日期、货币等数据。
1. 数字和货币格式化
<fmt:formatNumber> - 格式化数字
格式化数字、货币或百分比。
语法:
<fmt:formatNumber value="数字值" type="number|currency|percent"
pattern="自定义模式"
currencyCode="货币代码"
currencySymbol="货币符号"
groupingUsed="true|false"
maxIntegerDigits="最大整数位数"
minIntegerDigits="最小整数位数"
maxFractionDigits="最大小数位数"
minFractionDigits="最小小数位数"
var="变量名"
scope="作用域"/>示例:
<%-- 格式化普通数字 --%>
<fmt:formatNumber value="123456.789"/>
<%-- 输出: 123,456.789 --%>
<%-- 格式化货币 --%>
<fmt:formatNumber value="1234.56" type="currency"/>
<%-- 输出取决于本地设置,例如: ¥1,234.56 --%>
<%-- 指定货币代码 --%>
<fmt:formatNumber value="1234.56" type="currency" currencyCode="USD"/>
<%-- 输出: USD1,234.56 --%>
<%-- 格式化百分比 --%>
<fmt:formatNumber value="0.75" type="percent"/>
<%-- 输出: 75% --%>
<%-- 自定义格式模式 --%>
<fmt:formatNumber value="12345.678" pattern="#,#00.0#"/>
<%-- 输出: 12,345.68 --%><fmt:parseNumber> - 解析数字
将字符串解析为数字。
语法:
<fmt:parseNumber value="字符串" type="number|currency|percent"
pattern="自定义模式"
parseLocale="解析区域"
integerOnly="true|false"
var="变量名"
scope="作用域"/>示例:
<%-- 解析普通数字 --%>
<fmt:parseNumber value="123,456.78" var="numberValue"/>
<p>解析结果: ${numberValue}</p>
<%-- 解析货币 --%>
<fmt:parseNumber value="¥1,234.56" type="currency" var="currencyValue"/>
<p>解析结果: ${currencyValue}</p>
<%-- 解析百分比 --%>
<fmt:parseNumber value="75%" type="percent" var="percentValue"/>
<p>解析结果: ${percentValue}</p>2. 日期和时间格式化
<fmt:formatDate> - 格式化日期
格式化日期和时间。
语法:
<fmt:formatDate value="日期对象" type="date|time|both"
pattern="自定义模式"
dateStyle="默认日期格式"
timeStyle="默认时间格式"
timeZone="时区"
var="变量名"
scope="作用域"/>dateStyle/timeStyle值:default、short、medium、long、full
示例:
<%-- 设置当前日期到请求作用域 --%>
<c:set var="now" value="<%= new java.util.Date() %>"/>
<%-- 格式化日期(默认)--%>
<fmt:formatDate value="${now}"/>
<%-- 输出取决于本地设置,例如: 2023-5-1 --%>
<%-- 格式化时间 --%>
<fmt:formatDate value="${now}" type="time"/>
<%-- 输出取决于本地设置,例如: 14:30:45 --%>
<%-- 格式化日期和时间 --%>
<fmt:formatDate value="${now}" type="both"/>
<%-- 输出取决于本地设置,例如: 2023-5-1 14:30:45 --%>
<%-- 使用预定义样式 --%>
<fmt:formatDate value="${now}" type="both" dateStyle="full" timeStyle="full"/>
<%-- 输出: 2023年5月1日 星期一 下午02时30分45秒 CST --%>
<%-- 自定义格式模式 --%>
<fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss"/>
<%-- 输出: 2023-05-01 14:30:45 --%>
<%-- 指定时区 --%>
<fmt:formatDate value="${now}" type="both" timeZone="America/New_York"/><fmt:parseDate> - 解析日期
将字符串解析为日期对象。
语法:
<fmt:parseDate value="日期字符串" type="date|time|both"
pattern="自定义模式"
dateStyle="默认日期格式"
timeStyle="默认时间格式"
timeZone="时区"
parseLocale="解析区域"
var="变量名"
scope="作用域"/>示例:
<%-- 解析日期字符串 --%>
<fmt:parseDate value="2023-05-01" pattern="yyyy-MM-dd" var="dateValue"/>
<p>解析结果: ${dateValue}</p>
<%-- 解析日期时间字符串 --%>
<fmt:parseDate value="2023-05-01 14:30:45" pattern="yyyy-MM-dd HH:mm:ss" var="dateTimeValue"/>
<p>解析结果: ${dateTimeValue}</p>3. 国际化和本地化
<fmt:setLocale> - 设置区域
设置当前页面的区域。
语法:
<fmt:setLocale value="区域代码" variant="区域变体" scope="作用域"/>示例:
<%-- 设置为美国英语 --%>
<fmt:setLocale value="en_US"/>
<%-- 设置为中文简体 --%>
<fmt:setLocale value="zh_CN"/><fmt:setBundle> - 加载资源束
加载资源束(属性文件),用于国际化。
语法:
<fmt:setBundle basename="资源束基础名称" var="变量名" scope="作用域"/>示例:
<%-- 加载资源束 --%>
<fmt:setBundle basename="messages" var="msg"/>
<%-- 使用资源束 --%>
<fmt:message bundle="${msg}" key="welcome"/><fmt:message> - 输出本地化消息
输出资源束中的本地化消息。
语法:
<fmt:message key="消息键" bundle="资源束" var="变量名" scope="作用域">
<fmt:param value="参数值"/>
...
</fmt:message>示例:
<%-- 基本消息输出 --%>
<fmt:message key="welcome"/>
<%-- 带参数的消息 --%>
<fmt:message key="greeting">
<fmt:param value="${username}"/>
</fmt:message>
<%-- 使用指定资源束 --%>
<fmt:message bundle="${msg}" key="error.notFound"/><fmt:requestEncoding> - 设置请求编码
设置请求的字符编码。
语法:
<fmt:requestEncoding value="字符编码"/>示例:
<%-- 设置请求编码为UTF-8 --%>
<fmt:requestEncoding value="UTF-8"/>XML标签库(XML)
XML标签库提供了处理XML文档的功能,如解析、导航和转换。
1. XML解析和转换
<x:parse> - 解析XML
解析XML文档。
语法:
<x:parse var="变量名" scope="作用域" xml="XML字符串" systemId="系统ID" doc="XML文档" filter="过滤器"/>示例:
<%-- 解析XML字符串 --%>
<c:set var="xmlString">
<users>
<user id="1">
<name>张三</name>
<email>zhangsan@example.com</email>
</user>
<user id="2">
<name>李四</name>
<email>lisi@example.com</email>
</user>
</users>
</c:set>
<x:parse xml="${xmlString}" var="doc"/><x:transform> - XSLT转换
使用XSLT转换XML文档。
语法:
<x:transform xml="XML字符串" doc="XML文档" xslt="XSLT字符串" docSystemId="XML系统ID" xsltSystemId="XSLT系统ID" var="变量名" scope="作用域"/>示例:
<%-- 定义XSLT --%>
<c:set var="xsltString">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>用户列表</h2>
<table border="1">
<tr>
<th>ID</th>
<th>姓名</th>
<th>邮箱</th>
</tr>
<xsl:for-each select="users/user">
<tr>
<td><xsl:value-of select="@id"/></td>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="email"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
</c:set>
<%-- 应用XSLT转换 --%>
<x:transform xml="${xmlString}" xslt="${xsltString}"/>2. XML导航和提取
<x:out> - 输出XML元素内容
输出XML元素或属性的内容。
语法:
<x:out select="XPath表达式" escapeXml="true|false"/>示例:
<%-- 输出XML元素内容 --%>
<x:out select="$doc/users/user[1]/name"/>
<%-- 输出XML属性值 --%>
<x:out select="$doc/users/user[1]/@id"/><x:set> - 设置XML元素内容到变量
将XML元素或属性的内容设置到变量。
语法:
<x:set var="变量名" select="XPath表达式" scope="作用域"/>示例:
<x:set var="firstUserName" select="$doc/users/user[1]/name"/>
<p>第一个用户的姓名: ${firstUserName}</p><x:if> - XML条件判断
基于XML内容进行条件判断。
语法:
<x:if select="XPath表达式" var="变量名" scope="作用域">
条件为真时执行的内容
</x:if>示例:
<x:if select="$doc/users/user[@id='1']">
<p>ID为1的用户存在</p>
</x:if><x:forEach> - 遍历XML元素
遍历XML元素集合。
语法:
<x:forEach select="XPath表达式" var="变量名" varStatus="状态变量">
循环体内容
</x:forEach>示例:
<x:forEach select="$doc/users/user" var="user">
<div class="user">
<p>ID: <x:out select="$user/@id"/></p>
<p>姓名: <x:out select="$user/name"/></p>
<p>邮箱: <x:out select="$user/email"/></p>
</div>
</x:forEach><x:choose>、<x:when>、<x:otherwise> - XML多条件判断
基于XML内容进行多条件分支判断。
语法:
<x:choose>
<x:when select="XPath表达式1">
条件1为真时执行的内容
</x:when>
<x:when select="XPath表达式2">
条件2为真时执行的内容
</x:when>
<x:otherwise>
所有条件都为假时执行的内容
</x:otherwise>
</x:choose>示例:
<x:forEach select="$doc/users/user" var="user">
<div class="user">
<p>姓名: <x:out select="$user/name"/></p>
<x:choose>
<x:when select="$user/@id='1'">
<p>VIP用户</p>
</x:when>
<x:when select="$user/@id='2'">
<p>普通用户</p>
</x:when>
<x:otherwise>
<p>新用户</p>
</x:otherwise>
</x:choose>
</div>
</x:forEach>SQL标签库(SQL)
SQL标签库提供了在JSP页面中直接访问数据库的功能。虽然在实际项目中不推荐在视图层直接操作数据库,但在简单应用或快速原型开发中可能有用。
1. 数据库连接
<sql:setDataSource> - 设置数据源
设置数据库连接信息。
语法:
<sql:setDataSource var="变量名" scope="作用域" driver="驱动类" url="数据库URL" user="用户名" password="密码" dataSource="数据源对象"/>示例:
<%-- 设置数据库连接 --%>
<sql:setDataSource var="dataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/testdb"
user="root"
password="password"/>
<%-- 使用JNDI数据源 --%>
<sql:setDataSource var="dataSource" dataSource="java:comp/env/jdbc/testdb"/>2. SQL查询
<sql:query> - 执行查询语句
执行SQL查询并将结果保存到变量中。
语法:
<sql:query var="结果变量名" scope="作用域" sql="SQL语句" dataSource="数据源" startRow="起始行" maxRows="最大行数">
<sql:param value="参数值"/>
...
</sql:query>示例:
<%-- 执行简单查询 --%>
<sql:query var="users" dataSource="${dataSource}">
SELECT * FROM users
</sql:query>
<%-- 遍历查询结果 --%>
<table border="1">
<tr>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
</tr>
<c:forEach items="${users.rows}" var="user">
<tr>
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.email}</td>
</tr>
</c:forEach>
</table>
<%-- 使用参数化查询 --%>
<sql:query var="user" dataSource="${dataSource}">
SELECT * FROM users WHERE id = ?
<sql:param value="${param.userId}"/>
</sql:query>3. SQL更新
<sql:update> - 执行更新语句
执行SQL UPDATE、INSERT或DELETE语句。
语法:
<sql:update var="结果变量名" scope="作用域" sql="SQL语句" dataSource="数据源">
<sql:param value="参数值"/>
...
</sql:update>示例:
<%-- 插入数据 --%>
<sql:update dataSource="${dataSource}">
INSERT INTO users (username, email) VALUES (?, ?)
<sql:param value="${param.username}"/>
<sql:param value="${param.email}"/>
</sql:update>
<%-- 更新数据 --%>
<sql:update dataSource="${dataSource}">
UPDATE users SET email = ? WHERE id = ?
<sql:param value="${param.email}"/>
<sql:param value="${param.userId}"/>
</sql:update>
<%-- 删除数据 --%>
<sql:update var="deletedCount" dataSource="${dataSource}">
DELETE FROM users WHERE id = ?
<sql:param value="${param.userId}"/>
</sql:update>
<p>删除了 ${deletedCount} 条记录</p>4. 事务管理
<sql:transaction> - 事务管理
在事务中执行SQL操作。
语法:
<sql:transaction dataSource="数据源" isolation="隔离级别">
SQL操作标签
</sql:transaction>隔离级别:READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE
示例:
<%-- 在事务中执行多个更新操作 --%>
<sql:transaction dataSource="${dataSource}">
<sql:update>
UPDATE accounts SET balance = balance - ? WHERE id = ?
<sql:param value="${param.amount}"/>
<sql:param value="${param.fromAccount}"/>
</sql:update>
<sql:update>
UPDATE accounts SET balance = balance + ? WHERE id = ?
<sql:param value="${param.amount}"/>
<sql:param value="${param.toAccount}"/>
</sql:update>
</sql:transaction>函数标签库(Functions)
函数标签库提供了一组常用的EL函数,用于字符串操作、集合操作等。
1. 字符串操作函数
fn:length() - 获取长度
获取字符串或集合的长度。
语法:${fn:length(对象)}
示例:
<p>字符串长度: ${fn:length('Hello JSTL')}</p>
<p>集合大小: ${fn:length(users)}</p>fn:contains() - 包含子字符串
检查字符串是否包含指定的子字符串。
语法:${fn:contains(字符串, 子字符串)}
示例:
<c:if test="${fn:contains(username, 'admin')}">
<p>用户名包含'admin'</p>
</c:if>fn:containsIgnoreCase() - 忽略大小写包含子字符串
检查字符串是否包含指定的子字符串,忽略大小写。
语法:${fn:containsIgnoreCase(字符串, 子字符串)}
示例:
<c:if test="${fn:containsIgnoreCase(title, 'java')}">
<p>标题包含'java'(忽略大小写)</p>
</c:if>fn:startsWith() - 以子字符串开头
检查字符串是否以指定的子字符串开头。
语法:${fn:startsWith(字符串, 前缀)}
示例:
<c:if test="${fn:startsWith(email, 'admin@')}">
<p>管理员邮箱</p>
</c:if>fn:endsWith() - 以子字符串结尾
检查字符串是否以指定的子字符串结尾。
语法:${fn:endsWith(字符串, 后缀)}
示例:
<c:if test="${fn:endsWith(filename, '.jpg') or fn:endsWith(filename, '.png')}">
<p>图片文件</p>
</c:if>fn:indexOf() - 子字符串索引
获取子字符串在字符串中第一次出现的索引位置。
语法:${fn:indexOf(字符串, 子字符串)}
示例:
<p>@符号位置: ${fn:indexOf(email, '@')}</p>fn:substring() - 截取子字符串
截取字符串的子串。
语法:${fn:substring(字符串, 开始索引, 结束索引)}
示例:
<p>邮箱域名: ${fn:substring(email, fn:indexOf(email, '@') + 1, fn:length(email))}</p>fn:substringBefore() - 截取子字符串之前的部分
截取字符串中指定子字符串之前的部分。
语法:${fn:substringBefore(字符串, 子字符串)}
示例:
<p>邮箱用户名: ${fn:substringBefore(email, '@')}</p>fn:substringAfter() - 截取子字符串之后的部分
截取字符串中指定子字符串之后的部分。
语法:${fn:substringAfter(字符串, 子字符串)}
示例:
<p>文件扩展名: ${fn:substringAfter(filename, '.')}</p>fn:escapeXml() - 转义XML特殊字符
转义XML特殊字符,如<、>、&、"、'。
语法:${fn:escapeXml(字符串)}
示例:
<p>转义后的内容: ${fn:escapeXml(userInput)}</p>fn:trim() - 去除首尾空白
去除字符串首尾的空白字符。
语法:${fn:trim(字符串)}
示例:
<p>去除空白后: ${fn:trim(inputValue)}</p>fn:toLowerCase() - 转换为小写
将字符串转换为小写。
语法:${fn:toLowerCase(字符串)}
示例:
<p>小写邮箱: ${fn:toLowerCase(email)}</p>fn:toUpperCase() - 转换为大写
将字符串转换为大写。
语法:${fn:toUpperCase(字符串)}
示例:
<p>大写用户名: ${fn:toUpperCase(username)}</p>fn:replace() - 替换子字符串
替换字符串中的子字符串。
语法:${fn:replace(字符串, 被替换的子串, 替换的子串)}
示例:
<p>替换后的内容: ${fn:replace(text, 'old', 'new')}</p>fn:split() - 分割字符串
将字符串按指定分隔符分割成字符串数组。
语法:${fn:split(字符串, 分隔符)}
示例:
<c:set var="colors" value="${fn:split('红,绿,蓝,黄', ',')}"/>
<c:forEach items="${colors}" var="color">
<p>${color}</p>
</c:forEach>fn:join() - 连接字符串数组
将字符串数组按指定分隔符连接成字符串。
语法:${fn:join(字符串数组, 分隔符)}
示例:
<c:set var="colors" value="${fn:split('红,绿,蓝,黄', ',')}"/>
<p>连接后的字符串: ${fn:join(colors, ' | ')}</p>2. 集合操作函数
fn:contains() - 集合包含元素
检查集合是否包含指定的元素。
语法:${fn:contains(集合, 元素)}
示例:
<c:if test="${fn:contains(roles, 'admin')}">
<p>用户有管理员权限</p>
</c:if>JSTL最佳实践
1. 减少Java脚本
尽可能使用JSTL标签替代JSP页面中的Java脚本,提高代码的可读性和可维护性。
2. 合理使用EL表达式
结合EL表达式和JSTL标签,可以实现更简洁、更强大的数据访问和显示逻辑。
3. 避免在JSP中直接操作数据库
虽然JSTL提供了SQL标签库,但在实际项目中,应该遵循MVC模式,将数据库操作放在业务逻辑层,而不是视图层。
4. 注意XSS攻击防护
使用<c:out>标签时,设置escapeXml="true"(默认值)以防止XSS攻击。
5. 优化性能
- 避免在循环中执行耗时操作
- 使用
var属性将重复使用的表达式结果保存到变量中 - 合理设置标签的
scope属性,避免不必要的作用域范围
6. 保持页面简洁
不要在JSP页面中放置过多的逻辑,复杂的业务逻辑应该放在Servlet或其他控制器中处理。
7. 使用JSTL进行国际化
利用格式化标签库的国际化功能,可以轻松实现多语言支持。
总结
JSTL标签库是JSP页面开发中的重要工具,提供了丰富的标签和函数,可以大大减少JSP页面中的Java脚本代码,提高页面的可读性和可维护性。核心标签库提供了流程控制、变量操作和URL处理等基础功能;格式化标签库用于处理数据格式化和国际化;XML标签库用于处理XML文档;SQL标签库提供了数据库访问功能(虽然在实际项目中不推荐在视图层使用);函数标签库提供了常用的字符串和集合操作函数。
在实际开发中,应该合理使用JSTL标签,遵循MVC模式,将业务逻辑与视图分离,同时注意安全性和性能优化,构建高质量的Web应用。