在正式学习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就可以取代页面的所有脚本逻辑