I will be waiting for your knock ever after from today.


Visards, Inc.

Java Sticky Note

java
  ・JSTL
  ・Commons Net
  ・Apache
  ・Tomcat
  ・James
  ・Jetspeed
  ・POI
  ・Jexl
  ・Jelly
  ・Blojsom
  ・eclipse

link
  ・James

author
  ・profile

JSTL  
<< prev | JSTL Index | next >>
Standard TaglibsによるJSTLの利用

mixiチェック

5. ELを理解する
本節では,ELの機能とその使い方について解説し ます.

5.1 ELの役割とタグとの機能分担
ELが提供する主な機能を次に示します。
    ● Java オブジェクトの参照([] .)
    JavaオブジェクトをEL内で変数として扱うことが できます.また,Map,List,配列などのJavaオブジ ェクトの要素へのアクセス,JavaBeansのプロパティ にアクセスする手段も提供します.

    ● 算術演算(+ - * / %)
    整数,浮動小数点,BigDecimal,BigIntegerなど の四則演算,剰余演算などの一般的な算術演算が可 能です.

    ● 関係演算(== != < > <= >=)
    大小の比較など,一般な論理演算をひと通り提供 しています.関係演算子には,それぞれeq,ne,lt, t,le,geの別名が利用可能です.

    ● 論理演算(&& || !)
    上記の論理演算が提供されています.それぞれ, and,or,notの別名が利用可能です.
以上のように,ELが提供する機能は,Javaオブジ ェクトに対する演算処理です.ELには,変数に相当 するものはありますが,多くのスクリプト言語と同様 に型宣言がありません.また,代入,反復,if/switch などに相当する制御構造はタグの役割として,ELか らは排除されています.これらは,coreライブラリに よってタグとして提供されます.
  • 変数への代入
      変数textに文字列"Hello,World!" を代入しています.
      <c:set var="text" value="Hello,World!"/>

  • 反復
      ループ変数をiとして,0から10まで繰り返します.
      <c:forEach var="i" begin="0" end="10">
        ・・・
      </c:forEach>

  • 条件分岐
      x<y が成立する場合のみ,処理を実行します.
      <c:if test="${x<y}">
        ・・・
      </c:if>
5.2 リテラル
すでに,今までの例でいくつかのリテラルが出てき ました.ここでは,リテラルを整理しておきます.EL で扱うリテラルには,論理値,整数,小数点数,文 字列,Nullがあります.詳細な定義はここでは省略し ますが,いずれもJavaプログラマには馴染みのある表 記です.表5は,それぞれのリテラルの例です.
    表5 リテラルの表記例
     リテラル 例
     論理値 true false
     整数 1234
     小数点数 12.3 1.23e+12
     文字列 Hello,World!,xyz
     Null null
なお,整数に8進,16進表現はありません.また, 文字列中の' " \ のエスケープ処理には,Java言語同 様\を使用します.

5.3 変数
ELでの変数へのアクセスは,変数名を記述するだ けです.リスト1には,変数x, yが使用されていま す.ELには,変数の宣言命令が用意されていません. したがって,通常ELで使用する変数は,
    a. サーブレットの中で設定する
    b. JSP内でタグを使用して設定する
    c. 暗黙オブジェクトを使用する
ことになります. サーブレット内で,
    request.setAttribute("text", "Hello,World!");
のようにリクエストの属性として設定されたオブジェ クトは,そのサーブレットからforwardされたJSPフ ァイル内で,
    <c:out value="${text}"/>
のように,ELにおける変数として使用することがで きます.
また,JSTLには変数に値を代入する<c:set>タグが 用意されています.
    <c:set var="text" value="Hello,World!"/>
var属性が変数名,value属性がその変数に代入さ れる値です.<c:set>タグは,変数があればその値を上 書きし,変数がなければ新たに作成し,値を設定しま す.上記では,変数textに"Hello,World!" が設定さ れます.使用した変数を削除する必要がある場合に は,<c:remove>タグを使用します.
    <c:remove var="text"/>

5.3.1 変数のスコープ
ELの変数は,そのスコープによって4種類に分けら れます.
    ● ページスコープ変数
    変数が作成されたJSPページ内でのみ利用可能な変 数です.ページスコープ変数の実態は,PageContext オブジェクトに設定された属性です.PageContextオ ブジェクトの属性名がELにおける変数名,属性値が その変数の値となります.ページスコープ変数は,次 のように<c:set>タグを用いて生成することができま す.
      <c:set var="text" value="Hello,World!" scope= "page"/>
    scope属性の値pageが,この変数textがページスコ ープであることを示します.これは,次のJSPプログ ラムとほぼ等しい処理です.
      <% pageContext.setAttribute("text","Hello,World!"); %>
    このスコープの変数は,このJSPページでのみ有効 ですので,forwardしたページなどからアクセスする ことはできません.なお,<c:set>タグにより作成され る変数のデフォルトスコープは,pageとなっています ので,<c:set>タグのscope属性は,この場合省略する ことが可能です.

    ● リクエストスコープ変数
    1つのHTTPリクエストを処理している間有効な変 数です. リクエストスコープ変数の実態は, HttpServletRequestオブジェクトに設定された属性で す.ページスコープ変数同様,属性名が変数名,値 がその変数の値となります.以下のように,変数を作 成できます.
      <c:set var="text" value="Hello,World!" scope="request" />
    これは,次のJSPプログラムとほぼ等しい処理です.
      <% request.setAttribute("text","Hello,World!"); %>
    この変数は,importやforwardされたページ内から もアクセス可能ですが,次回のHTTPリクエスト処理 時には,有効ではありません.

    ● セッションスコープ変数
    セッションが有効な間,利用可能な変数です.セッ ションスコープ変数の実態は,HttpSessionオブジェ クトに設定された属性です.以下のように,変数を作 成できます.
      <c:set var="text" value="Hello,World!" scope="session"/>
    これは,次のJSPプログラムとほぼ等しい処理です.
      <% session.setAttribute("text","Hello,World!"); %>
    この変数は,セッションが有効な間利用可能ですの で,importやforwardされたページはもちろん,セッ ションが有効であれば,同じユーザからの次回のHTTP リクエスト時でも利用可能です.

    ●アプリケーションスコープ変数
    アプリケーションが有効な間,利用可能な変数で す. アプリケーションスコープ変数の実態は, ServletContextオブジェクトに設定された属性です. 以下のようにして,変数を作成できます.
      <c:set var="text" value="Hello,World!" scope="application"/>
    これは,次のJSPプログラムとほぼ等しい処理です.
      <% application.setAttribute("text","Hello,World!"); %>
    この変数は,アプリケーションが有効な間利用可能 です.逆に言えば,ここで設定した変数は,異なるユ ーザからのリクエストを含むすべてのリクエストの処 理に影響を与えますので,その点を考慮して使用する 必要があります.
変数同士の演算を行う場合,その変数がどのスコ ープに属しているかは考慮する必要がありません.た とえば,変数xがページスコープ,変数yがリクエス トスコープの場合でも,x+yは正しく加算されます.
ELが変数を参照する場合, PageContext.findAttribute("変数名") により値が参照されます. すなわち,PageContext,HttpServletRequest, HttpSession,ServletContextの順にそれぞれのオブ ジェクトに設定されている属性を探し,見つかった属 性を変数として演算が実行されます.次のように,単 純にJSPファイル内で宣言された変数は,PageContext 等の属性としては設定されませんので,ELからは変 数として利用することはできません.
    ソース
    <% String text = "Hello,World!"; %>
    <h1><c:out value="${text}"/></h1>
    出力結果
    <h1></h1>
PageContextオブジェクトなどの属性として設定さ れているものはアクセスが可能です.ただし,JSPフ ァイル内でのJavaプログラムは極力排除すべきである 点に注意してください.
    ソース
    <% pageContext.setAttribute("text","Hello,World!"); %>
    <h1><c:out value="${text}"/></h1>
    出力結果
    <h1>Hello,World!</h1>
もしELが使用された変数を発見できなければ,null が返ります.ただし,<c:out>タグは,出力にnullが指 定された場合には,nullではなく空文字を出力します.

5.3.2 プリミティブな型の変数
これまで見てきたように,EL における変数は, PageContextあるいはHttpServletRequestなど属性に 設定されたオブジェクトでした.したがってプリミテ ィブな型のデータはそのままでは属性に設定できませ ん.プリミティブな型のデータは,自動的にラッパー オブジェクトに変換されます.次の例では,プリミテ ィブな数値を設定した変数の型を確認しています. java.lang.Longでラップされていることがわかります.
    ソース
    <c:set var="x" value="${10}"/>
    <%= pageContext().getAttribute("x").getClass().getName() %>
    出力結果
    java.lang.Long


5.4 暗黙オブジェクト
JSPを使用する場合,requestやresponse,session など,システムが自動的に定義するため,ユーザが明 示的に定義しなくても使用可能な暗黙オブジェクトが 用意されていました.JSTLにおいても,同様にいく つかの暗黙オブジェクトが用意されています.表6に 暗黙オブジェクトの一覧を示します.
    表6 暗黙オブジェクト一覧
    暗黙オブジェクト概要
    pageContextPageContextオブジェクト
    pageScopeページスコープ変数を保持するMapオブジェクト
    requestScopeリクエストスコープ変数を保持するMapオブジェクト
    sessionScopeセッションスコープ変数を保持するMapオブジェクト
    applicationScopeアプリケーションスコープ変数のMapオブジェクト
    paramリクエストパラメータを保持するMapオブジェクト
    paramValuesリクエストのパラメータ名と値を1対多に対応させ保持するMapオブジェクト
    headerHTTPリクエストヘッダを保持するMapオブジェクト
    headerValuesHTTPリクエストヘッダの名前と値を1対多に対応させたMapオブジェクト
    initParam初期化パラメータを保持するMapオブジェクト
    cookieクッキー名とCookieオブジェクトを対応させたMapオブジェクト
これらは,JSPファイル内で宣言なしに使用するこ とができます.次は,暗黙オブジェクトheaderを使 用して,HTTPのリクエストヘッダに記述されたuseragent を表示する例です.
    <c:out value="${header['user-agent']}"/>
この結果,以下のように表示されます.
    Mozilla/5.0(X11;U;SunOS sun4u;……
ヘッダとパラメータは,同じ要素名に対して,複数 の値を持ちうるため,複数の値を取得できるように, それぞれ,headerValues,paramValuesが用意され ています.
リクエストや, 宣言済みの変数, クッキー, PageContext,初期化パラメータ等,Viewの実装に 必要な各種パラメータの多くが,暗黙オブジェクトと して利用可能です.そして,その多くの暗黙オブジェ クトの実態は,JavaのMapオブジェクトです.Map オブジェクトに設定されている要素は,ELから容易 にアクセスすることができます.詳細は後述します.

5.5 オブジェクト要素へのアクセス
ELでは,特定のJavaオブジェクトの内部データに アクセスするための汎用的な演算子として[] と. が用 意されています.Java言語では,[]は配列にアクセス するための演算子ですが,EL では少し異なります. ELでは,配列だけでなくMapオブジェクトなどの要 素にアクセスするための演算子として働きます.次に, []と. の働きをまとめます.
    ● Map オブジェクトの場合
    java.util.Mapインタフェースを実装したオブジェク トに[]演算子が使用された場合,Mapの要素に対す るアクセスとして処理されます.ELによるmap['key'] は,Javaではmap.get(" key")に相当します.暗黙オブ ジェクトのほとんどがMap オブジェクトですので, param['name']のようにその要素にアクセスできます. []の中に入るのは文字列式です.

    ● List オブジェクトの場合
    java.util.Listインタフェースを実装したオブジェク トに[] 演算子が使用された場合,Listの要素に対す るアクセスとして処理されます.すなわち,list[2]と いうELは,Java言語では,list.get(2)に相当します. ELでは,Javaと同じく0オリジンです.[]の中に入る ものは整数式です.

    ● 配列の場合
    配列のオブジェクトに対して[]演算子が使用された 場合,Javaと同様配列の要素に対するアクセスとして 処理されます.すなわち,EL におけるarray[2]は, Javaにおけるarray[2]と同様です.[]の中に入るもの は整数式です.

    ● JavaBeansの場合
    JavaBeansの場合, . 演算子はgetterメソッドとし て処理されます.ELによるbean.nameは,Javaでは bean.getName()に相当します.

なお,Mapオブジェクトに対して[]演算子の代わり に,. 演算子を用いることも許されています.map['key'] は,map.key と記述することも可能です.同様に JavaBeansに対して[]演算子を使用することも可能で す.bean['name']と記述しても,JavaBeansのプロパ ティにアクセスすることができます..演算子には, JavaBeansではない,通常のJavaオブジェクトのメソ ッドやメンバ変数にアクセスする機能はありません.
また[] や. をネストしたり複合的に用いることもも ちろん可能です.map['key'].nameのように記述する ことが可能です.Java言語との大きな違いとして,オ ブジェクトが存在しない場合でもNullPointerException やIndexOutOfBoundsExceptionが発生しないという 点があります.map[key]の場合,mapやkeyがnull だったり,配列において存在しない要素にアクセスし た場合でもExceptionが発生せずに,演算結果はnull となります.

5.6 自動型変換
ELおよびJSTLおいて,データの型は演算時に,必 要な型に自動変換されます.ここでは,ELおよびタ グライブラリがどのように型変換を実行するか見てい くことにします.

5.6.1 演算時の型変換処理
例えばA+1の場合で,Aが"12"のようなStringオブ ジェクトによる文字列の数値の場合,いくつかのスク リプト言語がそうであるように,ELにおいても12を 整数に変換した上で加算が実行されます.なおELの +には,文字列連結のための演算子としての機能はあ りません."abc"+"def"は,エラーとなります.
算術演算のオペランドにnullが指定された場合は, 0として扱われます.12+nullは,12+0として処理さ れます.EL ではこのようなString やnull 以外に, BigDecimalやBigInteger,小数点数も自動的に型変 換が行われて処理されます.オブジェクトがどのよう に型変換されるかについては次節で述べます.
A+Bの型変換を含む演算の手順は,次のようにな ります.
    1) A,B が両方null の場合
        0 を返す

    2) A,B のどちらかがBigDecimal の場合
        両方をBigDecimal に変換した上で,A.add(B)を返す

    3)A,B どちらかがFloat,Double または"1.25e+3"のようにe を含む文字列の場合
      3-1) A,B どちらかがBigInteger なら,A,B 両方をBigDecimal に変換し,A.add(B)を返す
      3-2) A,B 両方をDouble に変換し,A+B を返す

    4) A,B どちらかがBigInteger の場合
        A,B 両方をBigInteger に変換し,A.add(B)を返す

    5) 1)〜4)いずれでもない場合
        A,B をLong に変換し,A+B を返す
数値に変換できないオブジェクトに算術演算子が指 定された場合は,エラーが発生します.
算術演算だけでなく,論理演算についても同様に自 動的に型変換が行われます.== や != 演算子における 比較処理は,A,Bがオブジェクトの場合,Java言語 のようにポインタの比較ではなく,A.equals(B)とし て処理されます.A,Bがプリミティブな型の場合や, 文字列'123'のように数値として取り扱うことが可能な オブジェクトの場合,数値に変換された上で比較演算 が実行されます.したがって,128 == '128'は,'128'が 数値に変換して処理されるため,trueとなります.

5.6.2 型変換概要
オブジェクトの型変換がELにより実行される場合 の,主な型変換の方法を次に示します.
    1) 文字列への変換
    オブジェクトを文字列に変換する必要がある場合に は,Object.toString( )が実行されます.また,nullオ ブジェクトを文字列に変換する場合には,空文字に変 換されます.

    2) 数値への変換
    オブジェクトがShortやLongなど数値のWrapperオ ブジェクトの場合, s h o r t . s h o r t V a l u e ( ) や Long.longValue( )などで数値に変換されます.オブ ジェクトが"123"や,"12.3","1.0E+12"のように数値 を表す文字列の場合,それぞれ,その文字列を数値に 変換して処理されます.nullオブジェクトの場合,0 に変換されます.

    3) 論理値への変換
    変換するオブジェクトが,"true"や"false"の文字列 の場合には,それぞれに相当する論理値に変換されま す.nullや空文字は,falseに変換され処理されます.


5.6.3 タグ属性値の型変換処理
タグはそれぞれの属性によって,要求するデータの 型が異なります.変数に値を設定する<c:set>タグの 場合,valueの属性にはJavaのオブジェクトが要求さ れますが,<c:out>タグではvalue属性にStringを要求 します.属性値として設定される場合の型変換は次の 手順で行われます.
    1) 属性が単一のEL の場合
      <some:tag attr="${expression}"/>
    このような場合,expressionはオブジェクトとして 処理され,その後,属性attrが要求する型に変換され ます.<c:out>タグのvalue属性の場合には,文字列に 変換されます.
    次の例では,<c:set>によりxには,userオブジェク トが設定されますが,<c:out> のvalue 属性には user.toString( )の処理結果が設定されます.
      <c:set var="x" value="${user}"/>
      <c:out value="${user}"/>


    2) 属性値が複数のEL を含む場合
      <some:tag value="some${expression1}${expression2}"/>
    この場合は,ELを左側から順に評価し,結果を文 字列に変換します.さらにその文字列を属性が要求す る型に変換します.例えば,タグのbegin やend属性のように,数値を要求する属性の場合,文 字列が数値に変換され,処理されます.次の例の場 合,123までループが実行されます.
      <c:set var="x" value="${2}"/>
      <c:set var="y" value="${3}"/>
      <c:forEach begin="0" end="1${x}${y}"/>
      ・・・
      </c:forEach>
5.7 演算子
表7に演算子の優先順位を示します.
    表7 演算子の優先順位
    演算子(意味)
     [] .
     ()
     -(単項演算子)   not   !   empty
     *   /   div   %   mod
     +   -(二項演算子)
     <   >   <=   >=   lt   gt   le   ge
     ==   !=   eq   ne
     &&   and
     ||   or
    ※横に並んでいるものは同レベルであることを示す

なお,除算, 剰余演算などには,XPathとの互換性を考慮し,それ ぞれdiv,modの別名が用意されています.シフト, インクリメント,new,instanceofなどの演算子は用 意されていません.変数が存在するかどうかを調べる ための単項演算子としてemptyが用意されています. empty演算子は,指定されたオブジェクトが存在しな い場合だけでなくnullオブジェクトの場合も"true"を 返します.
  <c:if test="${empty user}"/>guest</c:if>




 << prev  ↑ JSTL index  next >>


このドキュメントに関するご意見、ご要望などはまで。


Copyright (C) 2003-2005 Visards, Inc. All Rights Reserved.