16、JavaEE核心技术-EL与 JSTL

EL与 JSTL 实践


一. EL(Expression Language)

EL(表达式语言)是 JSP 2.0 中引入的一种简单的脚本语言,用于在 JSP 页面中简化数据的访问和显示。它通过一种类似于 JavaScript 的语法,允许开发者在 JSP 页面中直接访问 JavaBean 的属性、集合、甚至是 Java 类的静态字段和方法。


1、 EL 的基本语法

EL 表达式的语法格式为 ${},例如:

jsp 复制代码
${requestScope.userName}  
2、 EL 的变量

EL 变量是自动创建的,您无需显式声明。以下是一些常见的变量:

  1. 隐式变量

    • pageScope:当前页面的作用域。
    • requestScope:请求作用域。
    • sessionScope:会话作用域。
    • applicationScope:应用作用域。
  2. 用户定义变量

    使用 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 的使用场景
  1. 访问 JavaBean 的属性

    jsp 复制代码
    <jsp:useBean id="user" class="com.example.User" scope="request"/>  
    用户名称:${user.name}  
  2. 遍历集合

    jsp 复制代码
    <c:forEach items="${users}" var="user">  
        ${user.name}  
    </c:forEach>  
  3. 条件判断

    jsp 复制代码
    <c:if test="${user.age > 18}">  
        成人用户  
    </c:if>  
  4. 格式化输出

    jsp 复制代码
    <fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd"/>  

二. JSTL(JavaServer Pages Standard Tag Library)

JSTL 是 Java 社区为了简化 JSP 页面开发而推出的一组标准标签库。它提供了多种功能标签,涵盖了常见的 Web 开发需求。


1、 JSTL 的核心标签库

JSTL 分为四个主要模块:

  1. 核心标签库:用于流程控制、集合操作、数据处理等。
  2. 格式化标签库:用于日期、时间、数字等格式化。
  3. 数据库标签库:用于简化 JDBC 操作。
  4. XML 标签库:用于 XML 数据的处理。
核心标签库(core)

以下是核心标签库中常用的标签:

  1. <c:out>

    用于输出数据,支持 HTML 转义。

    jsp 复制代码
    <c:out value="${user.name}" default="未知"/>  
  2. <c:forEach>

    用于遍历集合或数组。

    jsp 复制代码
    <c:forEach items="${users}" var="user" varStatus="status">  
        ${status.index}: ${user.name}  
    </c:forEach>  
  3. <c:forTokens>

    用于遍历字符串标记。

    jsp 复制代码
    <c:forTokens items="a,b,c" delims=",">  
        ${token}  
    </c:forTokens>  
  4. <c:if>

    用于条件判断。

    jsp 复制代码
    <c:if test="${user.age > 18}">  
        成人用户  
    </c:if>  
  5. <c:choose>

    用于多分支条件判断。

    jsp 复制代码
    <c:choose>  
        <c:when test="${user.age > 18}">成人用户</c:when>  
        <c:otherwise>未成年用户</c:otherwise>  
    </c:choose>  
  6. <c:set>

    用于设置变量。

    jsp 复制代码
    <c:set var="title" value="JSTL 示例" scope="page"/>  
    ${title}  
  7. <c:remove>

    用于删除变量。

    jsp 复制代码
    <c:remove var="title" scope="page"/>  
  8. <c:import>

    用于导入其他资源(如 HTML 文件、JSP 页面)。

    jsp 复制代码
    <c:import url="http://example.com/header.html"/>  
  9. <c:param>

    用于在导入资源时传递参数。

    jsp 复制代码
    <c:import url="detail.jsp">  
        <c:param name="id" value="123"/>  
    </c:import>  
  10. <c:redirect>

    用于页面跳转。

    jsp 复制代码
    <c:redirect url="/login.jsp"/>  

格式化标签库(fmt)
  1. fmt:setLocale

    设置Locale。

    jsp 复制代码
    <fmt:setLocale value="zh_CN"/>  
  2. fmt:bundle

    加载资源文件。

    jsp 复制代码
    <fmt:bundle basename="messages">  
        <fmt:message key="welcome.message"/>  
    </fmt:bundle>  
  3. fmt:formatDate

    格式化日期。

    jsp 复制代码
    <fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd"/>  
  4. fmt:formatNumber

    格式化数字。

    jsp 复制代码
    <fmt:formatNumber value="12345.678" pattern="#,###.##"/>  

数据库标签库(sql)
  1. sql:setDataSource

    设置数据源。

    jsp 复制代码
    <sql:setDataSource var="dataSource"   
                       driver="com.mysql.cj.jdbc.Driver"   
                       url="jdbc:mysql://localhost:3306/testdb"  
                       user="root"   
                       password="password"/>  
  2. sql:query

    执行查询。

    jsp 复制代码
    <sql:query dataSource="${dataSource}" sql="SELECT * FROM users">  
        ${users}  
    </sql:query>  
  3. sql:update

    执行更新(插入、删除、修改)。

    jsp 复制代码
    <sql:update dataSource="${dataSource}" sql="INSERT INTO users (name, email) VALUES ('John Doe', '[email protected]')"/>  

2、 JSTL 的使用场景
  1. 简化流程控制

    jsp 复制代码
    <c:forEach items="${users}" var="user">  
        <p>用户 ${user.name}</p>  
    </c:forEach>  
  2. 格式化数据

    jsp 复制代码
    <fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd"/>  
  3. 数据库操作

    jsp 复制代码
    <sql:query var="users" sql="SELECT * FROM users">  
        <c:forEach items="${users.rows}" var="user">  
            ${user.name}  
        </c:forEach>  
    </sql:query>  
  4. 国际化

    jsp 复制代码
    <fmt:setLocale value="${param.locale}"/>  
    <fmt:bundle basename="messages">  
        <h1><fmt:message key="welcome.message"/></h1>  
    </fmt:bundle>  

三. 实践:数据显示与分页

以下是一个完整的实践示例,展示如何使用 EL 和 JSTL 实现数据显示与分页功能。


1、 准备工作
  1. 创建数据库表

    sql 复制代码
    CREATE TABLE users (  
        id INT AUTO_INCREMENT PRIMARY KEY,  
        name VARCHAR(50),  
        email VARCHAR(100)  
    );  
  2. 添加测试数据

    sql 复制代码
    INSERT INTO users (name, email) VALUES  
        ('John Doe', '[email protected]'),  
        ('Jane Smith', '[email protected]'),  
        ('Bob Johnson', '[email protected]');  
  3. 添加依赖

    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、 功能说明
  1. 数据显示
    • 使用 <sql:query> 标签执行 SQL 查询,获取用户数据。
    • 使用 <c:forEach> 标签遍历结果集,显示用户信息。
  2. 分页功能
    • 计算总记录数和每页显示的记录数。
    • 使用 <c:forEach> 标签生成分页导航链接。
    • 通过 currentPage 参数控制当前显示的页码。
  3. EL 的使用
    • 使用 EL 表达式 ${} 来访问变量和显示数据。
    • 支持复杂的逻辑操作和格式化输出。

四. 总结

通过本讲义,您已经掌握了 EL 和 JSTL 的核心功能及其在实际开发中的应用。EL 和 JSTL 的优势在于:

  1. 简化代码:通过标签代替 Java 脚本,降低代码复杂度。
  2. 提高可维护性:将逻辑和展示分离,使代码更易维护。
  3. 跨平台支持:支持多种数据源和数据库。
相关推荐
qq_5298353519 分钟前
Java实现死锁
java·开发语言·python
牧小七27 分钟前
Java --- 根据身份证号计算年龄
java·开发语言
字节源流29 分钟前
【SpringMVC】常用注解:@RequestParam
java·开发语言
XMYX-01 小时前
解决 Redis 后台持久化失败的问题:内存不足导致 fork 失败
java·数据库·redis
bigcarp1 小时前
理解langchain langgraph 官方文档示例代码中的MemorySaver
java·前端·langchain
橘猫云计算机设计2 小时前
基于jspm校园安全管理系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·安全·毕业设计
幽络源小助理2 小时前
SpringBoot学生宿舍管理系统的设计与开发
java·spring boot·后端·学生宿舍管理
猿java2 小时前
源码分析:Spring IOC容器初始化过程
java·后端·spring
阿拉保2 小时前
C++复试笔记(四)
java·c++·笔记
蓝莓浆糊饼干3 小时前
请简述一下String、StringBuffer和“equals”与“==”、“hashCode”的区别和使用场景
android·java