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', 'john@example.com')"/>  

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', 'john@example.com'),  
        ('Jane Smith', 'jane@example.com'),  
        ('Bob Johnson', 'bob@example.com');  
  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. 跨平台支持:支持多种数据源和数据库。
相关推荐
泡茶喝茶写代码29 分钟前
A股量化数据工程:从 REST 接口到策略信号(第 8 篇):成长能力因子:营收与利润增速
java·python·股票数据api·股票数据api接口·股票量化数据api·股票量化数据接口·股票数据api数据
\光辉岁月/1 小时前
7.javase-面向对象
java·开发语言
weixin_531094691 小时前
heap_4内存管理
java·开发语言·算法
程序员南飞2 小时前
win系统安装minio
java·数据结构·算法
Escalating_xu2 小时前
【Python】使用库:标准库、第三方库、pip、项目实战与程序打包
java·python·pip
Wang's Blog2 小时前
Java框架 SpringCloud 快速入门: 过滤器链执行顺序
java·spring cloud
砚底藏山河3 小时前
量化实战:回测数据底座快照与版本管理进阶
java·大数据·python·金融·maven
Cc.Y3 小时前
Java零基础入门:封装与继承 —— 从“裸奔“到“穿衣服“,从“重复造轮子“到“站在巨人肩膀上“
java·开发语言
Escalating_xu3 小时前
【C 语言】深入理解指针(4):回调函数、qsort、void * 与泛型排序的模拟实现
java·c语言·开发语言
Shaoshing3 小时前
雪花算法
java