目次へ

24. Struts 1.2.x

2006.08.15 株式会社四次元データ 鈴木 圭

Struts 1.2.x で新たに追加になったクラスや、変更された点のうち主なものについて解説します。

24.1. ワイルドカード・マッピング

ワイルドカード・マッピングとは、struts-config.xml におけるアクション・マッピングの指定にワイルドカードを使用できる機能です。以下に使用例を示します:

<struts-config>
  <action-mappings>
    <action path="/show*" type="com.example.webapp.Show{1}Action" >
      <forward name="success" path="/WEB-INF/jsp/{1}.jsp" />
    </action>
  </action-mappings>
</struts-config>

action 要素の path 属性における "/show*" という指定は、"/showSettings" や "/showMessages"、"showCalendar" など、先頭が "/show" で始まる全てのページにマッチします。そして、マッチした文字列をマッピング先のアクション・クラスや、フォワード先のパスの指定に含めることができます。

特殊トークン 説明
* スラッシュ ('/') を除くゼロ個以上の文字とマッチします。
** スラッシュ ('/') を含めるゼロ個以上の文字とマッチします。
\character バックスラッシュ文字 ('\') はエスケープシーケンスとして使用されます。"\*" という指定は単一のアスタリスク ('*')、"\\" という指定は単一のバックスラッシュ ('\') とマッチします。

"*" や "**" は 1 つのパスの中に複数指定することができ、"*" や "**" にマッチした値は、"{N}" (N には 1 から 9 の数値が入る) によって参照することができます。上の例において "/showData" というページにアクセスされた場合、"com.example.webapp.Show{1}Action" の "{1}" に "Data" が代入され、結果として com.example.webapp.ShowDataAction にマッピングされます (forward 要素の path 属性の値に含まれる "{1}" にも "Data" が代入されます)。また、リクエストされた URI を表す特別な参照として {0} を使用することができます。

ワイルドカードにマッチした値は、以下に挙げる属性において ("{N}" 形式で) 使用することができます:

  • attribute
  • catalog
  • command
  • forward
  • include
  • input
  • multipartClass
  • name
  • parameter
  • prefix
  • roles
  • suffix
  • type

また、ワイルドカードにマッチした文字列を使用できるアクション・フォワードの属性は以下の通りです:

  • catalog
  • command
  • path

Struts 1.2 よりも前のバージョンでは、一定のパターンに沿ったマッピングを行う場合でも一つずつ分けて記述しなければならず設定ファイルが大きくなりがちでした。しかし Struts 1.2 以降ではワイルドカード・マッピングを適切に使用することで設定ファイルの肥大化を抑えることができます。

24.2. MappingDispatchAction

org.apache.struts.actions.MappingDispatchAction は org.apache.struts.actions.DispatchAction を拡張して作成されたクラスです。MappingDispatchAction を使用すると、ディスパッチ先のメソッドごとに異なる ActionForm を指定するなど、DispatchAction よりも柔軟なマッピングを行うことができます。以下に DispatchAction と MappingDispatchAction の違いを示します:

  • DispatchAction は struts-config.xml に起動するメソッドを指定するパラメータ名を指定する。
  • MappingDispatchAction は struts-config.xml にディスパッチ先のメソッドを直接指定する。

MappingDispatchAction の使い方は DispatchAction と同じで、ディスパッチ先となるメソッドを Action#execute メソッドと同じシグネチャで作成します (execute メソッドはオーバーライドしません):

package example;

public class MyMappingDispatchAction extends MappingDispatchAction {
    public ActionForward hoge(ActionMapping mapping, ActionForm form,
                              HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        ...
    }

    public ActionForward piyo(ActionMapping mapping, ActionForm form,
                              HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        ...
    }
}

以下に struts-config.xml での設定例を示します:

<struts-config>
  ...
  <form-beans>
    <form-bean name="hogeForm" ...>
      ...
    </form-bean>
  </form-beans>
  ...
  <action-mappings>
    ...
    <!-- MyMappingDispatchAction#hoge() へのマッピング. -->
    <action path="/hoge"
            parameter="hoge"
            name="hogeForm"
            type="example.MyMappingDispatchAction">
      ...
    </action>

    <!-- MyMappingDispatchAction#piyo() へのマッピング. -->
    <action path="/piyo"
            parameter="piyo"
            type="example.MyMappingDispatchAction">
      ...
    </action>
    ...
  </action-mappings>
  ...
</struts-config>

この例では、/hoge というリクエストに対して MyMappingDispatchAction#hoge() メソッド、/piyo というリクエストに対して MyMappingDispatchAction#piyo() メソッドにディスパッチされるように指定していますが、/hoge というリクエストのときだけ ActionForm (hogeForm) の指定を行っています。

24.3. stopOnFirstError

JavaScript によるクライアントサイドの Validation において、最初の検証エラーが発生した時点で、検証処理を停止するかどうかを決めることができるようになりました。設定方法は、struts-config.xml の ValidatorPlugIn の設定において、stopOnFirstError という値で指定します:

<struts-config>
  ...
  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames" value="..." />
    <set-property property="stopOnFirstError" value="false" />
  </plug-in>
  ...
</struts-config>

stopOnFirstError の値に false を指定すると、検証エラーが発生しても検証処理が最後まで行われ、全ての検証エラーが報告されるようになります。

24.4. キャンセル・ハンドラ (DispatchAction#cancelled)

キャンセル・ハンドラを実装することで、フォームでの入力のキャンセルを実現することができます。キャンセル・ハンドラとは org.apache.struts.actions.DispatchAction#cancelled メソッドのことで、<html:cancel> で作成したボタンが押された時に呼び出されます。派生クラスは cancelled メソッドをオーバーライドし、フォーム入力がキャンセルされたときの処理を記述します。LookupDispatchAction や MappingDispatchAction などは DispatchAction を継承しているので、これらのクラスでもキャンセル・ハンドラを利用可能です。

cancelled メソッドの実装の仕方は Action#execute メソッドの場合と同じです:

public class MyDispatchAction extends DispatchAction
{
    @Override
    protected ActionForward cancelled(ActionMapping mapping,
                                      ActionForm form,
                                      HttpServletRequest request,
                                      HttpServletResponse response) throws Exception
    {
        ... キャンセルされたときの処理.
    }

    ...
}

24.5. validator の変更

requiredif ルールが非推奨となり、代わりに新しく追加された ValidWhen ルールを使用することになりました。条件付きの validation を行いたい場合に使用します。

24.5.1 ValidWhen ルール

ValidWhen ルールは他のフィールドの状態と関係した validation を行うために使用します。例えばチェックボックスがチェックされているときに限りテキストフィールドに値が入力されていることを検証する、ということが可能です。

何らかの登録フォームで「登録者が未成年の場合だけ保護者氏名の入力を必須としたい」という場合は ValidWhen ルールを用いて以下のように検証ルールを記述することができます (フォームの入力項目に name (登録者の氏名)、age (登録者の年齢)、guardianName (保護者氏名) があるとします):

<!-- validation.xml -->

<form-validation>
  <formset>
    ...
    <form name="...">
      <field property="name" depends="required">
        ...
      </field>
      <field property="age" depends="required, integer">
        ...
      </field>
      <field property="guardianName" depends="validwhen">
        <var>
          <var-name>test</var-name>
          <var-value>((age >= 20) or (*this* != null))</var-value>
        </var>
      </field>
    </form>
    ...
  </formset>
</form-validation>

ValidWhen の検証ルールは、上の例のように var 要素で指定します。var の入れ子となる var-name 要素の値には test を指定し、var-value 要素で検証ルールの式を記述します。検証ルールの式の評価結果が true となる場合に検証に成功します。

検証ルールには以下に示すトークンを使用することができます:

数値 10 進数以外に 8 進数および 16 進数でも指定することができます。
文字列 シングルクォート (') またはダブルクォート (") で囲みます。
*this* 検証しているフィールド自身を表します。
null リテラルの null または空文字列を表します。例えば (*this* != null) という条件式は required ルールと同じくフィールドに入力が行われている場合に検証に成功します。
他のフィールド 他のフィールドの値は、ActionForm で付けられたフィールド名で参照します。
インデックス付けされたフィールド インデックス付けされたフィールドの値は values[7] のように添え字を付けて参照します。添え字は values[] のように省略することもでき、省略した場合はテストされているフィールドと同じインデックスが使用されます。

validation.xml で指定する検証ルールの式 (var-value 要素の値) は以下の条件を満たしている必要があります:

  • 全ての比較式は括弧で囲まれている
  • and や or で結合される部分式は 2 つまで

1 つ目の条件は var-value 要素で指定する式が「<var-value>*this* != null</var-value>」ではなく「<var-value>(*this* != null)</var-value>」のようになっていなければならない、ということです。2 つ目の「and や or で結合される要素は 2 つまで」という制限は、上の例のように「((age >= 20) or (guardianName != null))」は指定可能ですが、「((age >= 20) and (age <= 80) or (guardianName != null))」は不可ということです。

また、比較式は比較される要素が数値に変換可能な場合には数値として比較、そうでない場合には文字列として比較が行われます。

インデックス付けされたフィールドの検証

インデックス付けされたフィールドの検証の例を示します。例えば以下のような製品を表すクラス Product と、selectProductForm という名前の Product の配列を持つ ActionForm (この例では DynaActionForm で作成) があるとします:

[ Product.java ]

public class Product
{
    /** 注文フラグ. 注文する場合に ture. */
    private boolean flag = false;

    /** 製品名. */
    private String name = "";

    /** 注文数. */
    private String quantity = "";

    ... コンストラクタ, アクセッサの定義.
}
[ struts-config.xml ]

<struts-config>
  ...
  <form-beans>
    ...
    <form-bean name="selectProductForm"
               type="org.apache.struts.validator.DynaValidatorForm">
      <form-property name="products"
                     type="com.example.webchat.db.bean.Product[]"
                     size="3" />
    </form-bean>
    ...
  </form-beans>
  ...
</struts-config>

JSP での表示は、以下のようなものだと考えてください:

購入 製品名 注文数
マウス
キーボード
スピーカー

このとき、購入欄のチェックボックスがチェックされた製品の注文数が入力されていることを検証したい場合は、以下のような検証ルールを指定します。

[ validation.xml ]

<form-validation>
  <formset>
    ...
    <form name="selectProductForm">
      <field property="quantity" indexedListProperty="products" depends="validwhen">
        <var>
          <var-name>test</var-name>
          <var-value>((products[].flag == "false") or (*this* != null))</var-value>
        </var>
      </field>
    </form>
    ...
  </formset>
</form-validation>

validation.xml では selectProductForm の products プロパティがインデックス付けされていることを示すために、field 要素の indexedListProperty で "products" を指定していることに注目してください。そして検証ルールの式「((products[].flag == "false") or (*this* != null))」は「quantity と同じインデックスの flag が "false"」または「quantity が null 以外」の場合に検証に成功する、という意味になります。

24.5.2 url ルール

url ルールを使用すると、well-formed な URL であることを検証することができます。以下に使用例を示します:

<form-validation>
  <formset>
    ...
    <form ...>
      <field property="website" depends="url">
        <var>
          <var-name>schemes</var-name>
          <var-value>http, ftp</var-value>
        </var>
      </field>
    </form>
    ...
  </formset>
</form-validation>

url ルールには、以下に挙げるパラメータを指定することができます:

allowallschemes true を指定した場合は全てのスキーム ("http://……" の "http" など) が許可されます。デフォルトである false を指定した場合は、schemes で指定したスキーム以外は検証に失敗します。
allow2slashes true を指定した場合はスラッシュ ('/') が 2 つ連続することを許可します。デフォルトは false です。例えば "http://www.example.com//index.html" という URL は、この項目に true を指定した場合は検証に成功しますが false を指定した場合は失敗します。
nofragments true を指定した場合は "http://www.example.com/index.html#title" のようなフラグメントの指定を含む URL を許可します。デフォルトでは false です。
schemes 許可するスキームをカンマ (',') 区切りで指定します。このパラメータを指定しなかった場合は、デフォルトである http, https, ftp が許可されます。

これらのパラメータによって、どのような URL を許可するかを細かく指定することができます。パラメータを指定しなかった場合は、それぞれのデフォルト値が使用されます。

24.5.3 その他 validation 関係の変更点

  • IntRange ルールが単一選択リストやラジオボタンなどの検証に使用できるようになりました。
  • Required ルールがチェックボックスやラジオボタン、単一/複数選択リストの検証に使用できるようになりました。

↑このページの先頭へ

こちらもチェック!

PR
  • XMLDB.jp