Java Sticky Note
java
link
author
|
|
Standard TaglibsによるJSTLの利用
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フ
ァイル内で,
のように,ELにおける変数として使用することがで
きます.
また,JSTLには変数に値を代入する<c:set>タグが
用意されています.
<c:set var="text" value="Hello,World!"/>
var属性が変数名,value属性がその変数に代入さ
れる値です.<c:set>タグは,変数があればその値を上
書きし,変数がなければ新たに作成し,値を設定しま
す.上記では,変数textに"Hello,World!" が設定さ
れます.使用した変数を削除する必要がある場合に
は,<c:remove>タグを使用します.
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>
|
出力結果
PageContextオブジェクトなどの属性として設定さ
れているものはアクセスが可能です.ただし,JSPフ
ァイル内でのJavaプログラムは極力排除すべきである
点に注意してください.
ソース
<% pageContext.setAttribute("text","Hello,World!"); %>
<h1><c:out value="${text}"/></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() %>
|
出力結果
5.4 暗黙オブジェクト
JSPを使用する場合,requestやresponse,session
など,システムが自動的に定義するため,ユーザが明
示的に定義しなくても使用可能な暗黙オブジェクトが
用意されていました.JSTLにおいても,同様にいく
つかの暗黙オブジェクトが用意されています.表6に
暗黙オブジェクトの一覧を示します.
表6 暗黙オブジェクト一覧
暗黙オブジェクト | 概要 |
pageContext | PageContextオブジェクト |
pageScope | ページスコープ変数を保持するMapオブジェクト |
requestScope | リクエストスコープ変数を保持するMapオブジェクト |
sessionScope | セッションスコープ変数を保持するMapオブジェクト |
applicationScope | アプリケーションスコープ変数のMapオブジェクト |
param | リクエストパラメータを保持するMapオブジェクト |
paramValues | リクエストのパラメータ名と値を1対多に対応させ保持するMapオブジェクト |
header | HTTPリクエストヘッダを保持するMapオブジェクト |
headerValues | HTTPリクエストヘッダの名前と値を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>
このドキュメントに関するご意見、ご要望などはまで。
|
|