Struts2に触れよう! その1(HelloWorldサンプル編)

Strutsに関しては、数年前にStrutsのコードを少し追っかけた程度ですっかり忘れてます。まったくもって知識真っ白な状態なので、StrutsからStruts2になってどう変わったとかはまったく分かりません!ってな状態ですが、とりあえず触ってみることに。

まずは、動かしてみようということで、とりあえずstruts-2.0.6-all.zipをダウンロード。

まずはサンプルから。やっぱり最初はHellowWorldでしょう。
eclipse上でTomcatプロジェクトをプロジェクト名example01で新規作成し、struts-2.0.6/apps/struts2-blank-2.0.6.warを解凍して、まるっとインポート。ビルドパスの構成で、/WEB-INF/lib/配下のjarをライブラリに追加し、ソースフォルダを/WEB-INF/src/javaに変更。

Tomcatを起動し、
http://localhost:8080/example01/example/HelloWorld.action
にアクセスすると、Struts is up and running ...と書かれた画面が表示。

とりあえず、動いたのでコードを見てみますか。

今回使われてるのは以下のもの。

WEB-INF/web.xml
WEB-INF/classes/struts.xml
WEB-INF/classes/example.xml
WEB-INF/classes/example.ExampleSupport.class
WEB-INF/classes/example.HelloWorld.class
WEB-INF/classes/example/package.properties
WEB-INF/classes/example/package_es.properties
example/HelloWorld.jsp

[web.xml]

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>

org.apache.struts2.dispatcher.FilterDispatcherがリクエストの受け口なのね。ServletじゃなくてFilterになってるもよう。


[struts.xml]
[example.xml]

で、アクションをstruts.xmlに定義。今回はstruts.xmlにインクルードされたexample.xmlが実際の定義情報。

        <action name="HelloWorld" class="example.HelloWorld">
            <result>/example/HelloWorld.jsp</result>
        </action>

"HelloWorld"のアクションの場合、example.HelloWorldのクラスがインスタンス化されて、execute()メソッドが実行された結果、/example/HelloWorld.jspが呼び出されるってな事。


[example.HelloWorld.java]

com.opensymphony.xwork2.ActionSupport
△
|
example.ExampleSupport
△
|
example.HelloWorld

継承関係はこんな感じ。

アクションがサブミットされるとActionSupport#execute()が呼ばれます。HelloWorld#execute()でオーバーライドしてるので、実際に呼ばれるのはこいつ。

    public String execute() throws Exception {
        setMessage(getText(MESSAGE));
        return SUCCESS;
    }

getText()でメッセージを取得し終了。


[example/HelloWorld.jsp]

HelloWorld.javaで取得したメッセージを

<h2><s:property value="message"/></h2>

で表示して終了。


流れ的には以上なんですが、ActionSupport#getText()の動きがいまいち不明。
package.propertiesからメッセージを取得しているようだけど、どこにも"package"なんか定義していないし、"request_locale"リクエストパラメータでロケールの切り替えも行っているようだし。

まずは、ロケールの切り替えをどこで行ってるかを追いかけることに。getText()を遡っていくと、

com.opensymphony.xwork2.interceptor.I18nInterceptor

    public static final String DEFAULT_PARAMETER = "request_locale";

    protected String parameterName = DEFAULT_PARAMETER;

で定義されてるから、"request_locale"って文字列がロケール指定用の予約語になってるっぽい。protected指定だから変更できそう。必要性はないだろうけど。


続いて、package.propertiesをどう指定してるのかを追いかけることに。

com.opensymphony.xwork2.util.LocalizedTextUtil#findText()

                String packageName = basePackageName + ".package";

どうやらこいつも予約語っぽい。ソースをざっと見た感じ、{パッケージ}/{クラス名}.propertiesがなければ、{パッケージ}/package.propertiesを見に行くっぽい。
ためしに、HelloWorld.propertiesを用意したらこっちを優先に読みにいきました。

あとは、java.util.ResourceBundleでpropertiesファイルを読みにいってるようなので、ロケールによって、package.propertiesとpackage_es.propertiesを切り替えているもよう。