OGNLガイド
目次
OGNL (Object Graph Navigation Language) は,Javaオブジェクトのプロパティにアクセスしたりメソッドを呼び出したりすることの出来る,Javaによく似た式言語です.
Seasar2では,diconファイルの<property>要素の他,<component>要素・<initMethod>要素・<destroyMethod>要素・<arg>要素・<meta>要素にOGNL式を記述することが出来ます.
OGNLの詳細はこちらを参照してください.
Java標準のリテラル
OGNLでは,Java言語で定められているリテラルをそのまま記述することが出来ます.
例 |
型 |
true |
boolean |
false |
10 |
int |
0xABCD |
100L |
long |
1.0 |
float |
0.5F |
0.01D |
double |
'A' |
char |
'\uFFFF' |
"seasar2" |
java.lang.String |
null |
参照型 |
文字列を記述する際には,ダブルクォーテーションが必要なことに注意してください.
<component class="Person">
<property name="name">"Taro Yamada"</property>
<property name="age">25</property>
</component>
OGNL独自のリテラル
OGNL独自のリテラルも用意されています.
java.math.BigDecimal およびjava.math.BigInteger を表すリテラルがあります.
例 |
型 |
100.00B |
java.math.BigDecimal |
100000H |
java.math.BigInteger |
diconファイルに記述されたOGNL式は,S2コンテナが用意したコンテキストで実行されます.
この実行コンテキストには,次のオブジェクトがあらかじめ定義されています.
名前 |
型 |
説明 |
container |
org.seasar.framework.container.S2Container |
現在のdiconファイルを処理しているS2コンテナです. |
request |
javax.servlet.http.HttpServletRequest |
Webコンテナ上で実行されている場合,現在のスレッドで処理しているリクエストです.
設定されていない場合もあります. |
response |
javax.servlet.http.HttpServletResponse |
Webコンテナ上で実行されている場合,現在のスレッドで処理しているレスポンスです.
設定されていない場合もあります. |
session |
javax.servlet.http.session.HttpSession |
Webコンテナ上で実行されている場合,現在のスレッドで処理しているセッションです.
設定されていない場合もあります. |
servletContext |
javax.servlet.ServletContext |
Webコンテナ上で実行されている場合,現在のS2コンテナに関連づけられたサーブレットコンテキストです.
設定されていない場合もあります. |
さらに,コンテナに登録されているコンポーネントをその名前 (name 属性の値) で参照することが出来ます.
OGNLは変数を使うことが出来ます.全ての変数はグローバルで,先頭に'# 'を付けます.
変数の設定はJava言語と同様,= 演算子を使って値を代入しますが,diconファイルの中で変数を設定することはあまりないでしょう.
定義済みの変数
変数 |
説明 |
#this |
この変数を含んだ式の「現在のオブジェクト」を表します. |
#self |
<initMethod> または<destroyMethod> のボディの中でのみ定義されている変数です.
この変数は,現在のコンポーネント (<initMethod> または<destroyMethod> を囲む<component> 要素で表されているオブジェクト) を参照します. |
オブジェクトを生成するには,Java言語の場合と同様にnew 演算子を使用します.クラス名はパッケージ名で修飾した完全限定名で指定する必要があります
(java.lang パッケージの場合は省略することが出来ます).
<property name="url">new java.net.URL("http://localhost/")</property>
配列を生成することも出来ます.
<property name="array1">new int[5]</property><!-- 配列の要素はすべて0 -->
<property name="array2">new int[] {1, 3, 5}</property>
java.uti.ArrayList のインスタンスを手軽に生成することも出来ます.ただし,具体的な実装型 (java.util.LinkedList など) は指定することが出来ません.
<property name="list">{"green", "red", "blue"}</property>
java.util.Map のインスタンスを手軽に生成することも出来ます.
<property name="map">#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}</property>
java.util.Map の実装型を指定することも出来ます (省略時はjava.util.LinkedHashMap になります).
<property name="map">#@java.util.TreeMap@{"key1" : "value1", "key2" : "value2"}</property>
オブジェクトのpublic なフィールドへアクセスすることが出来ます.
インスタンスフィールド
インスタンスフィールドは,Java言語と同じようにアクセスすることが出来ます.
<property name="x">point.x</property>
static フィールド
static フィールドにアクセスするには,クラス名の前後を'@'で囲んで,その後にフィールド名を記述します.クラス名はパッケージ名で修飾した完全限定名を指定する必要があります
(java.lang パッケージの場合は省略することが出来ます).
<property name="priority">@Thread@NORM_PRIORITY</property>
オブジェクトのpublic なメソッドを呼び出すことが出来ます.
インスタンスメソッド
インスタンスメソッドは,Java言語と同じように呼び出すことが出来ます.
<property name="files">dir.listFiles()</property>
static メソッド
static メソッドを呼び出すには,クラス名の前後を'@'で囲んで,その後にメソッド名を記述します.クラス名はパッケージ名で修飾した完全限定名を指定する必要があります
(java.lang パッケージの場合は省略することが出来ます).
<property name="roots">@java.io.File@listRoots()</property>
OGNLを使用する上で中心となるのがプロパティへのアクセスです.
JavaBeansのプロパティ
OGNLでは,JavaBeansにおけるプロパティ (getter/setterメソッドでアクセスできるもの)を扱うことが出来ます.
次の例では,hello という名前の付けられたコンポーネントのmessage というプロパティ値をコンポーネントとして定義しています.message プロパティの値は,examples.dicon.HelloSetterInjection クラスのgetMessage() メソッドが返す値です.
<component name="hello" class="examples.dicon.HelloSetterInjection">
<property name="message">"Hello World!"</property>
</component>
<component name="msg">
hello.message
</component>
Mapのエントリ
java.util.Map のエントリもプロパティとして扱うことが出来ます.この場合,キーがプロパティ名となります.ただし,プロパティ名として使うことが出来るのは,識別子として有効なjava.lang.String 型のキーだけです.
次の例では,コンポーネントone はコンポーネントmap のキーone に関連づけられている値1B (java.math.BigDecimal の1) になります.
<component name="map">
#{"one" : 1B, "two" : 2B, "three" : 3B}
</component>
<component name="one">
map.one
</component>
コンポーネント
コンテナに登録されているコンポーネントをプロパティとして扱うことが出来ます.この場合,コンポーネントの名前
(name 属性の値) がプロパティ名となります.
<component name="foo" class="Foo"/>
<component name="">
<property name="foo">container.foo</property>
</component>
Javaの配列
Javaの配列はJavaと同じようにアクセスすることが出来ます.
次の例では,java.io.File#listRoots() メソッドが返す配列の最初の要素がプロパティに設定されます.
<property name="root">@java.io.File@listRoots()[0]</property>
JavaBeansのインデックス付きプロパティ
JavaBeansのインデックス付きプロパティを配列のように扱うことが出来ます.
次の例では,org.seasar.framework.container.S2Container#getChild(int) が呼び出されます.
<property name="firstChild">container.child[0]</property>
連想配列
プロパティやフィールドを連想配列のようにアクセスすることが出来ます.
次の例では,org.seasar.framework.container.S2Container#getNamespace() が呼び出されます.
<property name="tm">container["namepace"]</property>
連想配列によるインデックス付きプロパティ
JavaBeansのインデックス付きプロパティの拡張として,任意の型をインデックスとするプロパティにアクセスすることが出来ます.
次の例では,org.seasar.framework.container.S2Container#getComponentDef(String) が呼び出されます.
<property name="tm">container.componentDef["j2ee.transactionManager"]</property>
in 演算子
in 演算子を使うことで,配列またはコレクション (java.util.Collection のインスタンス) に要素が含まれているかをテストすることが出来ます.
次の例では,color というコンポーネントが"red" ,"green" ,"blue" の中に含まれているかをテストしています.color の値は"red" であるため,コンポーネントcontains はture になります (実際にはboolean のラッパー型であるBoolean 型になります).
<component name="color">"red"</component>
<component name="contains">color in {"red", "green", "blue"}</component>
セレクション
配列またはコレクションから,条件にマッチする要素だけを選択することが出来ます.
次の例では,リストcolors から,3文字より長い要素だけを選択したリスト (要素は "green" と"blue" ) がコンポーネントselected になります.
#this は配列またはコレクションの各要素への参照です.
<component name="colors">{"red", "green", "blue"}</component>
<component name="selected">colors.{? #this.length() > 3}</component>
条件にマッチする最初の要素だけを選択することも出来ます.
次の例では,コンポーネントfirstMatch は"green" になります.
<component name="colors">{"red", "green", "blue"}</component>
<component name="firstMatch">colors.{^ #this.length() > 3}</component>
条件にマッチする最後の要素だけを選択することも出来ます.
次の例では,コンポーネントlastMatch は"blue" を唯一の要素とするリストになります.
<component name="colors">{"red", "green", "blue"}</component>
<component name="lastMatch">colors.{$ #this.length() > 3}</component>
プロジェクション
配列またはコレクションの各要素に対して,そのプロパティまたはメソッドを適用した戻り値からなるコレクションを作ることも出来ます.
次の例では,様々な型の数値からなるリストnumbers から,その文字列表現を要素とするリストstrings を作成しています.
<component name="numbers">{0, 1L, 2.5f, 3B}</component>
<component name="strings">numbers.{#this.toString()}</component>
カンマ演算子を使うと,複数の副式を続けて記述することが出来ます.最後の副式の値が式全体の結果となります.
次の例では,標準出力へのプリントと,foo というオブジェクトの参照という二つの副式が記述されています.式全体の結果は最後の副式であるfoo になります.
<property name="foo">@System@out.println("Foo:" + foo), foo</property>
同一オブジェクトに対するメソッドを繰り返し呼び出す場合などに便利な記述方法が用意されています.
次の例では,<initMethod> 要素の中で#self (HashSet のインスタンス) に対するadd() メソッドの呼び出しを3回繰り返しています.add() メソッドは,それを囲んでいるカッコで区切られたコンテキストで評価されます.このコンテキストは#self (HashSet )であるため,どのadd() メソッドの呼び出しもHashSet に対して行われます.
<component name="set" class="java.util.HashSet">
<initMethod>#self.( add("one"), add("two"), add("three") )</initMethod>
</component>
|