如果你設計了一個 Util
類別,當中有個 length()
靜態方法可以將所傳入的 Collection
長度傳回。例如原先可能這麼使用它:
<%= Util.length(reqeust.getAttribute("someList")) %>
如果 someList
實際上是個 List
介面實作,而其長度為 10,這會傳回結果 10。
如果函式的部份也可以使用 EL 來呼叫,以下也許是你想要的撰寫方式:
${ util:length(requestScope.someList) }
這樣的寫法著實簡潔許多,如果這是你想要的需求,則可以自訂 EL 函式來滿足這項需求。自訂 EL 函式的第一步是撰寫類別,它必須是個公開(public
)類別,而想要呼叫的方法必須是公開且為靜態方法。例如你的 Util
類別可能是這麼撰寫的:
package cc.openhome;
import java.util.Collection;
public class Util {
public static int length(Collection collection) {
return collection.size();
}
}
Web 容器必須知道如何將這個類別中的 length()
方法當作 EL 函式來使用,所以你必須撰寫一個標籤程式庫描述檔(Tag Library Descriptor, TLD)檔案,這個檔案是個 XML 文件,副檔名為 *.tld。例如:
openhome.tld
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
<tlib-version>1.0</tlib-version>
<short-name>openhome</short-name>
<uri>https://openhome.cc/util</uri>
<function>
<description>Collection Length</description>
<name>length</name>
<function-class>
cc.openhome.Util
</function-class>
<function-signature>
int length(java.util.Collection)
</function-signature>
</function>
</taglib>
在 TLD 檔案中,重要的部份已在程式碼中直接標示。${util.length(...)}
的例子中,length
名稱就對應於 <name>
標籤的設定,而實際上 length
名稱背後執行的類別與真正的靜態方法,則分別由 <function-class>
與 <function-signature>
來設定。至於 <uri>
標籤則是在 JSP 網頁中會使用到,稍後就會了解其作用。
你可以將這個 TLD 檔案直接放在 WEB-INF 資料夾下,如此容器會自動找到 TLD 檔案並載入。如果要放在JAR檔案中,設定的方式之後還會作說明。在這邊為了簡化,先將 TLD 檔案放在 WEB-INF 資料夾下。接著可以撰寫一個 JSP 來使用這個自訂 EL 函式。例如:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="util" uri="https://openhome.cc/util"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>自訂EL函式</title>
</head>
<body>
${ util:length(requestScope.someList) }
</body>
</html>
在這邊使用 taglib
指示元素告訴容器,在轉譯這個 JSP 時,會用到對應 uri
屬性的自訂 EL 函式,容器會尋找讀入的 TLD 中,<uri>
標籤設定中有對應 uri
屬性的名稱,這就是剛才在 openhome.tld 中定義 <uri>
標籤的目的。至於 prefix
屬性則是設定前置名稱,如此若 JSP 中有多個來自不同設計者的 EL 自訂函式時,就可以避免名稱衝突的問題,所以要使用這個自訂 EL 函式時,就可以用 ${util:length(...)}
的方式。