SHOEISHA iD

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

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

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

Struts 2入門(7)~データ連携の仕組み~

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

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

Modelオブジェクト(ModelDriven)

 ValueStackの構造にあるModelオブジェクトとは、Struts 2のModelDriven機能で用いるオブジェクトです。「Model」は、MVCモデル(Model-View-Controller)のM(odel)のことで、ひとまとまりのデータとそれを操作するオブジェクトを意味します。Struts 2のModelDrivenとは、そのようなModelオブジェクトを、Actionクラスとは別に管理するための機能です。

 これまでのサンプルコードでは、直接Actionクラスのフィールドにデータをならべて、それぞれのSetterやGetterを、Actionクラスのメソッドとして定義していました。そのため、Actionクラスの定義がふくれあがり、クラスとしての構造が分かりにくくなっていました。

 ModelDrivenを適用すれば、データをModelクラスとして分離して定義することができます。たとえ複数のActionクラスで同じデータにアクセスする場合でも、Actionクラスをシンプルに記述できるのです。

 前述したように、Modelオブジェクトは、Actionクラスとは別にValueStackに保持されています。つまり、JSPページからActionクラスを経由せずに、直接Modelオブジェクトを指定して参照できるということです。

 今回は、このModelDriven機能を使って、ActionクラスとViewレイヤーでデータを連携するアプリケーションを紹介します。

ModelDrivenのサンプル

 ModelDrivenの仕組みは、ModelDrivenインターセプターによって実現されています。

 ModelDrivenインターセプターは、デフォルトのインターセプターに含まれていて、パラメータの設定も不要です。

 では、ごくかんたんなModelDrivenのサンプルを作ってみましょう。次の画面のような、本の情報を登録するアプリケーションです。

メニュー画面
メニュー画面

 蔵書管理などのイメージで、入力-確認-登録実行というフローです。

登録
登録
登録確認
登録確認
画面遷移
画面遷移
ファイル構成

 全体のファイル構成は、次のようになります。順に見ていきましょう。ここでは、「BooksSample1」のリンクで動作するファイルだけを示しています。ダウンロードできるサンプルには、後述するサンプルも含まれていて、books.actionパッケージに、すべてのクラス、contentフォルダ以下に、すべてのJSPファイルとなっています。

 <ContextRoot>
 ├ /WEB-INF
 │ ├ /classes
 │ │ ├ /books.action
 │ │ │ ├ BooksModel.class
 │ │ │ └ BooksAction.class
 │ │ └ struts.xml
 │ ├ /content
 │ │ ├ booksRegister.jsp
 │ │ ├ booksResult1.jsp
 │ │ └ booksInput1.jsp
 │ ├ /lib
 │ │ └ 参照ライブラリー
 │ └ web.xml
 └ index.jsp

 web.xml、struts.xmlは、前回とまったく同じです。

ModelDrivenインターフェイスの実装

 Actionクラスで、ModelDrivenを利用するには、com.opensymphony.xwork2.ModelDrivenインターフェイスを実装する必要があります。インターフェイスといっても、次のようにgetModelというメソッドを実装するだけです。getModelでは、戻り値として、モデルとなるデータクラスのインスタンスを設定します。

[リスト1]ModelDriven.class
public interface ModelDriven
{
    public abstract Object getModel();
}

 Actionクラスでの実装は、次のようになります。型パラメータを用いて、BooksModelクラスを指定しています。また、フィールドの初期化時に、Modelオブジェクトをインスタンス化しています。

[リスト2]BooksAction.javaの一部
public class BooksAction extends ActionSupport
                 implements ModelDriven<BooksModel> {

    private BooksModel model = new BooksModel();

    @Override
    public BooksModel getModel() {
        return model;
    }

    ...中略...
}

 ModelオブジェクトとなるBooksModelクラスは、登録情報の文字列をフィールドにして、それぞれのgetter/setterを定義したものです。

[リスト3]BooksModel.javaの一部
public class BooksModel {

    private String isbn;   // ISBN
    private String title;  // 書名
    private String author; // 作者名

    // 以下フィールドのGetter/Setter

    ...中略...
}

 なお、ダウンロードファイルのサンプルコードには、前回と同じような日本語処理の暫定処理を追加しています。

booksInput1.jsp

 booksInput1.jspでは、登録用フォームを表示します。次のように、BooksModelクラスのフィールド名と同じにします。

[リスト4]booksInput1.jspの一部
<s:textfield name="title" label="書名" />
<s:textfield name="author" label="著者" />
<s:textfield name="isbn" label="ISBN" />

 submitボタンをクリックすると、booksアクションに遷移して、booksActionクラスのexecuteメソッドが実行されます。その際、booksActionクラスの変数modelには、入力した値がセットされています(なお、今回のサンプルでは、データ連携部分のみを説明する目的のため、バリデーション機能を利用していません)。

 booksActionのexecuteメソッドでは、次のようにアノテーションによって、Action名(books)と、JSPファイルの指定を行っています。booksResult1.jspでは、入力結果を表示します。

[リスト5]BooksModel.javaの一部
@Action(
    value = "/books",
    results = {
         @Result(name = "success", location = "booksResult1.jsp")
    }
)
public String execute() throws Exception {
    return "success";
}
booksResult1.jsp

 booksResult1.jspでは、変数modelの内容を表示します。表示のタグは、次のように、<s:property>タグを用います。前述したように、直接Modelオブジェクトが参照できますので、titleなどのBooksModelクラスのフィールド名をそのまま指定するだけです。

[リスト6]booksResult1.jspの一部
<s:property value="title" />
<s:property value="author" />
<s:property value="isbn" />

 このJSPファイルでは、さらに次のように、「register」という別のActionに遷移するリンクをつけています。

[リスト7]booksResult1.jspの一部
<a href="<s:url action="register"/>">登録実行</a>

 registerアクションで、データベースへの登録処理などを行うイメージです。このサンプルでは、次のように、booksActionクラスのregisterメソッドを実行するようにしています。ただここでは、登録処理はなく、単に"success"を返すようにしています(データベースへの登録は、あとのサンプルで説明します)。

[リスト8]BooksModel.javaの一部
@Action(
    value = "/register",
    results = {
        @Result(name = "success", location = "booksRegister.jsp")
    }
)
public String register() throws Exception {
    return "success";
}
booksRegister.jsp

 booksRegister.jspは、booksResult1.jspとほとんど同じで、Modelオブジェクトを表示しています。次のような画面になります。

登録実行
登録実行

 登録確認とほとんど同じなのに、じつはこちらの画面では値が表示できていません。というのも、Actionクラスは、URIのリクエスト単位でインスタンス化されるため、「登録実行」をクリックすると、新たにbooksActionクラスがインスタンス化されて、変数modelも初期化されてしまうからです。この遷移では、フォームでの受け渡しデータはありませんから、変数modelには何も値が設定されないのです。値を表示したり、データベースに登録したりするには、別の手段で値をセットする必要があります。

 このようなケースでデータを受け渡すには、いくつかの方法が考えられます。今回は、その中の一つ、セッションにModelを保持する方法を説明することにしましょう。

次のページ
セッション単位でModelを保持する方法

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

  • 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 Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

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

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

この記事をシェア

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

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング