EL与 JSTL 实践
一. EL(Expression Language)
EL(表达式语言)是 JSP 2.0 中引入的一种简单的脚本语言,用于在 JSP 页面中简化数据的访问和显示。它通过一种类似于 JavaScript 的语法,允许开发者在 JSP 页面中直接访问 JavaBean 的属性、集合、甚至是 Java 类的静态字段和方法。
1、 EL 的基本语法
EL 表达式的语法格式为 ${}
,例如:
jsp
${requestScope.userName}
2、 EL 的变量
EL 变量是自动创建的,您无需显式声明。以下是一些常见的变量:
-
隐式变量:
pageScope
:当前页面的作用域。requestScope
:请求作用域。sessionScope
:会话作用域。applicationScope
:应用作用域。
-
用户定义变量 :
使用 JSTL 的
<c:set>
标签可以自定义变量,例如:jsp<c:set var="title" value="EL 示例" scope="page"/> ${title}
3、EL 的操作符
EL 支持多种操作符,包括:
- 算术操作符 :
+
,-
,*
,/
,%
,div
,mul
。 - 比较操作符 :
==
,eq
,!=
,neq
,>
,gt
,<
,lt
。 - 逻辑操作符 :
&&
,and
,||
,or
,not
,!
。 - 空检查操作符 :
empty
(检查对象是否为空)。
示例:
jsp
${10 + 5} <!-- 算术操作 -->
${user.age > 18} <!-- 比较操作 -->
${!empty user.name} <!-- 空检查 -->
4、EL 的使用场景
-
访问 JavaBean 的属性:
jsp<jsp:useBean id="user" class="com.example.User" scope="request"/> 用户名称:${user.name}
-
遍历集合:
jsp<c:forEach items="${users}" var="user"> ${user.name} </c:forEach>
-
条件判断:
jsp<c:if test="${user.age > 18}"> 成人用户 </c:if>
-
格式化输出:
jsp<fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd"/>
二. JSTL(JavaServer Pages Standard Tag Library)
JSTL 是 Java 社区为了简化 JSP 页面开发而推出的一组标准标签库。它提供了多种功能标签,涵盖了常见的 Web 开发需求。
1、 JSTL 的核心标签库
JSTL 分为四个主要模块:
- 核心标签库:用于流程控制、集合操作、数据处理等。
- 格式化标签库:用于日期、时间、数字等格式化。
- 数据库标签库:用于简化 JDBC 操作。
- XML 标签库:用于 XML 数据的处理。
核心标签库(core)
以下是核心标签库中常用的标签:
-
<c:out> :
用于输出数据,支持 HTML 转义。
jsp<c:out value="${user.name}" default="未知"/>
-
<c:forEach> :
用于遍历集合或数组。
jsp<c:forEach items="${users}" var="user" varStatus="status"> ${status.index}: ${user.name} </c:forEach>
-
<c:forTokens> :
用于遍历字符串标记。
jsp<c:forTokens items="a,b,c" delims=","> ${token} </c:forTokens>
-
<c:if> :
用于条件判断。
jsp<c:if test="${user.age > 18}"> 成人用户 </c:if>
-
<c:choose> :
用于多分支条件判断。
jsp<c:choose> <c:when test="${user.age > 18}">成人用户</c:when> <c:otherwise>未成年用户</c:otherwise> </c:choose>
-
<c:set> :
用于设置变量。
jsp<c:set var="title" value="JSTL 示例" scope="page"/> ${title}
-
<c:remove> :
用于删除变量。
jsp<c:remove var="title" scope="page"/>
-
<c:import> :
用于导入其他资源(如 HTML 文件、JSP 页面)。
jsp<c:import url="http://example.com/header.html"/>
-
<c:param> :
用于在导入资源时传递参数。
jsp<c:import url="detail.jsp"> <c:param name="id" value="123"/> </c:import>
-
<c:redirect> :
用于页面跳转。
jsp<c:redirect url="/login.jsp"/>
格式化标签库(fmt)
-
fmt:setLocale :
设置Locale。
jsp<fmt:setLocale value="zh_CN"/>
-
fmt:bundle :
加载资源文件。
jsp<fmt:bundle basename="messages"> <fmt:message key="welcome.message"/> </fmt:bundle>
-
fmt:formatDate :
格式化日期。
jsp<fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd"/>
-
fmt:formatNumber :
格式化数字。
jsp<fmt:formatNumber value="12345.678" pattern="#,###.##"/>
数据库标签库(sql)
-
sql:setDataSource :
设置数据源。
jsp<sql:setDataSource var="dataSource" driver="com.mysql.cj.jdbc.Driver" url="jdbc:mysql://localhost:3306/testdb" user="root" password="password"/>
-
sql:query :
执行查询。
jsp<sql:query dataSource="${dataSource}" sql="SELECT * FROM users"> ${users} </sql:query>
-
sql:update :
执行更新(插入、删除、修改)。
jsp<sql:update dataSource="${dataSource}" sql="INSERT INTO users (name, email) VALUES ('John Doe', '[email protected]')"/>
2、 JSTL 的使用场景
-
简化流程控制:
jsp<c:forEach items="${users}" var="user"> <p>用户 ${user.name}</p> </c:forEach>
-
格式化数据:
jsp<fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd"/>
-
数据库操作:
jsp<sql:query var="users" sql="SELECT * FROM users"> <c:forEach items="${users.rows}" var="user"> ${user.name} </c:forEach> </sql:query>
-
国际化:
jsp<fmt:setLocale value="${param.locale}"/> <fmt:bundle basename="messages"> <h1><fmt:message key="welcome.message"/></h1> </fmt:bundle>
三. 实践:数据显示与分页
以下是一个完整的实践示例,展示如何使用 EL 和 JSTL 实现数据显示与分页功能。
1、 准备工作
-
创建数据库表:
sqlCREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), email VARCHAR(100) );
-
添加测试数据:
sqlINSERT INTO users (name, email) VALUES ('John Doe', '[email protected]'), ('Jane Smith', '[email protected]'), ('Bob Johnson', '[email protected]');
-
添加依赖 :
在
pom.xml
中添加 JSTL 和 MySQL Connector/J 的依赖:xml<dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>
2、 JSP 页面实现
以下是一个完整的 JSP 页面示例,展示数据显示和分页功能。
jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<html>
<head>
<title>用户管理 - 数据显示与分页</title>
</head>
<body>
<h1>用户管理系统</h1>
<%
// 定义每页显示的记录数
int pageSize = 5;
// 获取当前页码(默认为第 1 页)
int currentPage = 1;
if (request.getParameter("currentPage") != null) {
currentPage = Integer.parseInt(request.getParameter("currentPage"));
}
// 总记录数
int totalRecords = 0;
// 计算总记录数
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "password");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM users");
if (rs.next()) {
totalRecords = rs.getInt(1);
}
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
%>
<c:set var="pageSize" value="<%=pageSize%>"/>
<c:set var="currentPage" value="<%=currentPage%>"/>
<c:set var="totalRecords" value="<%=totalRecords%>"/>
<c:if test="${totalRecords > 0}">
<sql:setDataSource var="dataSource"
driver="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/testdb"
user="root"
password="password"/>
<sql:query dataSource="${dataSource}" sql="SELECT * FROM users LIMIT ${currentPage-1}, ${pageSize}" var="users"/>
<div>
<h2>用户列表(第 ${currentPage} 页 / 共 ${totalRecords} 条记录)</h2>
<table border="1">
<tr>
<th>序号</th>
<th>用户姓名</th>
<th>用户邮箱</th>
</tr>
<c:forEach items="${users.rows}" var="user" varStatus="status">
<tr>
<td>${status.index + 1}</td>
<td>${user.name}</td>
<td>${user.email}</td>
</tr>
</c:forEach>
</table>
</div>
<!-- 分页导航 -->
<div style="margin-top: 20px;">
<c:if test="${currentPage > 1}">
<a href="?currentPage=${currentPage-1}">上一页</a>
</c:if>
<c:forEach begin="1" end="${totalRecords / pageSize + 1}" var="page">
<c:choose>
<c:when test="${page == currentPage}">
<span style="color: red;">${page}</span>
</c:when>
<c:otherwise>
<a href="?currentPage=${page}">${page}</a>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${currentPage < totalRecords / pageSize + 1}">
<a href="?currentPage=${currentPage+1}">下一页</a>
</c:if>
</div>
</c:if>
</body>
</html>
3、 功能说明
- 数据显示 :
- 使用
<sql:query>
标签执行 SQL 查询,获取用户数据。 - 使用
<c:forEach>
标签遍历结果集,显示用户信息。
- 使用
- 分页功能 :
- 计算总记录数和每页显示的记录数。
- 使用
<c:forEach>
标签生成分页导航链接。 - 通过
currentPage
参数控制当前显示的页码。
- EL 的使用 :
- 使用 EL 表达式
${}
来访问变量和显示数据。 - 支持复杂的逻辑操作和格式化输出。
- 使用 EL 表达式
四. 总结
通过本讲义,您已经掌握了 EL 和 JSTL 的核心功能及其在实际开发中的应用。EL 和 JSTL 的优势在于:
- 简化代码:通过标签代替 Java 脚本,降低代码复杂度。
- 提高可维护性:将逻辑和展示分离,使代码更易维护。
- 跨平台支持:支持多种数据源和数据库。