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

struts2-blank-2.0.6.warに入ってるLoginのサンプル。
http://localhost:8080/example01/example/Login_input.action
にアクセスすると、ユーザ、パスワード入力画面が表示され、適当に入力後、Submitボタン押下でメッセージ画面に遷移。Submit時には、特に、ユーザ、パスワードの妥当性チェックを行っているわけではなく、ただ単に必須チェックを行っているのみ。

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

WEB-INF/web.xml
WEB-INF/classes/struts.xml
WEB-INF/classes/example.xml
WEB-INF/classes/example.ExampleSupport.class
WEB-INF/classes/example.Login.class
WEB-INF/classes/example/Login-validation.xml
WEB-INF/classes/example/package.properties
WEB-INF/classes/example/package_es.properties
example/Login.jsp
example/Menu.jsp
example/Missing.jsp

[example.xml]

        <action name="Login_*" method="{1}" class="example.Login">
            <result name="input">/example/Login.jsp</result>
            <result type="redirect-action">Menu</result>
        </action>

        <action name="*" class="example.ExampleSupport">
            <result>/example/{1}.jsp</result>
        </action>

Loing_xxxのアクションの場合、example.Loginのxxxメソッドが呼ばれる。で、xxxメソッドの返り値(String)が"input"であった場合、/example/Login.jspが呼び出され、返り値が"success"であった場合、Menu.actionにリダイレクトされる。との意だと思う。。。

actionタグのmethod属性は、省略すれば、method="execute"となり、execute()メソッドが実行される。

ちなみに、今回の"success"の場合、example.xmlには、name="Menu"のactionタグの定義がされてないので、結果的にname="*"のアクションが適用され、/example/Menu.jspが呼び出されることになる。

面白いのがmethodの"{1}"で、"*"に入る文字列がそこに入るもよう。つまり、アクションがLogin_inputであれば、

<action name="Login_input" method="input" class="example.Login">

と同じことになるっぽい。

resultタグのname属性が実行される返り値の文字列で、"success"は省略可になってる。type属性の"redirect-action"は、指定されたアクション(今回の場合はMenu.action)が再実行される。
type属性には、同アクションの別メソッドを呼び出す"method"、別アクションのexecute()を呼び出す"action"、別URLにリダイレクトする"redirect"があるっぽい。検証はまた今度。。。redirect-actionとredirectの違いがわからん。。。


[example.Login.java]

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

リクエストの受け口で、継承関係はこんな感じ。

アクションがLogin_input.actionの場合、ActionSupport#input()メソッドが呼ばれる。アクションがLogin.actionの場合、Login#execute()メソッドが呼ばれる。
また、画面のチェック項目を記述した「アクション-validation.xml」といったファイル名のvalidationファイルを用意しておけば、勝手に入力項目チェックを行ってくれる。ただし、input()メソッドの場合はvalidationは実行されない。
Loginのアクションの場合、Login-validation.xmlに記述されたチェックが走り、チェックに引っかかった場合、

<result name="input">

タグで指定した/example/Login.jspが呼ばれる。

ちなみに特定のメソッドでvalidationを実行させたくない場合は、

@SkipValidation
public String hoge() throws Exception {
...
} 

みたいに、@SkipValidationアノテーションを使うべしみたいなことを書いてあったけど、他に方法はないんだろうか。。。


[example/Login.jsp]

struts2では、

<%@ taglib prefix="s" uri="/struts-tags" %>

を記述することで、s:〜で始まるいろんなタグライブラリと使うことができる。

<s:form action="Login">
    <s:textfield key="username" />
    <s:password key="password" />
    <s:submit/>
</s:form>
<s:textfield ...>タグが<input type="text" ...>に対応し、
<s:password ...>タグが<input type="password" ...>に対応し、
<s:submit ...>タグが<input type="submit" ...>に対応する。

<s:textfield ...>タグでは、
<s:textfield name="hoge" label="ほげ">>
と記述すれば、
<td><label for="xxx" class="label">ほげ:</label></td>
<td><input type="text" name="hoge" value="" id="xxx" /></td>
のようなHTMLが生成される。

key="hoge"のようにkey属性を使うと、生成されるHTMLでは、name属性が、name="hoge"となり、かつ、propertiesファイルから取得した内容をlabelタグの値として表示する。

画面上の入力値を取得するときは、ActionSupportの実装クラスにsetterを用意しておけばよし。Loginクラスの場合、usernameがsetUsernameでセットされ、passwordがsetPasswordでセットされる。

逆に画面にパラメータ値を渡すときは、

<s:textfield key="username" value="%{username}" />

のようにしておくと、getter(ここではgetUsername)で取得できる値が画面上にセットされる。


あー、思いつくままに書いただけだから、情報としてぐちゃぐちゃ。。。正しいかも分かんないし、余裕があれば整理したいけど、、、今余裕がない。。。