カスタマイズ方法
ここまで説明してきたルールは、すべてデフォルトの仕様です。Zero Configurationとはいえ、ある程度は既定値を変更するカスタマイズが可能です。カスタマイズには、アノテーションを用いた指定と、XMLの設定ファイルで既定値を上書きする方法があります。
Actionアノテーション
Actionアノテーションは、Action
メソッドと、それを呼び出すURIのマッピングを指定するものです。Actionアノテーションを用いると、一つのメソッドに複数のURIを設定できたり、execute
メソッド以外のメソッドを、Action
メソッドとして設定することができます。
例えば次のようにすると、ZeroAnn
クラスのAction
メソッドは、「/ann/zero-ann.action」というURIにマッピングされます。デフォルトの「/zero-ann.action」ではアクセスすることができません。
package zero.action; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; public class ZeroAnn1 extends ActionSupport { ...中略... @Action("/ann/zero1") public String execute() throws Exception { setReplyMsg("ann/zero1"); return "success"; } }
この場合URIが「/ann/zero1.action」ですので、対応するResult処理のViewテンプレートファイルは、「/WEB-INF/content/ann/zero1.jsp」ということになります。
一つのメソッドに、複数のURIをマッピングすることもできます。例えば、次のようにすると、「/ann/zero2.action」でも、「/ann/zero3.action」でも、同じメソッド(execute2)が呼び出されます。
import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; public class ZeroAnn1 extends ActionSupport { ...中略... @Actions({ @Action("/ann/zero2"), @Action("/ann/zero3") }) public String execute2() throws Exception { setReplyMsg("ann/zero2,ann/zero3"); return "success"; } }
Actionアノテーションのもう一つの用途は、一つのAction
クラスに、複数のAction
メソッドを定義することです。次の例では、ふたつのAction
メソッドを定義しています。
public class ZeroAnn1 extends ActionSupport { ...中略... @Action("/ann/zero1") public String execute() throws Exception { setReplyMsg("ann/zero1"); return "success"; } @Actions( { @Action("/ann/zero2"), @Action("/ann/zero3") }) public String execute2() throws Exception { setReplyMsg("ann/zero2,ann/zero3"); return "success"; } }
InterceptorRefアノテーション
InterceptorRefアノテーションを指定することで、インターセプターの設定をすることができます。このアノテーションは、クラス定義の前に記述し、クラスレベルで指定します。クラスレベルで指定すると、クラスで定義されたすべてのAction
メソッドに、このアノテーションが適用されます(ドキュメントでは、メソッド単位で指定可能なようですが、確認できませんでした)。
例えば次のように、「timer」インターセプターと、「defaultStack」を指定すると、ログにメソッドの実行時間が出力されます(Eclipseのコンソールでも確認できます)。
import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.InterceptorRef; import org.apache.struts2.convention.annotation.InterceptorRefs; ...中略... @InterceptorRefs( { @InterceptorRef("timer"), @InterceptorRef("defaultStack") }) public class ZeroAnn extends ActionSupport { ...中略... @Action("/ann/zero") public String execute() throws Exception { return "success"; } }
ログの出力は、次のようになります。
情報: Executed action [/ann/zero!execute] took 197 ms.
なお、「defaultStack」とは、連載第4回で説明したように、多くのアプリケーションで必要となる機能を、デフォルトのインターセプターとして定義したものです。
Resultアノテーション
Resultアノテーションは、Result処理をカスタマイズする際に使用します。このアノテーションでは、クラスレベルでの指定と、Action
メソッド単位での指定が可能です。
例えば次のように指定すれば、このAction
クラスのすべてのAction
メソッドで、"failure"というResultコードのときには、fail.jspを用いるようになります。現在時刻の秒数が偶数なら、"failure"を返すようにしていますので、そのときだけ「fail.jsp」が表示に用いられます。
import java.text.SimpleDateFormat; import java.util.Calendar; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; @Results({ @Result(name="failure", location="fail.jsp") }) public class ZeroAnn2 extends ActionSupport { ...中略... public String execute() throws Exception { Calendar cal = Calendar.getInstance(); SimpleDateFormat d = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); this.replyMsg = d.format(cal.getTime()); // 現在時刻の秒が偶数なら、failureを返す。 if ((cal.get(Calendar.SECOND) % 2) == 0) { return "failure"; } return "success"; } }
Action
メソッド単位に指定するには、次のようになります。type
属性を使って、Result処理の種別を指定することもできます。
public String execute() throws Exception { ...中略... @Action(value = "/ann/zero5", results = { @Result(name = "success", location = "http://codezine.jp/", type = "redirect") }) public String execute2() { return "success"; }
ResultPathアノテーション
ResultPathアノテーションは、Result処理で指定するViewテンプレートファイルの場所を指定するアノテーションです。この場所は、デフォルトでは「WEB-INF/content」になっています。
また、ResultPathアノテーションは、メソッドレベルでは指定できません。クラスレベルで指定するか、または、パッケージに対するコメントやアノテーションを記述するpackage-info.javaに記述する必要があります。
例えば次のようにすると、このAction
クラスでは、「WEB-INF/jsp」からViewテンプレートファイルがサーチされることになります。
import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.ResultPath; @ResultPath("/WEB-INF/jsp") public class ZeroAnn3 extends ActionSupport { ...中略... @Action("/ann/zero6") public String execute() { return "success"; } }
パッケージ内に、次のような「package-info.java」があると、今度は、パッケージに含まれるAction
クラスすべてに指定したことになります。「package-info.java」は、JDK1.5以降の機能で、パッケージの宣言と、アノテーション、コメントだけのファイルです。
@org.apache.struts2.convention.annotation.ResultPath("/WEB-INF/jsp") package zero.action.ResultPath;
その他のアノテーション
上記以外には、パッケージ単位で任意のURIの起点を指定するNamespaceアノテーションや、例外がスローされたときの遷移先を指定する、ExceptionMappingアノテーションなどがあります。
詳しくは、「Convention Plugin」のドキュメントを参照してください。