SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

続 Struts 2入門

Struts 2の同期処理を手助けするExecuteAndWaitインターセプタ

続 Struts 2入門(1)

適用されるアプリケーション

 まずはシンプルな具体例を挙げていきます。

 1つのテーブルのデータをCSVでダウンロードする機能をWebアプリケーションで実現したいのですが、そのデータ行数は、抽出条件によっては数千行~数万行になることがあります。このまま要望を実装してもどうしても長い待ち時間が発生してしまい、最悪ブラウザがタイムアウトをすることが考えられるため、なんらかの同期処理が欲しくなります。

 従来であれば、時間がかかる処理のみを切り出して、処理の開始~終了までを通知するスレッド管理の処理やメッセージの通知処理を使って、かつブラウザとの同期方法を実装しなければならないところですが、ここでExecuteAndWaitインターセプタを使うだけで簡単に実装することができます。

シンプルなActionクラスの例

 ここではさらにシンプルに次の処理をActionで実装し、仮想的に長時間の処理がかかるActionを用意します。

  • リクエストを受けると、15秒間待機し完了画面を出力する。
  • 待機画面は1秒ごとに更新する。

 これに対するActionクラスの実装は非常に単純で、リスト1のようになります。

リスト1 ExecAndWaitSampleAction.java
public class ExecAndWaitSampleAction {
    public String execute() throws Exception {
        Thread.sleep(15000);
        return "success";
    }
}

 次に、このActionに対して設定をしていきます。

Actionクラスに対する設定

 Actionに対する設定はstruts.xmlまたはActionクラスに対してアノテーションで定義することができます。

 Actionクラス終了時はsuccessを返すよう設定していますので、さらにインターセプタ用に1つの定義を追加します。

  • 処理中(wait) - Actionが処理中であった場合に返すレスポンス

 また、waitを省略した場合にはデフォルトのリフレッシュページが表示されます。

(1)struts.xmlの場合

リスト2 struts.xml
<struts>
    <package name="xnw" namespace="/xnw" extends="struts-default">
        <interceptors>
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="execAndWait">
                <param name="delay">500</param>
                <param name="delaySleepInterval">1000</param>
            </interceptor-ref>
        </interceptors>
        <action class="sample.action.ExecAndWaitSampleAction">
            <result name="wait">wait.jsp</result>
            <result name="success">success.jsp</result>
        </action>
    </package>
</struts>

(2)アノテーションを利用する場合

 先ほどのActionクラスに対して、リスト3のように@をつけてアノテーションを追加します。アノテーションを利用する場合は、先程のstruts.xmlは不要になります。

リスト3 ExecAndWaitSampleAction.java
package seren.lumi2.action;

import org.apache.log4j.Logger;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.InterceptorRefs;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;

import com.opensymphony.xwork2.ActionSupport;

/**
 * ExecuteAndWaitインターセプタ利用アクションクラス。
 *
 * @author koji.azuma(A-pZ)
 */

// アクションが属するパッケージ名。パッケージ名=パス。
@Namespace(value = "/xnw")

// 継承パッケージ。デフォルトのStruts 2の内容を継承。
@ParentPackage(value = "struts-default")

// インターセプタ定義
@InterceptorRefs( {
    // Struts 2デフォルト提供のインターセプタの組み合わせの後にExecuteAndWaitインターセプタを追加。
    @InterceptorRef("defaultStack"),
    @InterceptorRef(value = "execAndWait", params = { "delay", "500",
        "delaySleepInterval", "1000" }),
    // threadPriority    :スレッドの優先順位。
    // delay             :リクエストされてから初回レスポンスするまでの待ち時間。
    // delaySleepInterval:アクションが起動しているかをチェックする間隔。delay定義時のみ指定。
})
@Results({
    @Result(name = "wait",    location = "wait.jsp"),
    @Result(name = "success", location = "success.jsp"),
})
public class ExecAndWaitSampleAction extends ActionSupport {

    private static final long serialVersionUID = -8764919761726224220L;
    public static final Logger log = Logger
            .getLogger(ExecAndWaitSampleAction.class);

    /**
     * ExecuteAndWaitインターセプタを利用したサンプルアクション。
     * Conventionプラグインを利用すると、アノテーションで定義された名前がリクエスト情報になる。
     * Actionアノテーションで定義されたメソッドは、@Namespace/@Action.actionでリクエストされる。 このメソッドの場合、
     * /xnw/sample.actionとなる
     *
     * ExecuteAndwaitインターセプタで管理されるActionは、処理が終わるまで自動的にreturnの値がハンドリングされる。
     */
    @Override
    @Action("sample")
    public String execute() throws Exception {
        log.debug(" >> 処理開始 ...");
        Thread.sleep(15000); // 待機
        log.debug(" << 処理終了");
        return "success";
    }
}

 ExecuteAndWaitインターセプタにて定義できるパラメータは次の3つです。いずれも省略可能です。

ExecuteAndWaitインターセプタの設定項目
属性名 デフォルト値 概要
threadPriority Thread.NORM_PRIORITY 使われるスレッドの優先順位。
delay 0(ミリ秒) リクエストされてから初回レスポンスするまでの待ち時間。実際にはActionは即時に起動しています。レスポンスするのに必要な情報を出す準備に時間がかかる場合は設定するといいでしょう。
delaySleepInterval 100(ミリ秒) アクションが既に起動しているかをチェックする間隔。delay定義時のみ指定します。

 これでActionクラスの準備は完了です。

次のページ
リフレッシュ機能をつけたJSP

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

続 Struts 2入門連載記事一覧

もっと読む

この記事の著者

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、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本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

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

WINGSプロジェクト 東 浩二(アズマ コウジ)

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

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4912 2010/03/16 14:00

イベント

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

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

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

メールバックナンバー