常用提取:EL中的隐含对象
起初 EL 表达式只是为了方便存取数据所定义的一种语言。它只能使用在 JSTL 标签中,而不能在JSP 页面中运用。一直到了 JSP2.0 版本发布后, EL 才被正式纳入为 JSP 标准规范之一。这时,它才可以直接在 JSP 页面程序中使用,只要安装的 Web 服务器能够支持 Servlet2.4/JSP2.0。
在 JSP2.0 之前,Web开发者只能使用表达式<%=Name%>访问系统的值,例如:
<someTags:aTag attribute="<%=pageContext.getAttribute("aName")%>">或者调用JavaBean中的属性值:
<%= aCustomer.getAddress().getCountry() %>而EL表达式语言允许网页开发者使用简单的语法访问对象。比如要访问一个简单变量,可以像下面这样写:
<someTags:aTag attribute="${aName}">其中${aName}即为访问aName变量的EL表达式。而访问JavaBeans属性(例如获取aCustomer对象中定义的address对象变量的 country属性),可以使用:
${aCustomer.address.country}EL表达式还可以很好在JavaScript中得到使用,因为表达式语言正是借用了访问结构化数据的JavaScript语法。EL可以很好的和JSTL或者自定义标签结合使用,因为EL创建的初衷就是在JSTL 中使用。例如,在<c:if>标签中的不等式EL:
<c:if test=”${bean1.num < 3}”> body content </c:if>在EL中除了可以是变量、数值、对象的属性调用或者嵌套调用以及不等式判断(判断结果是Boolean类型),还可以直接包含一个字符串:
<c:out value=”an expression is ${‘${‘}expr}” />这样输出的字符串值为:an expression is ${expr}。 page 指令中,有一个 isELignored 属性,它就是指定该 JSP 页面是否支持 EL表达式。如果isELignored属性值为true,即忽略EL表达,在JSP页面可以直接使用${之类的字符,Web容器式不会试图解析这些表达式。如果设置为false,当Web容器遇到“${”字符时会解析其中的表达式内容,并把结果输出。注意:当 isELignored属性设置为false,即页面能够识别EL表达式语言,但是Web开发者又想使用“${”字符,则需要在前面加上“/”作标识。
总结起来, EL 表达式语言的使用范围以及特点包括如下:
不仅仅可以在 JSTL 或者自定义标签中使用 EL, JSP2.0 开始允许 EL 在 JSP 语句以及 JavaScript语句等更广范围内使用 EL 表达式语言。在 EL 表达式语言中可以获得命名空间( PageContext 对象,它是页面中所有其他内置对象的最大集成者,通过它可以访问到其他内置对象,本书的第五章有介绍)。 既可以访问一般变量,还可以访问 JavaBean 类中的属性以及嵌套属性和集合对象。在 EL 表达式中可以执行关系运算、逻辑运算以及算术运算。扩展函数可以和 Java 类的静态方法映射在 EL 表达式中可以访问 JSP 的一系列隐含对象( request、 session、 application 以及 page 等)。EL 表达式的使用是非常简单的,所有的 EL 表达式的格式都是以“ ${”开始,并以“ }”结尾。最直接和简单的方法,就是在 EL 中使用变量名获取到值,例如:
${ username }当 EL 表达式中的变量不给定范围时,则表示容器会默认从 page 范围中找,再依次到 request.、session以及 application 范围(由小到大)。如果中途中找到 username 变量,则直接返回,否则返回 NULL。下面列出了 EL使用到的变量属性范围的名称:
属性范围 page:在 EL 中使用名称 pageScope,例如${pageScope.username},则表示在 page 范围中找 username 变量,找不到直接返回 NULL。属性范围 request:在 EL 中使用名称 requestScope。属性范围 session:在 EL 中使用名称 sessionScope。属性范围 application:在 EL 中使用名称 applicationScope。JSP 表达式语言( EL)定义了可以在表达式中使用的文字包括以下:
Boolean: ture 和 false。Integer:与 Java 类似,可以包含任何正数或者负数,例如 24、 56、 -54 等。Floating Point:与 Java 类似,可以包含任何正的或者负的浮点数,例如-1.8E-5、 4.567。String:任何由引号或者双引号限定的字符串。对于单引号、双引号和反斜杠,使用反斜杠字符作为转义序列。必须注意,如果在字符串两端使用双引号,则但引号不需要转义。NULL:返回 null。下面逐一举例: ${false}包含 Boolean 类型、 ${3*8}包含整数类型 Integer、 ${5.678}包含浮点型、 ${“string”}或者${‘string’}包含字符串、 ${NULL}表示返回为空值。
在 EL 中,可以使用操作符“ []”和“ .”来取得对象的属性。例如:${user.name}或者${user[name]}表示取出对象 user 中的 name 属性值。 另外在 EL 中可以使用[]操作符来读取 Map、 List 或者对象集合中的数据,例如在 Session 域中存在一个数组 schools:获取数组中第二位数值:
${sessionScope.schools[1]}如果 schools 是 School 对象集合类,则可是获取第二位对象中的 name 属性值:
${sessionScope.shools[1].name}这里的 sessionScope 是在 EL 表达式中的调用 Session 内置对象的名称。 如果需要 EL 表达式来访问一个 JavaBean 中的属性值, JavaBean 的定义如下:
<jsp:useBean id=”user” class=”cn.User” />对 JavaBean 类中属性的引用: ${user.name}或者${user[“name”]}。注意:当属性名中包含了一些特殊符号时,例如“.”或者“-”等非字母或者数字符号时,就只能使用[]格式来访问属性值了,例如:${sessionScope.user[user_name]}是正确的,而${sessionScope.user.user_name}是不正确的。 另外一种情况也必须使用[]符号来引用属性值,当某个对象的属性名使用某一个变量(假设这里变量为 AttributeName)来给定的,例如: ${sessionScope.user[AttributeName]},这里的变量 AttributeName 可以在之前进行赋值。例如 AttributeName 变量赋值为 name,则以上 EL 表达式等价于:${sessionScope.user.name}
在 JSP 中的表达式语言( EL)提供了如下多个运算操作符,其中大部分是 Java 中常用的操作符。
算术操作符 说明 范例 结果+“加法”操作${23+5}28-“减法”操作${34-6}28*“乘法”操作${3*8}24/或者div“除法”操作${8/2}或者${8 div 2}4%或者mod“求余”操作${17/4}或者${17 mod 4}1EL 中使用的关系操作包括如下六种,如下表:
关系操作符 说明 范例 结果= =或者eq“等于”判断${5= =10}或者${5 eq 10}false!=或者ne“不等于”判断${5 != 10}或者${5 ne 10}true<或者lt“小于”判断${3 < 5}或者${3 lt 5}true>或者gt“大于”判断${3 > 5}或者${3 gt 5}false<=或者le“小于等于”判断${4 <= 4}或者${4 le 4}true>=或者ge“大于等于”判断${4 >= 6}或者${4 ge 6}false逻辑操作符包括如下几种,如表所示:
逻辑操作符 说明 范例&& 或者 and“与”操作符${num >5 && num <10}|| 或者 or“或”操作符${num <5 || num > 11}! 或者 not“非”操作符${!name.equals(“zzb”)}执行该操作符时,首先强行把 A 和 B 转换成Boolean类型,然后再执行相应的操作运算符。
如果 A 和B同为true,当操作符为“&&”时,返回true;操作符为“||”时,返回true。如果 A 和B其中一个为true,另一个为false。当操作符为“&&”时,返回false;操作符为“||”时,返回true。如果 A 和B同为false。当操作符为“&&”时,返回false;操作符为“||”时,则返回false。否则,执行过程产生异常,报错。注意:在执行过程中,只要表达式结果一旦确定,运算过程就会停止,例如,A && B && C或者A and B and C,则一旦计算到A为false,就会立即停止计算,并返回false。 “||”操作符也同样,例如 A || B || C,则一旦检测到第一个(A、B或者C)为true,则停止计算,直接返回true。 对“ &&”操作符来讲,只要检测到一个false,则整体为false;对“||”操作符来说,只要检测到一个true,则整体返回true。
执行该操作符之前,会强行把 A 转换成Boolean类型,然后再执行“非”或者“反”操作:
如果 A 判断为false,执行“!”操作之后,返回结果true如果 A 判断为true,执行完“!”操作之后,返回结果false否则,执行过程发生异常,报错这个“ empty”操作符是一个前缀形式的操作符,它使用来判断某个变量是否为 NULL 或者为空,在 EL 中的使用格式如下:${empty user.name},判断 user 对象 name 属性值是否为 NULL 或者空。“ empty”操作符的运算规则如下:
如果 A 为 NULL,则返回 true。否则,如果 A 是一个空的字符串,则返回 true。否则,如果 A 是一个空的数组,则返回 true。否则,如果 A 是一个空的 Map 集合类,则返回 true。否则,如果 A 是一个空的 List 集合类,则返回 true。否则,返回 false。包括的其他操作符还有:条件操作符和括号操作符。
EL 中还可以使用以下形式的条件操作符:
${A ? B : C}其中 A 为判断表达式,当 A 为 true 时,返回 B 表达式执行的结果;如果 A 为 false,则返回 C 表达式执行之后的结果。
在 EL 中也可以包含括号,例如:
${ (a * (b + c) ) }括号主要是使用来改变执行优先权,所有操作符的优先级顺序如下(由上往下,由左往右):
[]()-(负)、 not、!、 empty*、 /、 div、 %、 mod+、-(减)<、 >、 <=、 >=、 lt、 gt、 le、 ge==、!=、 eq、 ne&&、 and${A?B:C}为了方便地获得 Web 应用程序中的相关数据, EL 表达式语言定义了一些隐含对象。隐含对象总共有 11 个,这样使得 EL 能够更加方便地获取到数据。 这 11 隐含对象能够很方便地读取到 session、 cookie、 HttpHeader 以及用户提交表单( param)等,具体请查看如下表所示:
注意:有很多读者会把 EL 中定义的隐含对象和 JSP 中定义的隐含对象相混淆,其实只有一个对象是它们两者所共有的,即 PageContext 对象。这样 EL 也可以访问到JSP 中的其他隐含对象,这是因为PageContext 对象拥有访问 JSP 中所有其他 8 个隐含对象的权限。实际上,这也是将 PageContext 对象包含在 EL 隐含对象中的主要原因。
注:需要引入JSTL核心依赖
这四个映射用来获取请求参数和请求头的值。因为 HTTP 协议允许请求参数和请求头具有多个值,所以它们各有一对映射。每对中的第一个映射返回请求参数或头的主要值,通常是恰巧在实际请求中首先指定的那个值。每对中第二个映射允许检索参数或头的所有值。这些映射中的键是参数或头的名称,但这些值是 String 对象的数组,其中的每个元素都是单一参数值或头值。 param 和 paramValues 两隐含对象是取得用户的请求参数,类似于 JSP 中的下列方法:
request.getParameter(String name)request.getParameterValues(String name)下面创建 paramsubmit.jsp 和 param.jsp 页面来演示这四个隐含变量的使用方法, paramsubmit.jsp 用于提交参数,param.jsp接收数据,示例如下:
paramsubmit.jsp
<body> <h3>EL中的隐含对象:header,headerValues,param,paramValues</h3> <hr> <form action="param.jsp" method="post"> <table width="400" align="center" border="1"> <tr> <td width="60">姓名:</td> <td> <input type="text" name="name" width="15" /></td> </tr> <tr> <td>性别:</td> <td> <input type="radio" name="sex" value="male" checked />男 <input type="radio" name="sex" value="female" />女 </td> </tr> <tr> <td>专业:</td> <td> <select name="specialty"> <option value="计算机科学" selected>计算机科学</option> <option value="通信">通信</option> <option value="管理科学与工程">管理科学与工程</option> </select></td> </tr> <tr> <td>爱好:</td> <td> <input type="checkbox" name="habit" value="电影" />电影 <input type="checkbox" name="habit" value="读书" />读书 <input type="checkbox" name="habit" value="羽毛球" />羽毛球 <input type="checkbox" name="habit" value="篮球" />篮球 <input type="checkbox" name="habit" value="旅游" />旅游 </td> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="提交" /> | <input type="reset" value="重置" /></td> </tr> </table> </form> </body>param.jsp
<body> <h3>EL中的隐含对象:header,headerValues,param,paramValues</h3> <hr> <fmt:requestEncoding value="GBK" /> HTTP连接头部的host值: ${header["host"]} <br> HTTP头部的accept值: ${header.accept} <br> HTTP头部的user-agent值: ${header["user-agent"]} <br> <hr width="50%" align="left"> 姓名: <c:out value="${param.name}" /> <br> 性别: <c:out value="${param.sex}" /> <br> 专业: <c:out value="${param['specialty']}" /> <br> 兴趣: <c:out value="${paramValues.habit[0]}" /> <c:out value="${paramValues.habit[1]}" /> <c:out value="${paramValues.habit[2]}" /> <c:out value="${paramValues.habit[3]}" /> <c:out value="${paramValues.habit[4]}" /> </body>注:需要引入JSTL核心标签库和国际化标签库。
这四个隐含对象表示先前讨论的各种属性作用域。可以用它们来查找特定作用域中的标识符,而不用依赖于 EL 在默认情况下使用的顺序(首先 page,然后 request、 session,再 application)查找过程。 它们和 JSP 中的 page、 request、 session 以及 application 隐含对象非常相似,但是有一点要注意的,这里的四个隐含对象只能用来取得范围属性值,而不能取得其他相关信息。 下面创建一个 scope.jsp 文件。首先使用<c:set>标签在不同的范围内( page、 request、 session 和application)设置相同的 name 变量,然后调用相应的 pageScope、 requestScope、 sessionScope 以及applicationScope 隐含对象来取得 name 变量值。
<head><title>pageScope、requestScope、sessionScope以及applicationScope隐含对象在EL中使用</title></head> <body> <h4>EL中的pageScope、requestScope、sessionScope以及applicationScope隐含对象</h4> <hr> <c:set var="name" value="pageValue" scope="page" /> <c:set var="name" value="requestValue" scope="request" /> <c:set var="name" value="sessionValue" scope="session" /> <c:set var="name" value="applicationValue" scope="application" /> \${name}: <c:out value="${name}" /> <br> \${pageScope.name}: <c:out value="${pageScope.name}" /> <br> \${requestScope.name}: <c:out value="${requestScope.name}" /> <br> \${sessionScope.name}: <c:out value="${sessionScope.name}" /> <br> \${applicationScope.name}: <c:out value="${applicationScope.name}" /> <br> </body>cookie 隐式对象提供了对由请求设置的 cookie 名称的访问。这个对象将所有与请求相关联的 cookie名称映射到表示那些 cookie 特性的 Cookie 对象。 JSTL 标准标签并没有提供设置 cookie 的动作,因此这个动作通常都是开发者必须要去做的事情,而不是交给前端。如已经在 cookie 中设置了一个 name 的值,则可以通过${cookie.name}来取得它的值。 最后一个 EL 隐式对象 initParam 也是一个映射,它储存与 Web 应用程序相关联的所有上下文的初始化参数的名称和值。初始化参数是通过 web.xml 部署描述符文件指定的,该文件位于应用程序的WEB-INF 目录中。例如在 web.xml 文件中设定如下:
<context-param> <param-name>username</param-name> <param-value>Johnson</param-value> </content-param>那么在程序当中就可以直接使用${initParam.username}来取得 username 参数的值“ Johnson”。 参考资料:
《JSP宝典》