【Java Web编程 六】深入理解EL表达式和JSTL标签(上)

简介: 【Java Web编程 六】深入理解EL表达式和JSTL标签(上)

在正式学习Servlet之前,我们还是把JSP的全部内容搞定,剩下的EL表达式和JSTL标签其实没什么特别的,还是为了我们一直提到的JSP的目标:简化Java代码的写法,尽量让页面干净整洁

EL表达式

什么是EL表达式呢?官方解释为:表达式语言(Expression Language,EL)是一种简单的数据访问语言,基本的语法格式为${ 表达式 },主要用于在页面上生成动态内容,并代替 JSP 脚本元素。其实说通俗点儿,EL表达式就是JSP内置的表达式:作用是来替代JSP的默认语法:<%=%>

基本功能

EL表达式的标准格式为:${el表达式},有以下几个基本功能,其实可以看的出来分别对应了我们前面三篇Blog中对<%=%>的使用,基本语法,内置对象使用和操作Java Bean:

  • 输出内容&执行计算【基本语法】:使用EL表达式可以方便地向客户端打印值,并且表达式支持一系列的逻辑运算
  • 操作隐式对象【内置对象】:使用一系列的隐含对象,如 pageContext 对象、request 对象和 session对象
  • 操作JavaBean对象【Java Bean】:使用${JavaBean.property} 的形式访问作用域中 JavaBean 对象的属性

接下来我们分别从这三个角度对比下写法。

输出内容&执行计算

从基本语法的角度来看,EL表达式好像并没有减少太多原有的<%=%>写法的数量,只是通过符号使整个页面变得更简单了:

代码清单对比示例

我们来看下输出内容和执行计算的内容:

<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page import="com.example.MyFirstJavaWeb.javabean.Person" %><%--
  Created by IntelliJ IDEA.
  User: 13304
  Date: 2021/7/18
  Time: 18:46
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
  String name = "tml"; // 定义姓名
  int age = 80; // 定义年龄
  String sex = "男"; // 定义性别
  pageContext.setAttribute("name", name); // 放入 page 范围内
  pageContext.setAttribute("age", age);
  pageContext.setAttribute("sex", sex);
  List listNull=null;
  pageContext.setAttribute("listNull", listNull);
  List list=new ArrayList();
  list.add("22");
  pageContext.setAttribute("list", list);
%>
<h3>
  旧的写法:姓名:<%=name%>  年龄:<%=age%>  性别:<%=sex%>,域中listNull的长度是否为0:<%=listNull==null?"true":"false"%> , 域中list的长度是否为0:<%=list.size()==0?"true":"false"%>
  </br>
  新的写法:姓名:${name}  年龄:${age}  性别:${sex}, 域中listNull的长度是否为0: ${empty listNull }, 域中list的长度是否为0: ${empty list }
</h3>
<%
  Person person=new Person();
  //将person放入域中
  request.setAttribute("person", person);
%>
获取域中person的name值【EL】: ${person.name } <br>
获取域中person的name值【旧】:<%=((Person)request.getAttribute("person")).getName() %>
<%
  String a = "tml";
  String b = "帅";
  pageContext.setAttribute("a", a);
  pageContext.setAttribute("b", b);
%>
<br>
a+b字符串相连的结果为【EL】:${a}${b} <br/>
a+b字符串相连的结果为【旧】:<%=a+b%>
<%
  int para1 = 15;
  int para2 = 13;
  pageContext.setAttribute("para1", para1);
  pageContext.setAttribute("para2", para2);
%>
<br>
para1和para2比较的结果【EL】:${para1==para2}<br/>
para1和para2比较的结果【旧】:${para1==para2}
<%
  boolean flag = true;
  pageContext.setAttribute("flag", flag);
%>
<br>
para1取反的结果【EL】:${not flag}<br/>
para1取反的结果【旧】:<%=!flag%>
</body>
</html>

返回结果为:

其实从以上内容可以看的出来,简单的输出上EL并没有什么优势,甚至如果不把变量显式放到域里EL都获取不到,但是一些特殊的逻辑判断和运算,EL是有优势的。

EL的运算符

为了方便JSP中实现计算和逻辑判断功能,EL表达式提供了如下几种运算符:存取数据运算符,算术运算符,关系运算符,逻辑运算符,条件运算符,empty 运算符,从以上的例子我们知道,其实这才是基本语法中EL的大杀器,通过定义特定的语法让基本的表达式逻辑写法更简化。

存储数据运算符

在 EL 表达式中可以使用运算符[].来取得对象的属性,如 ${person.name} 或者 ${person["name"]} 表示取出对象 person中的 name 属性值:

<%
  Person person=new Person();
  //将person放入域中
  request.setAttribute("person", person);
%>
获取域中person的name值【EL】: ${person.name } <br>
获取域中person的name值【旧】:<%=((Person)request.getAttribute("person")).getName() %>

算术运算符

算术运算符可以作用于整数和浮点数。EL 表达式中的算术运算符主要有 5 个:

注意:EL表达式无法像Java一样将两个字符串用+运算符相连接,如${"a"+"b"}的写法是错误的,但可以使用${"a"}${"b"}的写法来表示:

<%
  String a = "tml";
  String b = "帅";
  pageContext.setAttribute("a", a);
  pageContext.setAttribute("b", b);
%>
<br>
a+b字符串相连的结果为:${a}${b}

关系运算符

关系运算符作用在整数和浮点数上,可以依据字母的顺序比较两个字符串的大小:

在使用 EL 关系表达式时,不能写成 ${param.password1}==${param.password2},而应写成 ${param.password1==param.password2}

<%
  int para1 = 15;
  int para2 = 13;
  pageContext.setAttribute("para1", para1);
  pageContext.setAttribute("para2", para2);
%>
<br>
para1和para2比较的结果:${para1==para2}

逻辑运算符

逻辑运算符主要用于连接多个关系运算符,实现并且、或者关系判断,EL 表达式中的逻辑运算符主要包含3个

代码示例如下:

<%
  boolean flag = true;
  pageContext.setAttribute("flag", flag);
%>
<br>
para1取反的结果【EL】:${not flag}<br/>
para1取反的结果【旧】:<%=!flag%>

empty 运算符

empty 运算符是一个前缀运算符,用于判断对象或变量是否为 null 或空,语法格式为:${empty 变量或对象 }

  • ${empty A} 指向的A对象为 null 时,表达式 ${empty A}返回 true
  • ${empty A} 中A 是空字符串时,表达式 ${empty A} 返回 true
  • ${empty A}当 A 是集合或数组时,如果 A 中没有任何元素,则表达式 ${empty A}返回 true

代码示例如下:

<%
  String name = "tml"; // 定义姓名
  int age = 80; // 定义年龄
  String sex = "男"; // 定义性别
  pageContext.setAttribute("name", name); // 放入 page 范围内
  pageContext.setAttribute("age", age);
  pageContext.setAttribute("sex", sex);
  List listNull=null;
  pageContext.setAttribute("listNull", listNull);
  List list=new ArrayList();
  list.add("22");
  pageContext.setAttribute("list", list);
%>
<h3>
  旧的写法:姓名:<%=name%>  年龄:<%=age%>  性别:<%=sex%>,域中listNull的长度是否为0:<%=listNull==null?"true":"false"%> , 域中list的长度是否为0:<%=list.size()==0?"true":"false"%>
  </br>
  新的写法:姓名:${name}  年龄:${age}  性别:${sex}, 域中listNull的长度是否为0: ${empty listNull }, 域中list的长度是否为0: ${empty list }

条件运算符

条件运算符的格式为:A?B:C,它表示根据表达式 A 的结果选择执行 B 或 C,类似于Java中的三目判断运算符,首先将表达式 A 的计算结果转换为布尔型,如果表达式 A 的计算结果为 true,则执行 B 并返回表达式 B 的值;如果计算结果为 false,则执行表达式 C 并返回表达式 C 的值。

例如,表达式 ${1==2?"true":"false"} 的运行结果为 false

运算符优先级

EL 中的运算符有不同的运算优先级,而同一行中的运算符,则按照运算符在表达式中的顺序从左到右依次进行计算。所有运算符的优先级别从高到低如下:

[ ] ( )
not ! empty
算术运算符
关系运算符
逻辑运算符
三目运算符

操作隐式对象

为了更方便的读取Cookie、HTTP 请求消息头字段、请求参数以及 Web 应用程序的初始化参数等信息,JSP中定义了如下隐含对象:

需要注意:不要将 EL 表达式中的隐含对象与 JSP 隐含对象混淆,其中只有 pageContext 对象是两者共用的。

代码清单对比示例

整体的代码清单如下:

<%--
  Created by IntelliJ IDEA.
  User: 13304
  Date: 2021/7/18
  Time: 22:41
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>Title</title>
</head>
<body>
<table border="1" align="left">
  <tr><td> 对 pageContext 隐含对象的调用【EL】 </td></tr>
  <tr><td>${pageContext.request.requestURL}</td></tr>
  <tr><td>${pageContext.request.contextPath}</td></tr>
  <tr><td>${pageContext.request.method}</td></tr>
</table>
</table>
<br/>
<br/>
<br/>
<br/>
<br/>
<%
  pageContext.setAttribute("userName", " 访问放入 page 范围内的 Java");
  request.setAttribute("userName", " 访问放入 request 范围内的 Java");
  session.setAttribute("userName", " 访问放入 session 范围内的 Java");
  application.setAttribute("userName", " 访问放入 application 范围内的 Java");
%>
<br/> ${pageScope.userName }
<br/> ${requestScope.userName }
<br/> ${sessionScope.userName }
<br/> ${applicationScope.userName }
<br/>
<br/>
旧的写法
<br/>
<br/> <%=pageContext.getAttribute("userName")%>
<br/> <%=request.getAttribute("userName")%>
<br/> <%=session.getAttribute("userName")%>
<br/> <%=application.getAttribute("userName")%>
<br/>
</body>
</html>

返回结果为:

pageContext隐含对象

我们来看下pageContext的一些使用示例,看看pageContext的一些用法:

<table border="1" align="left">
  <tr><td> 对 pageContext 隐含对象的调用 </td></tr>
  <tr><td>${pageContext.request.requestURL}</td></tr>
  <tr><td>${pageContext.request.contextPath}</td></tr>
  <tr><td>${pageContext.request.method}</td></tr>
</table>

作用域隐含对象

不同的作用域可以放置不同的对象,EL也支持直接用隐含对象获取,我们来看下旧的写法和EL写法的对比:

<%
  pageContext.setAttribute("userName", " 访问放入 page 范围内的 Java");
  request.setAttribute("userName", " 访问放入 request 范围内的 Java");
  session.setAttribute("userName", " 访问放入 session 范围内的 Java");
  application.setAttribute("userName", " 访问放入 application 范围内的 Java");
%>
<br/> ${pageScope.userName }
<br/> ${requestScope.userName }
<br/> ${sessionScope.userName }
<br/> ${applicationScope.userName }
<br/>
<br/>
旧的写法
<br/>
<br/> <%=pageContext.getAttribute("userName")%>
<br/> <%=request.getAttribute("userName")%>
<br/> <%=session.getAttribute("userName")%>
<br/> <%=application.getAttribute("userName")%>

这里对比可以看的出来EL表达式写法确实更加简洁。

操作JavaBean对象

之前的Blog我们提到过通过JSP动作标签和脚本代码两种方式来访问JavaBean对象,这次我们用更加简化的方式,使用EL表达式来操作Java Bean对象,这里还使用我们上篇Blog中的Person对象:

<%--
  Created by IntelliJ IDEA.
  User: 13304
  Date: 2021/7/18
  Time: 23:06
  To change this template use File | Settings | File Templates.
--%>
<%--导入javabean类--%>
<%@ page import="com.example.MyFirstJavaWeb.javabean.*" pageEncoding="UTF-8" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%-- JSP脚本段--%>
JSP脚本段
<br>
<%
    Person p = new Person();
    out.print(p.getAge() + "<br>");
    out.print(p.getName() + "<br>");
    out.print(p.getSex() + "<br>");
%>
<br>
<br>
<%-- JSP动作标签--%>
JSP动作标签
<%--id表示被实例化的对象名字,class表示类这是javabea声明标签--%>
<jsp:useBean id="person" class="com.example.MyFirstJavaWeb.javabean.Person" scope="request"></jsp:useBean>
<br>
<jsp:getProperty property="name" name="person"/>
<br>
<jsp:getProperty property="age" name="person"/>
<br>
<jsp:getProperty property="sex" name="person"/>
<br>
<br>
<%-- EL表达式--%>
EL表达式
<jsp:useBean id="personEl" class="com.example.MyFirstJavaWeb.javabean.Person" scope="request"></jsp:useBean>
<br>
${personEl.name}
<br>
${personEl.age}
<br>
${personEl.sex}
<br>
</body>
</html>

输出的结果都是相同的,我们可以看的出来脚本段掺杂了换行元素,Jsp动作标识比较冗长,而EL表达式则是最合适的方式:

JSTL标签

什么是JSTL标签,官方的定义为:JSP 标准标签库(JavaServer Pages Standard Tag Library,JSTL),包含用于编写和开发 JSP 页面的一组标准标签,它可以为用户提供一个无脚本环境,通常和EL表达式配合使用

好的,说白了就是发明出来为了取代<% %><%! %>脚本段的,还是那个目标,简化简化再简化,直至JSP页面没有脚本代码。也就是说EL+JSTL就可以取代页面的所有脚本逻辑

相关文章
|
7月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
288 6
|
7月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
398 1
|
8月前
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
1239 2
|
7月前
|
安全 前端开发 Java
从反射到方法句柄:深入探索Java动态编程的终极解决方案
从反射到方法句柄,Java 动态编程不断演进。方法句柄以强类型、低开销、易优化的特性,解决反射性能差、类型弱、安全性低等问题,结合 `invokedynamic` 成为支撑 Lambda 与动态语言的终极方案。
293 0
|
9月前
|
安全 Java 数据库连接
2025 年最新 Java 学习路线图含实操指南助你高效入门 Java 编程掌握核心技能
2025年最新Java学习路线图,涵盖基础环境搭建、核心特性(如密封类、虚拟线程)、模块化开发、响应式编程、主流框架(Spring Boot 3、Spring Security 6)、数据库操作(JPA + Hibernate 6)及微服务实战,助你掌握企业级开发技能。
1106 3
|
8月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
577 100
|
9月前
|
安全 Java API
Java中的Lambda表达式:简洁与功能的结合
Java中的Lambda表达式:简洁与功能的结合
543 211
|
9月前
|
安全 Java
Java中的Switch表达式:更简洁的多路分支
Java中的Switch表达式:更简洁的多路分支
691 211
|
9月前
|
Java 编译器
Java 17 Switch表达式:更简洁、更强大的流程控制
Java 17 Switch表达式:更简洁、更强大的流程控制
1056 111