action-mapping

画面遷移設定のまとめ。

Struts2サンプルアプリ「mailreader」の定義ファイルより
<package name="subscription" namespace="/" extends="mailreader-support">
    <global-results>
        <result name="input">/Subscription.jsp</result>
        <result type="redirect-action">Registration_input</result>
    </global-results>

    <action name="Subscription_save" method="save" class="mailreader2.Subscription">
        <interceptor-ref name="user-submit" />
    </action>

    <action name="Subscription_*" method="{1}" class="mailreader2.Subscription" />
</package>

action定義

    <action name="Subscription_save" method="save" class="mailreader2.Subscription">
        <interceptor-ref name="user-submit" />
        < !--result type="redirect-action">Registration_input</result-->
    </action>

通常、アクションは上記のようにかける。
actionタグのmethod属性を省略した場合にはclass属性で指定したクラスのexecute()が実行される。
クラスにexecute()がない場合はActionSupportクラス*1のexecute()がデフォルト動作する。
メソッドはStringを返す(=遷移先の指定)。
これを受け取ってどこに遷移するかをタグで記述する。
(ここでは例として省略されているタグを追記してみた)
resultタグではname属性にメソッドの戻り値を記述する。
name属性を省略した場合にはデフォルトの「success」が指定される。
resultタグが記述されていない場合は、global-resultsタグが検索される。

global-results定義

    <global-results>
        <result name="input">/Subscription.jsp</result>
        <result type="redirect-action">Registration_input</result>
    </global-results>

パッケージ内すべてから参照される(共通の)遷移先を定義する。
先のアクションでresultタグが記述されていない場合には、このglobal-resultsタグ内が検索される。
よって、Subscription_saveアクションは正常終了すると、「Registration_input」アクションへリダイレクトされることになる。

wildcard定義

    <action name="Subscription_*" method="{1}" class="mailreader2.Subscription" />

ワイルドカード「*」を利用することによって、そこに指定された文字を「{1}」に当てはめることができる。
上記の定義は「Subscription_delete」とアクションが呼ばれた場合にmailreader2.Subscription#delete()が実行される。
ワイルドカードを利用する場合には、struts.xmlに次の設定を行う。(デフォルトではtrueとなっているため)

    <constant name="struts.enable.DynamicMethodInvocation" value="false" />

global-exception-mappint定義

アクションメソッドから通知された例外をキャッチして、定義された遷移先(result)にマップすることが可能。
ようは、「システムエラーが発生しました。管理者に連絡してください。」みたいなエラー画面に遷移する方法。

interceptorの定義

独自のパッケージ定義、インターセプタ定義(スタック含む)をしていない限りは不要。
Struts2が提供しているパッケージなど利用していない場合は以下のインターセプタの定義をする。

<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
global-exception-mappingsの定義

パッケージ固有のマッピングでもOK

    <global-exception-mappings>
        <exception-mapping exception="java.sql.SQLException" result="SQLException"/>
        <exception-mapping exception="java.lang.Exception" result="Exception"/>
    </global-exception-mappings>

exception属性に定義された例外クラス(サブクラス)をキャッチした場合にresult属性で指定したresultを返す。

まとめぽいなにか

基本なにごともパッケージ単位で記述(管理)するようになったStruts2…というかWebWork2
Struts1.xのときも定義ファイルの分割はできたけど、2.xはさらに細かく分割できるのでよくなったかも。
記述量というか分割しすぎのファイル数増加はどうかと思ったりもするけど。
interceptorによるcommandデザインパターンによる実装も(interceptorを知ってくると)なかなかよかと思ってみたり。


最後に、アクションマッピング定義とかに関して参考にさせていただいたサイトさん、ありがとうございます。
MyMemoWiki

*1:ActionSupportを継承している場合