Expression Language リファレンス

Expression Language

式言語 (Expression Language, EL) とは JSP 2.0 から導入された埋め込み型言語です。 元々は <%= %> の代わりに属性値を記述できるよう JSTL で規定されたものでしたが、Java EE 5 での JSTL 標準化により JSP の標準機能となりました。 JSP 内の静的なテキストの中や拡張タグに渡す属性値の部分に以下の形式で記述することが出来ます。

${expression}

expression 部分には foo, foo.bar などの変数や 後述の演算子を用いた簡単な演算、ユーザ定義の関数などを記述することが出来ます。


web.xml を Servlet API 2.3 以前のバージョンで宣言している場合、JSP 内の EL が評価されなので注意してください。

<!DOCTYPE
    web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
...

上記のような DTD での宣言が行われているなら Servlet API 2.4 の Schema を使用した宣言に変更する必要があります。

<web-app
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
...

暗黙オブジェクト

EL では以下の暗黙オブジェクト (Implicit Object) を使用することが出来ます。

pageContext.servletContext Bean この JSP のサーブレットが所属するコンテキスト。
pageContext.session Bean クライアントに対するセッションオブジェクト。
pageContext.request Bean JSP の実行を行っているリクエスト。
pageContext.response Bean JSP から返すレスポンス。
param Map リクエストパラメータのマップ。
paramValues Map リクエストパラメータのマップ (配列値)。
header Map リクエストヘッダのマップ。
headerValues Map リクエストヘッダのマップ (配列値)。
cookie Map Cookie のマップ。
initParam Map コンテキストの初期化パラメータのマップ。
pageScope Map ページスコープ変数のマップ。
requestScope Map リクエストスコープ変数のマップ。
sessoinScope Map セッションスコープ変数のマップ。
applicationScope Map アプリケーションスコープ変数のマップ。

変数

EL における変数は 「親コンテキストに従属する識別子」という形式で表現されます。 これは parent.identifier あるいは parent['identifier'] と記述します (foo.barfoo['bar'] と同じです)。

親コンテキスト識別子識別子の型
Bean プロパティ名 文字列 foo.bar, foo['bar']
(foo.getBar() と等価)
Map キー 任意 map.key, map['key']
(map.get("key") と等価)
List, 配列 インデックス int list[1], array[1]
(list.get(1), array[1] と等価)

いくつかの状況では [] でしか識別子を指定できません。

  • 識別子を動的に指定したい (×foo.(bar+i) → ○foo['bar'+i])
  • 識別子を EL の変数として記述できない (×foo.(biz.moyo.lab.user-list) → ○foo['biz.moyo.lab.user-list'])
  • 親コンテキストがリストまたは配列 (×foo.0 → ○foo[0])

暗黙オブジェクト以外のオブジェクトは JSP で定義されている 4 つのスコープから page, request, session, application の順序で検索されます。

データ型とキーワード、演算子

EL で使用できるリテラルと演算子を以下に記述します。 演算子の優先順位は Java でのそれと同じです。

数値 Integer, Double 等の valueOf() が認識できる形式
文字列 " または ' で囲み (エスケープ文字は \", \', \\)。
null null 値
true ブール代数 true
false ブール代数 false
[], . フィールドアクセス
() 括弧
empty 右辺値の文字列,コレクション,配列が null または長さ 0 の場合 true
+, -, *, /, div, %, mod 四則演算子と余剰演算子
- 単項マイナス演算子
&&, and, ||, or, !, not 論理演算子
==, eq, !=, ne, <, lt, >, gt, <=, le, >=, ge 比較演算子
A? B: C 3項条件演算子
instanceof 予約のみ?

ユーザ定義関数

TLD (タグライブラリ記述子) で定義した関数を EL で使用することが出来ます。 JSTL 標準の functions でもいくつか簡単な関数が用意されていますが、ここでは 自分で作成した機能を関数として使用する方法を記述します。

関数と言っても単に Java の static メソッドを作成するだけで、 特別なクラスやインターフェースの知識は必要はありません。 例として IP アドレスと本日日付に基づいた 8 桁の文字列を返すメソッドを作成します。

package biz.moyo.lab.app.func;
import sun.misc.BASE64Encoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyELFunctions{
    private static String getRemoteHash(String addr){
        try{
            addr += new SimpleDateFormat("yyyyMMdd").format(new Date());
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] binary = md.digest(addr.getBytes("UTF-8"));
            BASE64Encoder e = new BASE64Encoder();
            return e.encode(binary).substring(0, 8);
        } catch(Exception ex){/* */}
        return "--------";
    }
}

次に、TLD ファイル /WEB-INF/tld/myfunc.tld (場所や名前は何でもいい) に 「makeRemoteHash() が呼ばれたら MyELFunctions#getRemoteHash() を実行する」 と 定義します (同じ名前でなくても良いことを示すためにあえて名前は変えてあります)。

<function>
    <name>makeRemoteHash</name>
    <function-class>biz.moyo.lab.app.func.MyELFunctions</function-class>
    <function-signature>
        java.lang.String getRemoteHash(java.lang.String)
    </function-signature>
</function>

最後に JSP 内で <%@taglib%> を使用して前述の TLD で定義した関数を使用します。

<%@ taglib prefix="mf" uri="/WEB-INF/tld/myfunc.tld"%>
...
<c:out value="${mf:makeRemoteHash(request.remoteAddr)}" />

page スコープに設定されている foo という名前のオブジェクトを出力します。

<c:set var="foo" value="hello, world" />
<c:out value="${foo}" />
 
→ hello, world

<c:out> を用いなくても出力を行うことは出来ますが HTML エスケープが行われません。 この使い方は値に <, > のような文字が含まれないことが 確実な場合 (例えば結果が int 型など) のみにし、それ以外は <c:out> か JSTL functions の escapeXml() 関数を使用してください。

<c:set var="foo" value="<b>hello, world&#x2620;</b>" />
${foo}
<c:out value="${foo}" />
${fn:escapeXml(foo)}
 
→ hello, world☠
→ <b>hello, world&#x2620;</b>
→ <b>hello, world&#x2620;</b>

演算子を用いて簡単な演算を行うことが出来ます。

<% pageContext.setAttribute("foo", new String[]{"A","B","C"}); %>
1 + 1 := <c:out value="${1 + 1}" />
<span style="font-weight:${empty foo?'normal;':'bold'};">hello,world</span>
${fn:length(foo)}
 
→ 1 + 1 := 2
→ hello,world 
→ 3