EL(表达式语言)
EL(表达式语言)
制作人:全心全意
EL的基本语法
EL表达式语法很简单,它以“${”开头,以“}”结束,中间为合法的表达式,具体的语法格式如下:
${expression}
参数说明:
expression:用于指定要输出的内容,可以是字符串,也可以是由EL运算符组成的表达式。
技巧:用于EL表达式的语法以“${”开头,所以如果在JSP网页中要显示“${”字符串,必须在前面加上“\”符号,即“\${”,或者写成“${'${'}”,也就是用表达式来输出“${”符号。
EL的特点
- EL可以与JSTL结合使用,也可以与JavaScript语句结合使用。
- EL中会自动进行类型转换。如果想通过EL输出两个字符串型数值(例如,number1和number2)的和,可以直接通过+号进行连接(例如:${number1+number2})。
- EL不仅可以访问一般变量,而且还可以访问JavaBean中的属性以及嵌套属性和集合对象。
- 在EL中可以执行算术运算、逻辑运算、关系运算和条件运算等。
- 在EL中可以获得命名空间(PageConext对象,它是页面中所有其他内置对象的最大范围的集成对象,通过它可以访问其他内置对象)。
- 在使用EL进行除法运算时,如果0作为除数,则返回无穷大infinity,而不返回错误。
- 在EL中可以访问JSP的作用域(request、session、application以及page)。
- 扩展函数可以与Java类的静态方法进行映射。
禁用EL
如今EL已经是一项成熟、标准的技术,只要安装的Web服务器能够支持Servlet2.4/JSP 2.0,就可以在JSP页面中直接使用EL。由于在JSP2.0以前的版本中没有EL,所以JSP为了和以前的规范兼容,还提供了禁用EL的方法。JSP提供了以下3种禁用EL的方法,下面将分别进行介绍。
使用斜杠“\”符号
使用斜杠符号是一种比较简单的禁用EL的方法。该方法只需要在EL的起始标记“${”前加上“\”符号,具体的语法如下:
\${expression}
使用page指令
使用JSP的page指令也可以禁用EL表达式,其具体的语法格式如下:
<%@ page isELIgnored="布尔值" %>
isELIgnored属性:用于指定是否禁用页面中的EL,如果属性值为true,则忽略页面中的EL,否则将解析页面中的EL。
在web.xml文件中配置<el-ignored>元素
在web.xml文件中配置<el-ignored>元素可以实现禁用服务器中的EL。
在web.xml文件中配置<el-ignored>元素的具体代码如下:
<jsp-config> <jsp-property-group> <url-pattern>*.jsp</url-pattern> <el-ignored>true</el-ignored> <!-- 将此处的值设置为false,表示使用EL --> </jsp-property-group> </jsp-config>
EL保留的关键字
同java一样,EL也有自己的保留关键字,在为变量命名时,应该避免使用这些关键字,包括在使用EL输出已经保存在作用域范围内的变量也不能使用关键字,如果已经定义了,那么需要修改为其它的变量名。EL的保留关键字如下表所示。
and | eq | gt |
instanceof | div | or |
le | false | empty |
not | lt | ge |
EL的运算符及优先级
运算符的优先级决定了在多个运算符同时存在时,各个运算符的求值顺序,对于同级运算符采用从左向右计算的原则。使用括号()可以改变优先级。运算符的优先级如下图所示。
通过EL访问数据
通过EL提供的“[]”和“.”运算符可以访问数据。通常情况下,“[]”和“.”运算符是等价的,可以相互代替。
例如:访问JavaBean对象userInfo的id属性,可以写成以下两种形式:
${userInfo.id} ${userInfo[id]}
注意:不是所有情况下都可以相互替代,当对象的属性名中包括一些特殊的符号(-获.)时,就只能使用“[]”运算符来访问对象的属性。另外,EL的“[]”还有一个用途,就是用来获取数组或者List集合中的数据。
例:List集合元素的获取(向session域中保存一个包含3个元素的List集合对象,并应用EL输出该集合的全部元素)
<%@page import="java.util.List"%> <%@page import="java.util.ArrayList"%> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>首页</title> </head> <body> <% List<String> list = new ArrayList<String>(); list.add("香蕉"); list.add("苹果"); list.add("大鸭梨"); session.setAttribute("goodsList", list); %> <% List<String> list1 = (List<String>) session.getAttribute("goodsList"); for (int i = 0; i < list.size(); i++) { request.setAttribute("requestI", i); %> ${requestI} : ${goodsList[requestI]} <!-- 应用“[]”运算符可以获取List集合中的指定元素,但是“.”运算符则不能 --> <br> <% } %> </body> </html>
注意:在上面的代码中,必须将循环变量i保存到request范围内的变量中,否则将不能正确访问数组,这里不能直接使用Java代码片段中定义的变量i,也不能使用<%=i%>输出i。
通过EL进行算术运算
在EL中,也可以进行算术运算,同Java语言一样,EL提供了加、减、乘、除和求余5种算术运算符,各运算符及其用法,如下表所示。
运 算 符 | 功 能 | 示 例 | 结 果 |
+ | 加 | ${19+1} | 20 |
- | 减 | ${66-30} | 36 |
* | 乘 | ${52.1*10} | 521.0 |
/ 或 div | 除 | ${5/2}或${5 div 2} | 2.5 |
${9/0}或${9 div 0} | Infinity | ||
% 或 mod | 求余 | ${17%3}或${17 mod 3} | 2 |
${15%0}或${15 mod 0} | 抛出异常:java.lang.ArithmeticException:/by zero |
通过EL判断对象是否为空
在EL中,判断对象是否为空,可以通过empty运算符实现,该运算符是一个前缀(prefix)运算符,即empty运算符位于操作数前方,用来确定一个对象或变量是否为空或null。empty运算符的格式如下:
${empty expression}<!--判断对象是否为空--> ${not empty expression}<!--判断对象是否非空-->
参数说明如下:
expression:用于指定要判断的变量或对象。
通过EL进行逻辑关系运算
在EL中,通过逻辑运算符和关系运算符可以实现逻辑关系运算。关系运算符用于实现对两个表达式的比较,进行比较的表达式可以是数值型,也可以是字符串型。而逻辑运算符,则常用于对boolean型数据进行操作。逻辑运算符和关系运算符经常一同使用。逻辑关系运算语法如下:
${表达式1 逻辑关系运算符 表达式2}
- 关系运算符
运 算 符 | 功 能 | 示 例 | 结 果 |
== 或 eq | 等于 | ${10 == 10} | true |
${"A" eq "a"} | false | ||
!= 或 ne | 不等于 | ${10 ne 10} | false |
${"A" != "A"} | false | ||
< 或 lt | 小于 | ${7 < 6} | false |
${"A" lt "B"} | true | ||
> 或 gt | 大于 | ${7 > 6} | true |
${"A" gt "B"} | false | ||
<= 或 le | 小于等于 | ${7 le 6} | false |
${"A" <= "A"} | true | ||
>= 或 ge | 大于等于 | ${7 ge 6} | true |
${"A" >= "B"} | false |
- 逻辑运算符
运 算 符 | 功 能 | 示 例 | 结 果 |
&& 或 and | 与 | ${true && false} | false |
${true && true} | true | ||
|| 或 or | 或 | ${true or false} | true |
${false || false} | false | ||
! 或 not | 非 | ${! true} | false |
${not false} | true |
通过EL进行条件运算
在EL中进行简单的条件运算,可以通过条件运算符实现。EL的条件运算符唯一的优点在于其非常简单和方便,和Java语言里的用法完全一致。其语法格式如下:
${条件表达式 ? 表达式1:表达式2}
参数说明如下:
条件表达式:用于指定一个条件表达式,该表达式的值为boolean型。可以由关系运算符、逻辑运算符和empty运算符组成。
表达式1:用于指定当条件表达式的值为true时,将要返回的值。
表达式2:用于指定当条件表达式的值为false时,将要返回的值。
说明:通常情况下,条件运算符可以用JSTL中的条件标签<c:if>或<c:choose>替代
EL的隐含对象
EL提供了11个隐含对象,这些对象类似于JSP的内置对象,也是直接通过对象名进行操作。
在EL的隐含对象中,除了PageContext是JavaBean对象,对应于javax.servlet.jsp.PageContext类型外,其他的隐含对象都对应于java.util.Map类型。这些隐含对象可以分为页面上下文对象、访问作用域范围和访问环境信息的隐含对象3种。
页面上下文对象
页面上下文对象为pageContext,用于访问JSP内置对象(如request、response、out、session、exception、和page等,但不能用于获取application、config和pageContext对象)和servletContext。在获取到这些内置对象后,就可以获取其属性值。这些属性与对象的getXXX()方法相对应,在使用时,去掉方法名中的get,并将首字母改为小写即可。
例1:通过request对象访问getServerPort()方法
${pageContext.request.serverPort}
注意:不可以通过pageContext对象获取保存到request范围内的变量。
例2:通过exception对象获取异常信息字符串
${pageContext.exception.message}
说明:在使用该对象时,也需要在可能出现错误的页面中指定错误处理页,并且在错误处理页中指定page指令的isErrorPage属性值为true,然后再使用上面的EL输出异常信息。
例3:通过servletContext对象获取servlet上下文路径
${pageContext.servletContext.contextPath}
访问作用域范围的隐含对象
在EL中提供了4个用于访问作用域范围的隐含对象,即pageScope、requestScope、sessionScope和applicationScope。应用这4个隐含对象指定所要查找的标识符的作用域后,系统将不再按照默认的顺序(page、request、session及application)来查找相应的标识符。它们与JSP中的page、request、session、及application内置对象类似,只不过这4个隐含对象只能用来取得指定范围内的属性值,而不能取得其他相关信息。
- pageScope隐含对象:pageScope隐含对象用于返回包含page(页面)范围内的属性值集合,返回值为java.util.Map对象。
- requestScope隐含对象:requestScope隐含对象用于返回包含request(请求)范围内的属性值集合,返回值为java.util.Map对象。
- sessionScope隐含对象:sessionScope隐含对象用于返回包含session(会话)范围内的属性值的集合,返回值为java.util.Map对象。
- applicationScope隐含对象:applicationScope隐含对象用于返回包含application(应用)范围内的属性值的集合,返回值为java.util.Map对象。
例:通过pageScope隐含对象用于返回包含page范围内的JavaBean的属性值
UserInfo类:用户名的JavaBean
package com.zq; public class UserInfo { private String name = ""; //用户名 public String getName() { return name; } public void setName(String name) { this.name = name; } }
index.jsp页面:应用pageScope隐含对象获取该JavaBean实例的name属性
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>pageContext</title> </head> <body> <!-- 应用pageScope隐含对象获取该JavaBean实例的name属性 --> <jsp:useBean id="user" scope="page" class="com.zq.UserInfo" type="com.zq.UserInfo"> <jsp:setProperty property="name" name="user" value="全心全意" /></jsp:useBean> ${ pageScope.user.name } <br> <!-- 应用requestScope隐含对象获取request范围内的userName变量 --> <% request.setAttribute("userName", "quanxinquanyi"); %> ${requestScope.userName } </body> </html>
访问环境信息的隐含对象
- param对象:param对象用于获取请求参数的值,应用在参数值只有一个的情况。在应用param对象时,返回的结果为字符串。(例如表单)
例:param对象的使用示例(表单)
放置一个名称为user的文本框
<input name="name" type="text" />
在表单提交页面,获取name文本框的值
${param.name}
注意:如果使用中文,需应用“request.setCharacterEncoding("字符编码")”设置支持中文的字符编码。
- paramValues对象:如果一个请求参数对应多个值时,则需要使用paramValues对象获取请求参数的值。在应用paramValues对象时,返回的结果为数组。(例如复选框)
- header和headerValues对象:header对象用于获取HTTP请求的一个具体的header的值,但是在有些情况下,可能存在同一个header拥有多个不同的值的情况,这时就必须使用headerValues对象。
- initParam对象:initParam对象用于获取Web应用初始化参数的值(初始化参数为web.xml文件中定义的初始化参数)
- cookie对象:虽然在EL中,并没有提供向cookie中保存值的方法,但是它提供了访问由请求设置的cookie的方法,这可以通过cookie隐含对象实现。如果在cookie中已经设定一个名称为username的值,那么可以使用${cookie.username}来获取该cookie对象。但是如果要获取cookie中的值,需要使用cookie对象的value属性${cookie.username.value}。
例:cookie对象的使用示例
使用response对象设置一个请求有效的cookie对象,然后再使用EL获取该cookie对象的值
<% Cookie cookie = new Cookie("user","quanxinquanyi"); response.addCookie(cookie); %> ${cookie.user.value}
注意:在应用param和paramValues对象时,如果指定的参数不存在,则返回空的字符串,而不是返回null。
定义和使用EL函数
EL函数的定义和使用分为以下3个步骤:
(1)编写一个Java类,并在该类中编写公用的静态方法,用于实现自定义EL函数的具体功能。
(2)编写标签库描述文件,对函数进行声明。该文件的扩展名为.tld,被保存到Web应用的WEB-INF文件夹下。
(3)在JSP页面中引用标签库,并调用定义的EL函数,实现相应的功能
例:定义EL函数处理字符串中的回车换行符和空格符。
StringDeal类:添加一个公用的静态的方法shiftEnter(),在该方法中替换输入字符串中的回车换行符为<br>,空格符为 ,最后返回新替换后的字符串。
package com.zq; public class StringDeal { public static String shiftEnter(String str) { String newStr = str.replaceAll("\r\n", "<br>"); // 替换回车换行符 newStr = newStr.replaceAll(" ", " ");// 替换空格符 return newStr; } }
stringDeal.tld文件:标签库的描述文件,将其保存到WEB-INF文件夹下。
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <uri>/stringDeal</uri> <!-- 指定tld文件的映射路径。在应用EL函数时,需要使用该标记指定的内容 --> <function> <name>shiftEnter</name> <!-- 对应EL函数对应的方法名,通常与Java文件中的方法名相同 --> <function-class>com.zq.StringDeal</function-class> <!-- 对应静态类,这里需要包括包名和类名 --> <function-signature>java.lang.String shiftEnter(java.lang.String) </function-signature> <!-- 对应静态方法,这里包括返回值的类型和入口参数的类型 --> </function> </taglib>
index.jsp页面:放置一个表单及表单元素,用于收集内容信息。
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>welcome</title> </head> <body> <form name="form1" method="post" action="deal.jsp"> <textarea name="content" cols="30" rows="5"></textarea> <br> <input type="submit" name="Button" value="提交"> </form> </body> </html>
deal.jsp页面:对获取到的内容信息进行处理后显示到页面中。
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@ taglib uri="/stringDeal" prefix="wghfn"%> <!-- 引用标签库时,指定的uri属性与标签库描述文件中的<uri>标记的值是相对应的 --> <% request.setCharacterEncoding("utf-8"); %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>显示结果</title> </head> <body> 内容为: <br> ${wghfn:shiftEnter(param.content) } </body> </html>
定义和使用EL函数时常见错误
- 由于没有指定完整的类型名而产生异常信息
- 由于在标签库的描述文件中输入了错误的标记名产生的异常信息
- 由于定义的方法不是静态方法所产生的异常信息