EL 3.0


在 Java EE 7 之後,釋出了 Expression Language 3.0,成為一個獨立的規格(JSR 341)。

在 EL 3.0 中,允許指定變數,例如,想要將 a 指定為 "10"b 指定為 "20",可以如下:

${a = "10"}
${b = "20"}

被指定值之後,EL 3.0 會將 ab 的值輸出至頁面,實際上,變數會被指定為頁面範圍屬性,可以使用 pageContext.getAttribute("a") 取得,上面的例子中相當於:

<% pageContext.setAttribute("a", "10") %><%= pageContext.getAttribute("a") %>
<% pageContext.setAttribute("b", "10") %><%= pageContext.getAttribute("b") %>

如果在 EL 運算式中加上分號,可以繼續執行指定的 EL 運算式,而最後一個運算式的結果會顯示在頁面上,例如底下會顯示 20:

${a = "10"; b = "20"}

而底下會顯示 0:

${a = "10"; b = "20"; 0}

如果想要建立 ListSetMap,可以如下:

${scores = [100, 95, 88, 75]}
${names = {"Justin", "Monica", "Irene"}}
${passwords={"Admin" : "123456", "Manager" : "654321"}} 

如果想要串接字串,可以使用 +=,例如:

${firstName = "Justin"}
${lastName = "Lin"}
${firstName += lastName}

注意,這跟一般程式語言中,a += b 相當於 a = a + b 不同,在 ${firstName += lastName} 時,只是用 += 來區別 +,以便表示字串串接,執行過後顯示出串接結果為 "JustinLin",然而 firstName 仍然是 "Justin",如果想要 firstName 被指定為串接後的結果,必須撰寫 ${firstName = firstName += lastName}

+ 仍然是用在數字運算,例如運算的結果會是 30:

${a = "10"}
${b = "20"}
${a + b}

如果 ab 無法被剖析為數值,就會引發 NumberFormatException

然而,以下運算的結果會是 "1020",因為 += 會串接字串:

${a = "10"}
${b = "20"}
${a += b}

你可以直接呼叫物件的方法,例如將字串轉大寫:

${name = "Justin"}
${name.toUpperCase()}

如果呼叫的方法沒有傳回值,那麼就不會顯示結果,例如:

${pageContext.setAttribute("token", "123")}

你甚至可以直接呼叫靜態方法或取用靜態成員,預設 java.lang 中的類別是可以直接呼叫其靜態方法或取用靜態成員的:

${Integer.parseInt("123")}
${Math.round(1.6)}
${Math.PI}

如果要是其他套件中的類別,可以透過 pageContext.getELContext().getImportHandler().importClass(".....") 來追加,例如:

${pageContext.ELContext.importHandler.importClass("java.time.LocalTime")} 
${LocalTime.now()}

除了 importClass() 之外,也可以使用 importPackage()importStatic() 等方法,如果要呼叫建構式的話,直接於類別名稱之後接上 () 就可以了,不用加上 new。例如:

${String("Justin")}

EL 也支援 Lambda 運算式,例如:

${plus = (x, y) ->  x + y}
${plus(10, 20)}
${() -> plus(10, 20) + plus(30, 40)}

如果 Lambda 運算式有參數的話,可以使用 () 指定引數來運算,若沒有參數,那麼會立即運算。

既然 EL 3.0 中,可以呼叫方法,也可以使用 Lambda 運算式,那麼就可以形成 Java SE 8 那種流暢的 Stream 風格:

${names = ["Justin", "Monica", "Irene"]}
${names.stream().filter(name -> name.length() == 5).toList()}