使用 EL 取得屬性


你可以在 JSP 中將物件設定至 pagerequestsessionapplication 範圍中作為屬性,基本上是透過 setAttribute() 方法設定屬性,使用 getAttribute() 取得屬性,但這些方法呼叫必須在 Scriptlet 中進行。如果不想撰寫 Scriptlet,可以考慮使用 <jsp:useBean><jsp:setProperty><jsp:getProperty>

不過 <jsp:getProperty> 在使用上,語法仍是較為冗長。如果只是要取得屬性,使用 EL 則可以更為簡潔。例如:

<h1><jsp:getProperty name="user" property="name"/>登入成功</h1>

如果使用 EL 來撰寫的話,則可以修改如下:

<h1>${user.name}登入成功</h1>

在 EL 中,可以使用 EL 隱含物件指定範圍來存取屬性,EL 隱含物件將在稍後介紹。

若不指定屬性的存在範圍,則預設是以 pagerequestsessionapplication 的順序來尋找 EL 中所指定的屬性。以上例而言,就是在 page 範圍中找到了 user 屬性,點運算子後跟隨著 name,表示利用物件的 getName() 方法取得值,而後顯示在網頁上。

如果 EL 存取的對象是個陣列物件,則可以使用 [] 運算子來指定索引以存取陣列中的元素。例如若網頁的某處在請求範圍中設定了陣列作為屬性:

<%
    String[] names = {"caterpillar", "momor", "hamimi"};
    request.setAttribute("array", names);
%>

如果現在打算取出屬性,並存取陣列中的每個元素,則可以如下使用 EL:

名稱一 : ${array[0]} <br>
名稱二: ${array[1]} <br>
名稱三: ${array[2]} <br>

不僅僅是陣列物件可以在 [] 中指定索引來存取元素,如果屬性是個 List 型態的物件,也可以使用 [] 運算子指定索引來進行存取元素。

點運算子(.)與 [] 運算子需要特別說明。在某些情況下,可以使用點運算子(.)的場合,也可以使用 []運算子。以下先列點歸納:

  • 如果使用點(.)運算子,則左邊可以是 JavaBean 或 Map 物件。
  • 如果使用 [] 運算子,則左邊可以是 JavaBean、Map、陣列或 List物件。

所以你不只可以使用點(.)運算子來取得 JavaBean 屬性,也可以使用 [] 運算子。例如,你可以用點(.)運算子取得 Username 屬性:

${user.name}

也可以使用 [] 運算子來取得取得 Username 屬性:

${user["name"]}

如果想取得 Map 物件中的值,點(.)運算子或[]運算子都可以使用。例如網頁中若有某個地方有以下的程式碼:

<%
    Map<String, String> map = new HashMap<>();
    map.put("user", "caterpillar");
    map.put("role", "admin");
    request.setAttribute("login", map);
%>

則你可以在網頁某處使用點運算子取得 Map 中的值:

User: ${login.user}<br>
Role: ${login.role}<br>

也可以在網頁某處使用 [] 運算子取得 Map 中的值:

User: ${login["user"]}<br>
Role: ${login["role"]}<br>

基本上,當左邊是 Map 物件時,建議使用 [] 運算子,因為如果設定 Map 時的鍵名稱有空白或點字元時,這是讓你可以正確取得值的方式。例如:

<%
    Map<String, String> map = new HashMap<>();
    map.put("user name", "caterpillar");
    map.put("local.role", "admin");
    request.setAttribute("login", map);
%>
...
User: ${login["user name"]}<br>
Role: ${login["local.role"]}<br>

[] 運算子的右邊,除了可以是 JavaBean、Map 外,也可以是陣列或 List 型態的物件。之前示範過陣列的例子,以下則是個 List 的例子:

<%
    List<String> names = new ArrayList<>();
    names.add("caterpillar");
    names.add("momor");
    request.setAttribute("names", names);
%>
...
User 1: ${names[0]}<br>
User 2: ${names[1]}<br>

你也可以在指定索引時使用雙引號,例如 ${names["0"]},不過一般指定索引不會這麼特別寫。事實上,當 [] 運算子當是使用雙引號(")指定時,就是作為鍵名稱或索引來使用。如果 [] 運算子中不是使用雙引號,則會嘗試作運算,結果再給 []來使用。例如:

<%
    List<String> names = new ArrayList<>();
    names.add("caterpillar");
    names.add("momor");
    request.setAttribute("names", names);
%>
...
User : ${names[param.index]}<br>

在這個範例的 EL 中,使用了 param.indexparam 是 EL 隱含物件,表示請求參數,這個範例會先尋找請求參數中 index 的值,然後再作為索引值給 [] 使用。所以如果請求時使用了 index=0,則顯示 "caterpillar",使用 index=1,則顯示 "momor"。所以,[] 中也可以進行巢狀。例如:

<%
    List<String> names = new ArrayList<>();
    names.add("caterpillar");
    names.add("momor");
    request.setAttribute("names", names);

    Map<String, String> datas = new HashMap<>();
    datas.put("caterpillar", "caterpillar's data");
    datas.put("momor", "momor's data");
    request.setAttribute("datas", datas);
%>
// ...
User data: ${datas[names[param.index]]}<br>

根據 EL,如果如果請求時使用了 index=0,則會取得 names 中索引 0 的值 "caterpillar",然後用取得的值作為鍵,再從 datas 中取得對應的 "caterpillar's data"