j2EE|EL表达式的使用

在JSP 2.0的页面中,我们使用下面形式的元素调用表达式语言:
${expression}
EL可以出现在JSP页面的模板文本中,也可以出现在JSP标签的属性中。
下面是在JSP模板文本中使用表达式:


  • 客户名:${customer.custName}
  • Email地址:${customer.email}

下面是在JSP标准动作的属性中使用EL表达式:



表达式语言的功能
(1)提供了一组简单的运算符。表达式语言提供了一组简单有效的运算符,通过这些运算符可以完成算术、关系、逻辑、条件或空值检查运算。
(2)对作用域变量的方便访问。作用域变量是使用setAttribute()方法存储在PageContext、HttpServletRequest、HttpSession或ServletContext作用域中的对象,可以简单地使用下面的形式访问:
${userName}

(3)对JavaBeans对象访问的简单表示。在JSP页面中要访问一个JavaBean对象customer的custName属性,需要下面的语法:

而使用EL表达式,可以表示为:
${customer.custName}
(4)对集合元素的简单访问。集合包括数组、List对象、Map对象等,对这些对象的元素的访问可以使用下面的简单形式:
${variable[indexOrKey]}

(5)对请求参数、Cookie和其他请求数据的简单访问。如要访问Accept请求头,可以使用header隐含变量,如下所示:
${header.Accept}或${header["Accept"]}
(6)提供了在EL中使用Java函数的功能。EL中不能定义和使用变量,也不能调用对象的方法,但可以通过标签的形式使用Java语言定义的函数。

EL表达式和JSP的区别:
JSP表达式的使用格式为:

这里的expression为合法的Java表达式,它属于脚本语言的代码。在expression中可以使用由脚本声明的变量。
EL表达式的格式为:
${expression}
这里的expression是符合EL规范的表达式,并且不需要包含在标签内的。在EL表达式不能使用脚本中声明的变量。

使用传统的脚本语言,很容易在JSP中声明变量,使用的标签为,例如:

这里声明了一个整型变量,接下来使用下面的JSP表达式语句,这将输出变量count的值为100:
The count value is :
而如果使用下面的语句,将返回一个空值,即用EL的empty运算符测试结果为true。
The count value is: ${count}
在EL中不能定义变量,也不能使用脚本中声明的变量,但它可以访问请求参数、作用域变量、JavaBeans以及EL隐含变量等。

E算数运算符:
算术运算符说明示例结果
+加${6.80 + -12}-5.2
-减${15-5}10
*乘${2 * 3.14159}6.28318
/或div除${25 div 5} 与 ${25/5}5.0
%或mod取余${24 mod 5} 与 ${24 % 5} 4

在EL表达式中还可以使用“e”在浮点数中表示幂运算,例如:
${1.5e6/1000000} 的结果为 1.5;
${1e6 * 1} 的结果为 1000000.0。
这些操作在执行时调用类中的方法,但是要注意操作结果的数据类型。例如,定点数和浮点数的运算结果总是浮点数值。类似地,低精度的值与高精度的值进行运算,如一个Integer的值与一个BigInteger的值相加,总是得到一个高精度的值。
与数值一样,String对象上也可以使用算术运算符,只要String对象能够转换为数值即可,例如:
${"16" * 4} 的结果为 64,字符串被转换成整数16;
${a div 4} 的结果为 0.0,a没有定义,它的默认值为0;
${"a" div 4} 将产生编译错误,字符串“a”不能和数值运算。
关系运算符 说明示例结果
== 或 eq相等${3==5}或${3 eq 5}false
!= 或ne不相等 ${3!=5}或${3 ne 5}true
< 或lt小于 ${3<5}或${3 lt 5}true
> 或gt大于 ${3>5}或${3 gt 5}false
<= 或le小于等于 ${3<=5}或${3 le 5}true
>= 或ge大于等于 ${3>=5}或${3 ge 5}false

在EL中不允许使用Java的流程控制语句,如if、for及while,因此,逻辑表达式的使用是直接显示表达式的boolean值。

EL的条件运算符的语法是:
expression ? expression1 : expression2
表达式的值是基于expression的值,它是一个boolean表达式。如果expression的值为true,则返回expression1结果;如果expression的值为false,则返回expression2的结果。例如:
${(5 * 5) == 25 ? 1 : 0} 的结果为 1;
${(3 gt 2) && !(12 gt 6) ? "Right" : "Wrong"} 的结果为Wrong;
${("14" eq 14.0) && (14 le 16) ? "Yes" : "No"} 的结果为Yes;
${(4.0 ne 4) || (100 <= 10) ? 1 : 0} 的结果为 0。

empty运算符的使用格式为:
${empty expression}
它判断expression的值是否为null、空字符串、空数组、空Map或空集合,若是则返回true,否则返回false。

属性和几何元素的访问运算符
属性访问运算符用来访问对象的成员,集合访问运算符用来检索Map、List或数组对象的元素。这些运算符在处理隐含变量时特别有用。在EL中,这类运算符有下面两个:
? 点号(.)运算符。
? 方括号([])运算符。

1. 点号(.)运算符
点号运算符用来访问Map对象一个键的值或bean对象的属性值,例如:param是EL的一个隐含对象,它是一个Map对象,下面代码返回param对象username请求参数的值:
${param.username}
再比如,假设customer是CustomerBean类的一个实例,下面代码访问该实例的custName属性值:
${customer.custName}

2. 方括号([])运算符
方括号运算符除了可以访问Map对象键值和bean的属性值外,还可以访问List对象和数组对象的元素。例如:
${ param ["username"]}或${ param ['username']}
${customer["custName"]}

访问作用域变量:
在JSP页面中,可以使用JSP表达式访问作用域变量。
一般做法是:在Servlet中使用setAttribute()方法将一个变量存储到某个作用域对象上,如HttpServletRequest、HttpSession及ServletContext等。然后使用RequestDispatcher对象的forward()方法将请求转发到JSP页面,在JSP页面中调用隐含变量的getAttribute()方法返回作用域变量的值。
使用EL就可以更方便地访问这些作用域变量。要输出作用域变量的值,只需在EL中使用变量名即可,例如:
${variable_name}
对该表达式,容器将依次在页面作用域、请求作用域、会话作用域和应用作用域中查找名为variable_name的属性。如果找到该属性,则调用它的toString()方法并返回属性值。如果没有找到,则返回空字符串(不是null)。
访问JavaaBean属性:
设有一个名为com.model.CustomerBean的JavaBeans,它有一个名为custName的属性。在JSP页面中如果需要访问custName属性,应使用下面代码实现:



这里使用了pageContext的findAttribute()方法查找名为customer的属性,使用JSP表达式输出custName的值,但是如果找不到指定的属性,上面的代码会抛出NullPointerException异常。

如果知道JavaBeans的完整名称和它的作用域,也可以使用下面JSP标准动作访问JavaBeans的属性:
scope="session" />



如果使用表达式语言,就可以通过点号表示法很方便地访问JavaBeans的属性,如下所示:
${customer.custName}
使用表达式语言,如果没有找到指定的属性不会抛出异常,而是返回空字符串。

使用表达式语言还允许访问嵌套属性。例如,如果CustomerBean有一个address属性,它的类型为AddressBean,而AddressBean又有zipCode属性,则可以使用下面简单形式访问zipCode属性:
${customer.address.zipCode}
上面的方法不能使用实现。
下面通过一个示例来说明对JavaBeans属性的访问。该例中有两个JavaBeans,分别为AddressBean,它有三个字符串类型的属性,city、street和zipCode;CustomerBean是在前面的类的基础上增加了一个AddressBean类型的属性address表示地址。

在CustomerServlet.java程序中创建了一个CustomerBean对象并将其设置为请求作用域的一个属性,然后将请求转发到JSP页面,在JSP页面中使用下面的EL访问客户地址的三个属性:
  • city:${customer.address.city}
  • street: ${customer.address.street}
  • zipCode:${customer.address.zipCode}

    访问集合元素:
    在EL中可以访问各种集合对象的元素,集合可以是数组、List对象或Map对象。这需要使用数组记法的运算符([])。例如,假设有一个上述类型的对象attributeName,可以使用下面形式访问其元素:
    ${attributeName[entryName]}


    如果attributeName对象是数组,则entryName为下标。上述表达式返回指定下标的元素值。

    (1)下面代码演示了访问数组元素:

    My favorite fruit is:${favoriteList [2]}
    上面一行还可以写成:
    My favorite fruit is:${favoriteList ["2"]}

    (2)如果attributeName对象是实现了List接口的对象,则entryName为索引。
    下面代码演示了访问List元素:


    My favorite fruit is:${favoriteList [2]}

    (3)如果attributeName对象是实现了Map接口的对象,则entryName为键,相应的值通过Map对象的get(key)方法获得的,例如:


    The capital of China is:${capital["China"]}
    The capital of Russia is:${capital.Russia}

    在EL中访问隐含的变量:
    在JSP页面中可以访问JSP隐含变量,如request、session、application等。在EL表达式中也定义了一套自己的隐含变量。使用EL可以直接访问这些隐含变量。

    【j2EE|EL表达式的使用】1. pageContext变量
    pageContext是PageContext类型的变量。PageContext类依次拥有request、response、session、out和servletContext属性,使用pageContext变量可以访问这些属性的属性。
    下面是一些例子:

    ${pageContext.request.method}//获得HTTP请求的方法,如GET或POST。
    ${pageContext.request.queryString}//获得请求的查询串
    ${pageContext.request.requestURL}//获得请求的URL
    ${pageContext.request.remoteAddr}//获得请求的IP地址
    ${pageContext.session.id}//获得会话的ID
    ${pageContext.session.new}//判断会话对象是否是新建的
    ${pageContext.servletContext.serverInfo}//获得服务器的信息
    上述EL是通过成员访问运算符访问对象的属性。在EL中不允许调用对象的方法,所以下面的使用是错误的:
    ${pageContext.request.getMethod()}
    然而,仍然可以使用下面的脚本表达式:

    2. param和paramValues变量
    param和paramValues变量用来从ServletRequest中检索请求参数值。param变量是调用给定参数名的getParameter(String name)方法的结果,使用EL表示如下:
    ${param.name}
    类似地,paramValues是使用getParameterValues(String name)方法返回给定名称的参数值的数组。要访问参数值数组的第一个元素,可使用下面代码:
    ${paramValues.name[0]}
    上述代码也可以用下面两种形式表示:
    ${paramValues.name["0"]}
    ${paramValues.name['0']}
    因为数组元素是按整数下标访问的,因此必须使用“[]”运算符访问数组元素。下面两个表达式都会产生编译错误:
    ${paramValues.name.0}
    ${paramValues.name."0"}
    所以,EL在处理属性和集合的访问时与传统的Java语法并不完全一样。
    3. header和headerValues变量
    header和headerValues变量是从HTTP请求头中检索值,它们的运行机制与param和paramValues类似。下面代码使用EL显示了请求头host的值。
    ${header.host}或${header["host"]}
    类似地,headerValues.host是一个数组,它的第一个元素可使用下列表达式之一显示:
    ${headerValues.host[0]}
    ${headerValues.host["0"]}
    ${headerValues.host['0']}
    4. cookie变量
    在Servlet中向客户发送一个Cookie可以使用下面代码:
    Cookie cookie = new Cookie("userName","Hacker");
    response.addCookie(cookie);
    要检索客户发给服务器的Cookie,应该使用下面代码:
    Cookie[] cookies = request.getCookies();
    for(int i =0; iif((cookies[i].getName()).equals("userName")){
    out.println(cookies[i].getValue());
    }
    }
    在JSP页面中可以使用EL的cookie隐含变量得到客户向服务器发回的Cookie数组,即调用request对象的getCookies()方法的返回结果。如果要访问cookie的值,则需要使用Cookie类的属性value(即getValue方法)。因此,下面一行可以输出名为userName的Cookie的值。如果没有找到这个cookie对象,则输出空字符串:
    ${cookie.userName.value}
    使用cookie变量还可以访问会话Cookie的ID值,例如:
    ${cookie.JSESSIONID.value}

    5. initParam变量
    initParam变量存储了Servlet上下文的参数名和参数值。例如,假设在DD中定义了如下初始化参数:

    email
    hacker@163.com

    则可以使用下面的EL表达式得到参数email的值:
    ${initParam.email}
    如果通过JSP脚本元素访问该Servlet上下文参数,应该使用下面表达式:


    6. pageScope、requestScope、sessionScope和applicationScope变量
    这几个隐含变量很容易理解,它们用来限定访问不同作用域的属性。例如,下面代码在会话作用域中添加一个表示商品价格的totalPrice属性,然后使用EL访问该属性值:

    ${sessionScope.totalPrice}
    注意,访问应用作用域的属性应使用applicationScope变量而不是使用pageContext变量。

    在EL中使用函数:
    创建静态的方法:
    在JSP页面中使用EL函数需要创建下面三个文件:
    (1)方法的类文件(*.java),它定义了在JSP中要使用的Java方法。
    (2)标签库描述文件(*.tld),它实现将每个Java方法与函数名的映射。
    (3)JSP文件(*.jsp),使用标签库URI以及函数名调用Java方法。

    开发EL函数首先要创建在JSP中要调用的Java方法。在下面的例子中,创建了一个名为add(String x,String y)的方法来计算传递的两个字符串参数的和。
    程序9.11Compute.java
    在创建EL函数时请记住下面这些要点:
    (1)类需要声明为public,方法需要声明为public static。这样容器可以不用创建新对象就可以访问类的方法。
    (2)类文件要保存在 /WEB-INF/classes目录中。
    (3)在EL中方法的参数和返回值必须合法。否则,Web容器将不能识别方法的签名。

    要在JSP页面中调用这些方法还要创建一个标签库描述文件。标签库描述文件(Tag Library Descriptor,TLD)的主要作用是定义静态方法与函数名之间的映射。
    下面的TLD文件就实现了add()方法与名为add的函数之间的映射。
    程序9.12sampleLib.tld


    9.4.1创建静态(static)方法
    9.4.3在JSP中访问EL函数

    创建了TLD文件后,在JSP中调用Java函数就非常简单了,这主要包括两步:
    (1)通过taglib指令指定函数使用的前缀(prefix)和函数的URI,该URI必须与TLD文件中定义的元素的值匹配。
    (2)使用前缀名和函数名创建EL表达式。
    程序9.13sum.jsp



      推荐阅读