SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

作りながら学ぶJavaアプリケーションフレームワーク

Struts 2入門(6)~XML不要のZero Configuration~

作りながら学ぶJavaアプリケーションフレームワーク (6)

  • X ポスト
  • このエントリーをはてなブックマークに追加

カスタマイズ方法

 ここまで説明してきたルールは、すべてデフォルトの仕様です。Zero Configurationとはいえ、ある程度は既定値を変更するカスタマイズが可能です。カスタマイズには、アノテーションを用いた指定と、XMLの設定ファイルで既定値を上書きする方法があります。

Actionアノテーション

 Actionアノテーションは、Actionメソッドと、それを呼び出すURIのマッピングを指定するものです。Actionアノテーションを用いると、一つのメソッドに複数のURIを設定できたり、executeメソッド以外のメソッドを、Actionメソッドとして設定することができます。

 例えば次のようにすると、ZeroAnnクラスのActionメソッドは、「/ann/zero-ann.action」というURIにマッピングされます。デフォルトの「/zero-ann.action」ではアクセスすることができません。

[リスト4]ZeroAnn1.javaの一部
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)が呼び出されます。

[リスト5]ZeroAnn1.javaの一部
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メソッドを定義しています。

[リスト6]ZeroAnn1.javaの一部
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のコンソールでも確認できます)。

[リスト7]ZeroAnn.javaの一部
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」が表示に用いられます。

[リスト8]ZeroAnn2.javaの一部
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処理の種別を指定することもできます。

[リスト9]ZeroAnn2.javaの一部
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テンプレートファイルがサーチされることになります。

[リスト10]ZeroAnn3.javaの一部
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以降の機能で、パッケージの宣言と、アノテーション、コメントだけのファイルです。

[リスト11]package-info.java
@org.apache.struts2.convention.annotation.ResultPath("/WEB-INF/jsp")
package zero.action.ResultPath;

その他のアノテーション

 上記以外には、パッケージ単位で任意のURIの起点を指定するNamespaceアノテーションや、例外がスローされたときの遷移先を指定する、ExceptionMappingアノテーションなどがあります。

 詳しくは、「Convention Plugin」のドキュメントを参照してください。

次のページ
まとめ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
作りながら学ぶJavaアプリケーションフレームワーク連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 高江 賢(タカエ ケン)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3837 2009/05/12 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング