EL和JSTL核心技术

153 阅读5分钟

一.EL表达式

EL(Expression Language)表达式提供了在JSP中简化表达式的方法,可以方便地访问各种数据 并输出。

1.1 EL主要功能

依次访问pageContext、request、session和application作用域对象存储的数据。

获取请求参数值。

访问Bean对象的属性。

访问集合中的数据。

输出简单的运算结果

1.2 访问内置对象的数据

访问方式:

image.png 使用setattribute设置对象的数据:

pageContext.setAttribute("name1", "pageContext对象中的属性值:zhangfei");
request.setAttribute("name2", "request对象中的属性值:guanyu");
session.setAttribute("name3", "session对象中的属性值:liubei");
application.setAttribute("name4", "session对象中的属性值:zhaoyun");

再使用JSP中原始的方法获取和打印:

<%-- 使用JSP中原始方式获取数据和打印 --%>
<%--<%= "name1的数值为:" + pageContext.getAttribute("name1") %><br/>   &lt;%&ndash; zhangfei &ndash;%&gt;
<%= "name2的数值为:" + request.getAttribute("name2") %><br/>       &lt;%&ndash; guanyu &ndash;%&gt;
<%= "name3的数值为:" + session.getAttribute("name3") %><br/>       &lt;%&ndash; liubei &ndash;%&gt;
<%= "name4的数值为:" + application.getAttribute("name4") %><br/>   &lt;%&ndash; zhaoyun &ndash;%&gt;--%>

使用EL表达式实现获取数据和打印:

name1的数值为:${name1}<br/>
name2的数值为:${name2}<br/>
name3的数值为:${name3}<br/>
name4的数值为:${name4}<br/>

1.3 访问请求参数的数据

image.png

image.png 首先设置页面内容:

<html>
<head>
    <title>实现一个简单页面负责向JSP页面传递参数</title>
</head>
<body>
<form action="el_param.jsp" method="post">
    姓名:<input type="text" name="name"/><br/>
    爱好:<input type="checkbox" name="hobby" value="唱歌"/>唱歌<br/>
         <input type="checkbox" name="hobby" value="跳舞"/>跳舞<br/>
         <input type="checkbox" name="hobby" value="学习"/>学习<br/>
    <input type="submit" value="提交"/><br/>
</form>
</body>
</html>

使用JSP原始方法获取内容的值:

<body>

    request.setCharacterEncoding("utf-8");

<%-- 使用JSP语法中的原始方式获取请求参数值 --%>
<%= "姓名是:" + request.getParameter("name") %><br/>
<%= "爱好是:" + Arrays.toString(request.getParameterValues("hobby")) %><br/>


使用EL方法获取内容的值:

姓名是:${param.name}<br/>
爱好是:${paramValues.hobby[0]}<br/>

1.3 访问bean对象的属性

访问方式:

image.png 两种访问方式的主要区别:

image.png 测试:创建一个java类并定义name和age

package com.example.a3.demo01;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

使用JSP原始方法获取数据:

<%
    Person person = new Person();
    person.setName("zhangfei");
    person.setAge(30);
    pageContext.setAttribute("person", person);

    pageContext.setAttribute("var1", "name");
    pageContext.setAttribute("var2", "age");
%>

<%= "获取到的姓名为:" + person.getName() %>
<%= "获取到的年龄为:" + person.getAge()  %>

使用el方法获取数据:

<%-- 使用EL表达式实现属性的获取和打印 --%>
获取到的姓名是:${person.name}<br/>
获取到的年龄是:${person.age}<br/>
<%-- 另外一种写法 --%>
${person["name"]}<br/>
${person["age"]}<br/
<%-- 测试一下动态取值的效果 --%>
动态取值的结果为:${person[var1]}

1.4 访问集合中的数据

<%@ page import="java.util.LinkedList" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %><%--
  Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>实现集合中数据内容的获取和打印</title>
</head>
<body>
<%
    //准备一个List集合并添加数据内容
    List<String> list = new LinkedList<>();
    list.add("two");
    list.add("one");
    list.add("three");
    // 将整个集合放入指定的内置对象中
    pageContext.setAttribute("list", list);

    // 准备一个Map集合并添加数据
    Map<String, Integer> map = new HashMap<>();
    map.put("one", 1);
    map.put("two", 2);
    map.put("th.ree", 3);
    // 将整个集合放入指定的内置对象中
    pageContext.setAttribute("map", map);
%>

<%-- 使用EL表达式实现集合中数据内容的获取 --%>
集合中下标为0的元素是:${list[0]}<br/>    <%-- two --%>
集合中下标为1的元素是:${list[1]}<br/>    <%-- one --%>
集合中下标为2的元素是:${list[2]}<br/>    <%-- three --%>
<hr/>
<%-- 使用EL表达式实现Map集合中数据内容的获取 不支持下标 --%>
整个Map集合中的元素有:${map}<br/>
获取带有特殊字符key对应的数值为:${map["th.ree"]}<br/>   <%-- 3 --%>
</body>
</html>

1.5 常用的内置对象

image.png

1.6 常用的运算符

image.png

<%@ page import="java.util.List" %>
<%@ page import="java.util.LinkedList" %>
<%@ page import="java.util.Arrays" %><%--
  Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>实现常用运算符的使用</title>
</head>
<body>
<%
    // 通过内置对象设置属性的方式来准备操作数
    request.setAttribute("ia", 5);
    request.setAttribute("ib", 2);
    request.setAttribute("b1", true);
    request.setAttribute("b2", false);
%>

<%-- 实现上述所有操作数的获取和打印 --%>
ia的数值为:${ia}<br/>      <%-- 5 --%>
ib的数值为:${ib}<br/>      <%-- 2 --%>
b1的数值为:${b1}<br/>      <%-- true --%>
b2的数值为:${b2}<br/>      <%-- false --%>
<hr/>

<%-- 实现算术运算符的使用 --%>
ia+ib的结果为:${ia+ib}<br/>    <%-- 7 --%>
ia-ib的结果为:${ia-ib}<br/>    <%-- 3 --%>
ia*ib的结果为:${ia*ib}<br/>    <%-- 10 --%>
ia/ib的结果为:${ia/ib}<br/>    <%-- 2.5 --%>
ia%ib的结果为:${ia%ib}<br/>    <%-- 1 --%>
<hr/>

<%-- 实现关系运算符的使用 --%>
ia大于ib的结果为:${ia > ib}<br/>  <%-- true --%>
ia大于等于ib的结果为:${ia >= ib}<br/>  <%-- true --%>
ia小于ib的结果为:${ia < ib}<br/>  <%-- false --%>
ia小于等于ib的结果为:${ia <= ib}<br/>  <%-- false --%>
ia等于ib的结果为:${ia == ib}<br/>  <%-- false --%>
ia不等于ib的结果为:${ia != ib}<br/>  <%-- true --%>
<hr/>

<%-- 实现逻辑运算符的使用 --%>
b1并且b2的结果为:${b1 && b2}<br/>  <%-- false --%>
b1或者b2的结果为:${b1 || b2}<br/>  <%-- true --%>
b1取反的结果为:${ !b1 }<br/>  <%-- false --%>
b2取反的结果为:${ !b2 }<br/>  <%-- true --%>
<hr/>

<%
    String str1 = null;
    String str2 = "";
    String str3 = "hello";

    List<Integer> list1 = new LinkedList<>();
    List<Integer> list2 = Arrays.asList(11, 22, 33, 44, 55);

    request.setAttribute("str1", str1);
    request.setAttribute("str2", str2);
    request.setAttribute("str3", str3);
    request.setAttribute("list1", list1);
    request.setAttribute("list2", list2);

%>
<%-- 实现条件运算符和验证运算符的使用 --%>
ia和ib之间的最大值为:${ia>ib? ia: ib}<br/>
判断是否为空的结果是:${empty str1}<br/>    <%-- true --%>
判断是否为空的结果是:${empty str2}<br/>    <%-- true --%>
判断是否为空的结果是:${empty str3}<br/>    <%-- false --%>
判断是否为空的结果是:${empty list1}<br/>    <%-- true --%>
判断是否为空的结果是:${empty list2}<br/>    <%-- false --%>

</body>
</html>

二.JSTL标签

2.1 JSTL概念

JSTL( JSP Standard Tag Library ) 被称为JSP标准标签库。

开发人员可以利用这些标签取代JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护 难度。

2.2 使用方法

下载JSTL的jar包并添加到项目中

然后在JSP页面中使用taglib指定引入jstl标签库,方式为:

image.png

2.3 常用标签

(1)输出标签

image.png 代码示例:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>实现out输出标签的使用</title>
</head>
<body>
<c:out value="Hello World"></c:out>
</body>
</html>

(2)设置标签

image.png 代码示例:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>实现set标签的使用</title>
</head>
<body>
<%-- 表示设置一个名字为name的属性,对应的数值为zhangfei,有效范围为:page --%>
<%-- pageContext.setAttibute("name", "zhangfei") --%>
<c:set var="name" value="zhangfei" scope="page"></c:set>
<%-- 使用out标签打印出来 --%>
<c:out value="${name}"></c:out>
<hr/>

<%-- 设置一个对象的属性值并打印出来 --%>
<jsp:useBean id="person" class="com.lagou.demo01.Person" scope="page"></jsp:useBean>
<c:set property="name" value="guanyu" target="${person}"></c:set>
<c:set property="age" value="35" target="${person}"></c:set>
<c:out value="${person.name}"></c:out>
<c:out value="${person.age}"></c:out>

</body>
</html>

(3)删除标签

image.png default="无名" 设置默认值为无名


<%-- 设置一个属性值并打印 --%>
<c:set var="name" value="liubei" scope="page"></c:set>
<c:out value="${name}"></c:out>
<hr/>

<%-- 删除这个属性值后再次打印 --%>
<c:remove var="name" scope="page"></c:remove>
<c:out value="${name}" default="无名"></c:out>

(4)单条件判断标签

image.png

<%-- 设置一个变量以及对应的数值 --%>
<c:set var="age" value="17" scope="page"></c:set>
<c:out value="${age}"></c:out>
<hr/>

<%-- 判断该年龄是否成年,若成年则提示已经成年了 --%>
<c:if test="${age >= 18}">
    <c:out value="已经成年了!"></c:out>
</c:if>

(5)多条件判断标签

image.png

<%-- 设置一个变量代表考试的成绩并指定数值 --%>
<c:set var="score" value="59" scope="page"></c:set>
<c:out value="${score}"></c:out>
<hr/>

<%-- 进行多条件判断和处理 --%>
<c:choose>
    <c:when test="${score > 60}">
        <c:out value="成绩不错,继续加油哦!"></c:out>
    </c:when>
    <c:when test="${score == 60}">
        <c:out value="60分万岁,多一份浪费!"></c:out>
    </c:when>
    <c:otherwise>
        <c:out value="革命尚未成功,同志仍需努力!"></c:out>
    </c:otherwise>
</c:choose>

(6)循环标签

image.png

<%
    // 准备一个数组并初始化
    String[] sArr = {"11", "22", "33", "44", "55"};
    pageContext.setAttribute("sArr", sArr);
%>

<%-- 使用循环标签遍历数组中的所有元素 --%>
<c:forEach var="ts" items="${sArr}">
    <c:out value="${ts}"></c:out>
</c:forEach>

跳跃性遍历 间隔为2 也就是跳过一个遍历一个

<c:forEach var="ts" items="${sArr}" step="2">
    <c:out value="${ts}"></c:out>
</c:forEach>
<hr/>

指定起始和结尾位置 从下标1开始到3结束,包含1和3

<c:forEach var="ts" items="${sArr}" begin="1" end="3">
    <c:out value="${ts}"></c:out>
</c:forEach>

2.4 常用函数标签

image.png fn设置数组输出结果:

<%
    pageContext.setAttribute("var", "Hello World!");
%>
原始字符串为:${var}<br/>    <%-- HelloWorld --%>
判断该字符串是否包含指定字符串的结果为:${fn:contains(var, "Hello")}<br/>   <%-- true --%>
将字符串中所有字符转换为大写的结果为:${fn:toUpperCase(var)}<br/>           <%-- HELLO WORLD!--%>
将字符串中所有字符转换为小写的结果为:${fn:toLowerCase(var)}<br/>           <%-- hello world!--%>

2.5 常用格式化标签

image.png 设置时间之后,在浏览器上显示的时间格式有问题,使用fmt 继续进行格式化:

<%
    // 获取当前系统时间
    Date date = new Date();
    pageContext.setAttribute("date", date);
%>

当前系统时间为:${date}
<hr/>
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate>

2.6 自定义标签

如果上面几个标签不能满足需求,程序员也可以自定义标签,步骤如下: 编写标签类继承SimpleTagSupport类或TagSupport类并重写doTag方法或doStartTag方法。

public class HelloTag extends SimpleTagSupport {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void doTag() throws JspException, IOException {
        // 获取输出流
        JspWriter out = this.getJspContext().getOut();
        // 写入数据到浏览器
        out.write("自定义标签哦!" + name);
        // 关闭流对象
        out.close();
    }

定义标签库文件(tld标签库文件)并配置标签说明文件到到WEB-INF下:

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1">

    <tlib-version>1.0</tlib-version>
    <short-name>my</short-name>
    <uri>http://lagou.com</uri>

    <!-- Invoke 'Generate' action to add tags or functions -->
    <tag>
        <name>hello</name>
        <tag-class>com.lagou.demo01.HelloTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>name</name>
            <required>true</required>
        </attribute>
    </tag>
</taglib>

在JSP中添加taglib指令引入标签库使用:

<%@ taglib prefix="my" uri="http://lagou.com" %>

使用自定义标签:

<my:hello name="zhangfei"/>

三.EL和JSTL的区别:

一、定义与基本概念

  • EL表达式

    • 全称为Expression Language,是一种用于在Java Web应用中访问和操作数据的简化表达式语言。
    • 它是在JSP 2.0规范中引入的,用于在JSP页面中获取和显示数据,而不需要使用Java代码片段。
    • 使用${expression}的语法结构,其中expression可以是JSP中的变量、JavaBean的属性、Map中的键等。
  • JSTL

    • 全称为JavaServer Pages Standard Tag Library,即JSP标准标签库。
    • 它是一组用于在JSP页面中进行逻辑处理和数据展示的定制标签库。
    • JSTL提供了诸如条件判断、循环迭代、国际化、SQL操作等功能强大的标签。

二、主要功能与用途

  • EL表达式

    • 主要用于简单的数据获取和运算,如访问JavaBean的属性、执行算术运算等。
    • 它支持基本运算、三元运算符、逻辑运算符等简单的操作,但不支持在表达式中直接调用方法。
    • EL表达式提高了JSP页面的可读性和可维护性,减少了Java代码的嵌入。
  • JSTL

    • 提供了比EL表达式更复杂的逻辑处理和数据展示功能,如条件判断、循环迭代、格式化输出等。
    • JSTL标签可以嵌套使用,支持在标签中调用方法,使得JSP页面的逻辑处理更加灵活和强大。
    • 与EL表达式结合使用时,可以进一步简化JSP页面的开发。

三、使用方式

  • EL表达式

    • 直接在JSP页面中通过${expression}的语法结构使用。
    • 无需额外引入标签库或进行复杂的配置。
  • JSTL

    • 需要在JSP页面顶部通过<taglib>指令引入相应的标签库。
    • 使用JSTL标签时,需要按照标签库的语法和规则进行编写。
    • JSTL标签可以包含EL表达式,以实现更复杂的逻辑处理和数据展示。

四、安全性与灵活性

  • EL表达式

    • 在安全性上比较严格,不允许直接调用方法,这有助于防止潜在的安全风险。
    • 但其灵活性相对较低,主要用于简单的数据访问和操作。
  • JSTL

    • 相对于EL表达式来说,JSTL提供了更高的灵活性,支持在标签中调用方法、执行复杂的逻辑处理等。
    • 然而,这也意味着开发者需要更加注意代码的安全性和性能问题。