EL表達式詳解

JSP 2.0中,JSP容器自己可以理解EL表達式。這使你在所有過去只能應用Java表達式的地方應用EL表達式成爲可能,比如:標準和定製action的屬性值,模板文本。

在我們看具體的例子前,讓我們更進一步的看看 什麼是EL。EL是從JavaScript中獲得啓發的一種語言,XPath(一種用來訪問XML文檔的語言),但是EL在對變量的null值和執行更多 數據類型的自動類型轉換的處理上更加寬鬆。這些新特性對於web應用非常重要,在這些應用中輸入通常通過html表單的request parameter來得到。這些參數可能僅僅在某些請求下才能體現出來,而且瀏覽器經常將request parameter作爲文本發送,然而應用程序經常需要把他們作爲數字類型、布爾類型(true 或者 false)來使用。通過EL,你根本就很少需要關心缺少某些參數的值或者類型轉換。

一個EL表達式包含變量和操作符。任何存儲在某個JSP作用範圍(如:page、 request、session、application)的bean能被作爲一個EL變量來使用。另外,EL支持以下預定義的變量: 
變量名稱 
說明

pageScope 
一個包含所有page scope範圍的變量集合 (a java.util.Map)

requestScope 
一個包含所有request scope範圍的變量集合 (a java.util.Map)

sessionScope 
一個包含所有session scope範圍的變量集合 (a java.util.Map)

applicationScope 
一個包含所有application scope範圍的變量集合 (a java.util.Map)

param 
一個包含所有請求參數的集合 (a java.util.Map),通過每個參數對應一個String值的方式賦值

paramValues 
一個包含所有請求參數的集合 (a java.util.Map),通過每個參數對應一個String數組的方式賦值

header 
一個包含所有請求的頭信息的集合, (a java.util.Map) ,通過每個頭信息對應一個String值的方式賦值

headerValues 
一個包含所有請求的頭信息的集合 (a java.util.Map) ,通過每個頭信息的值都保存在一個String數組的方式賦值

cookie 
一個包含所有請求的 cookie集合 (a java.util.Map), 通過每一個cookie(javax.servlet.http.Cookie)對應一個cookie值的方式賦值

initParam 
一個包含所有應用程序初始化參數的集合(a java.util.Map) ,通過每個參數分別對應一個String值的方式賦值

pageContext 
一個javax.servlet.jsp.PageContext類的實例, 用來提供訪問不同的請求數據


操作符描述了你對變量所期望的操作。如果你之前曾經使用過任何編程語言的話,在EL表達式中所使用的操作符對你來說可能看起來很熟悉。因爲它們和那些在大多數語言中所支持的操作符一樣。 
Operator 
Description


訪問一個bean屬性或者 Map entry

[] 
訪問一個數組或者鏈表元素

() 
對子表達式分組,用來改變賦值順序

? : 
條件語句,比如: 條件 ? ifTrue : ifFalse.如果條件爲真,表達式值爲前者,反之爲後者


數學運算符,加操作


數學運算符,減操作或者對一個值取反


數學運算符,乘操作

/ or div 
數學運算符,除操作

% or mod 
數學運算符,模操作(取餘)

== or eq 
邏輯運算符,判斷符號左右兩端是否相等,如果相等返回true,否則返回false

!= or ne 
邏輯運算符,判斷符號左右兩端是否不相等,如果不相等返回true,否則返回false

< or lt 
邏輯運算符,判斷符號左邊是否小於右邊,如果小於返回true,否則返回false

> or gt 
邏輯運算符,判斷符號左邊是否大於右邊,如果大於返回true,否則返回false

<= or le 
邏輯運算符,判斷符號左邊是否小於或者等於右邊,如果小於或者等於返回true,否則返回false

>= or ge 
邏輯運算符,判斷符號左邊是否大於或者等於右邊,如果大於或者等於返回true,否則返回false

&& or and 
邏輯運算符,與操作賦。如果左右兩邊同爲true返回true,否則返回false

|| or or 
邏輯運算符,或操作賦。如果左右兩邊有任何一邊爲true返回true,否則返回false

! or not 
邏輯運算符,非操作賦。如果對true取運算返回false,否則返回true

empty 
用來對一個空變量值進行判斷: null、一個空String、空數組、 空Map、沒有條目的Collection集合

func(args) 
調用方法, func是方法名,args是參數,可以沒有,或者有一個、多個參數.參數間用逗號隔開


一個EL表達式可以包含:數字、文本(在單引號或者雙引號之間)、布爾值、null值。

因爲一個EL表達式可以出現在靜態文本出現的 地方,因此你必須告訴JSP容器它應該被當作一個EL表達式來處理。你可以通過使用定界符來做到這一點。一個EL表達式總是以”${ }”來標記(一個“$”符號和一個左花括號,右花括號)。這裏有一個EL表達式,它將一個命名爲amount的變量加5:

${amount + 5}

如果你想要將5加到一個bean的property上,可以使用property訪問操作符:

${order.amount + 5}

在當前這個指定的bean或者collection集合中,Property訪問操作符(一個“.“符號)告訴EL去尋找名字爲amount的property。

${order['amount'] + 5}

在[]之間的值必須是一個property的名字(就像上面的例子中那樣)或者是一個保存property名字的變量(或者是一個完整的EL子表達式)。

EL表達式可以被用來賦值給任何標準的或者定製的JSP行爲屬性(action attribute),這些行爲屬性被標記爲可以接受動態值(或者請求期間的屬性值,就象它被正式調用一樣):

<c:out value="${order.amount + 5}"/>

在JSP 2.0之前,你不得不使用Java表達式去給一個屬性動態賦值。在過去的很多年中,這已經成爲語法混亂的一個普遍根源。

最後,EL表達式可以在頁面中和模板直接混合使用。當你生成HTML並且需要設置一個動態值給一個屬性的時候,這非常方便:

<input name="firstName" value="${customer.firstName}">

JSP 1.2中,你不得不使用JSTL的<c:out>來實現同樣的事情,最後把各種不同類型的元素混合起來,這導致程序理解起來非常的困難:

<input name="firstName" 

value="<c:out value="${customer.firstName}"/>" >


新JSTL 1.1 Tag Library 標識符

JSTL1.1發佈的是一個初級的版本,主要 目的是用來整合JSTL和JSP2.0 。最明顯的變化是JSTL1.0 “孿生函數庫”(一組庫用來接受EL表達式,另外一組用來接受JAVA表達式),而它們已經被一組既可以用於EL表達式也可以用於JAVA表達式的函數庫 所代替。

在JSTL 1.1中使用以下標識符: 
庫 
URI 
前綴

Core 
http://java.sun.com/jsp/jstl/core 
c

XML processing 
http://java.sun.com/jsp/jstl/xml 
x

I18N formatting 
http://java.sun.com/jsp/jstl/fmt 
fmt

Database access 
http://java.sun.com/jsp/jstl/sql 
sql

Functions 
http://java.sun.com/jsp/jstl/functions 
fn


如果你曾經使用過JSTL1.0,你可能會注意到新的標識符和舊的EL庫標試符一模一樣,除了加入了“/jsp path” element。你也可能注意到在JSTL1.1中有一個庫,包含了EL的函數。我們稍後就會看到。

一個新的EL操作符

在JSP頁面中一個非常普遍的需求就是:當某 個條件爲真時,要在網頁中包含一些文字。在JSP1.2和JSTL1.1中,用具有代表性的<c:if>來實現,但是這樣做非常繁瑣。 JSP2.0增加了一個新的條件操作符用於EL,以更加優雅的方式來處理這樣的情況。這個條件操作符存在於很多編程語言中(比 如:Java,C,JavaScript),因此你可能以前就見過它。它判斷一個布爾的條件,當條件爲真或者假時,分別取不同的結果。

一個能清楚說明它如何工作的例子:

<select name="artist">

<option value="1" ${param.artist == 1 ? 'selected' : ''}>

Vesica Pisces

<option value="2" ${param.artist == 2 ? 'selected' : ''}>

Cortical Control

<option value="3" ${param.artist == 3 ? 'selected' : ''}>

Vida Vierra

</select> 

在這裏,我使用了EL表達式和條件操作符來選 擇是否包含 html 中的 “selected”屬性,只有符合條件的 “option” 才被添加 “selected” 屬性。如果條件(param.artist==1)爲真時,前面的“selected” 才被添加到網頁中;否則就添加後面的(在這裏是空字符串 ‘’)到頁面中。

EL函數

當EL從JSTL規範中移到JSP規範中,它使用了一個如何進行函數調用的技巧。這個EL函數語法非常簡單:方法名,緊接着在圓括號中有一組參數:<%@ taglib prefix="fn"

uri="http://java.sun.com/jsp/jstl/functions" %>

${fn:length(myCollection)} 

這是一個屬於標籤庫中的函數,並且函數名字在頁面中所包含的前綴要指定taglib庫。在這個例子中,我使用了前綴fn,這是JSTL function庫默認的前綴。

標籤庫描述符(Tag Library Descriptor,TLD)將函數名稱映射到一個由JAVA實現的靜態方法中:<function>

<description>

Returns the number of items in a collection or the number of characters in a string.

</description>

<name>length</name>

<function-class>

org.apache.taglibs.standard.functions.Functions

</function-class>

<function-signature>

int length(java.lang.Object)

</function-signature>

</function> 

在這裏最有趣的element 是<function-signature>。它包含一個函數返回類型的聲明,靜態的方法的名字,在圓括號中聲明該方法所有參數的類型(可以 沒有參數或者有多個,參數間用逗號間隔開)。返回值類型和參數類型必須是java的原始類型(Object)或者是其他合法類型。

這個靜態方法 length()在Jakarta Taglibs標準庫中用類似於下面的代碼實現的:public static int length(Object obj)

throws JspTagException {

if (obj == null)

return 0;

if (obj instanceof String)

return ((String)obj).length();

if (obj instanceof Collection)

return ((Collection)obj).size();

if (obj instanceof Map)

return ((Map)obj).size(); 

int count = 0;

if (obj instanceof Iterator) {

Iterator iter = (Iterator) obj;

count = 0;

while (iter.hasNext()) {

count++;

iter.next();

}

return count;

}

if (obj instanceof Enumeration) {

Enumeration enum = (Enumeration) obj;

count = 0;

while (enum.hasMoreElements()) {

count++;

enum.nextElement();

}

return count;

}

try {

count = Array.getLength(obj);

return count;

} catch (IllegalArgumentException ex) {}

throw new JspTagException("Unsupported type"));

}

就像你所看到的,在那裏沒有什麼出奇的地方。它是一個常規的靜態方法,這個函數中通過對運行期中的參數類別的判斷,找出參數的長度。

除了在這個方法中使用的length()方法,JSTL1.1標籤庫還包含了許多其它經常使用的函數: 
函數 
描述

fn:contains(string, substring) 
如果參數string中包含參數substring,返回true

fn:containsIgnoreCase(string, substring) 
如果參數string中包含參數substring(忽略大小寫),返回true

fn:endsWith(string, suffix) 
如果參數 string 以參數suffix結尾,返回true

fn:escapeXml(string) 
將有特殊意義的XML (和HTML)轉換爲對應的XML character entity code,並返回

fn:indexOf(string, substring) 
返回參數substring在參數string中第一次出現的位置

fn:join(array, separator) 
將一個給定的數組array用給定的間隔符separator串在一起,組成一個新的字符串並返回。

fn:length(item) 
返回參數item中包含元素的數量。參數Item類型是數組、collection或者String。如果是String類型,返回值是String中的字符數。

fn:replace(string, before, after) 
返回一個String對象。用參數after字符串替換參數string中所有出現參數before字符串的地方,並返回替換後的結果

fn:split(string, separator) 
返回一個數組,以參數separator 爲分割符分割參數string,分割後的每一部分就是數組的一個元素

fn:startsWith(string, prefix) 
如果參數string以參數prefix開頭,返回true

fn:substring(string, begin, end) 
返回參數string部分字符串, 從參數begin開始到參數end位置,包括end位置的字符

fn:substringAfter(string, substring) 
返回參數substring在參數string中後面的那一部分字符串

fn:substringBefore(string, substring) 
返回參數substring在參數string中前面的那一部分字符串

fn:toLowerCase(string) 
將參數string所有的字符變爲小寫,並將其返回

fn:toUpperCase(string) 
將參數string所有的字符變爲大寫,並將其返回

fn:trim(string) 
去除參數string 首尾的空格,並將其返回


結束語:

在這篇文章中,我從EL講到JSTL1.1規 範、EL新特色和JSTL 1.1函數庫。接下來的部分我將要告訴你:關於JSP error-page的改進和增強; jsp:id 屬性帶來的益處;新的配置屬性描述符;JSP2.0如何使JSP操作XML變得更加容易;自定義標籤庫的新特性。

如果你想要嘗試JSP2.0的新特性,我建議 你使用Apache Tomcat 5。它是最早實現了JSP新規範的容器之一。在公佈最終版本的JSP 2.0規範之前,一個被標記爲“stable”版本的Tomcat是不能被髮布的。但是最新的beta版已經被證實是非常穩定的,不要理會beta版的標 記。Tomcat 5在the Jakarta Project site可以下載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章