金子邦彦研究室プログラミングTomcat を用いた Java サーブレット・プログラミングEclipse で Struts フレームワーク・プログラム開発

Eclipse で Struts フレームワーク・プログラム開発

Struts とは,Web アプリケーション開発のフレームワークです. Apache Jakarta プロジェクトの成果物です.

このページでは,Eclipse の機能を使いながら,Struts フレームワークに準拠した Java サーブレット・プログラムを開発(設計と実装)する手順を説明する. さらに,Eclipse で, 出来たJava サーブレット・プログラムを,Tomcat 上で動作させます. 以上のことを,プロラムの見本と,操作手順の図解で説明する.

※ Tomcat と Java サーブレット・プログラムの全般については,別の Web ページを見てください.

【この Web ページの目次】

【補足説明】

下記の 2つのサーバは別物です. 2つを同時に動かすことはできません(ポートを奪い合うことができないので).一方を動かすときは,もう一方を止めることになる.

  1. Eclipse 内部の tomcat サーバ:

    Eclipse では,Eclipse 内部の Tomcat サーバが動き, Java サーブレットの動作テストなどに使う.

  2. 公開 tomcat サーバ:

    Eclipse とは無関係の Tomcat サーバ(C:\tomcat55\bin\tomcat5w.exe で起動する Tomcat サーバのこと).当然, 公開 tomcat サーバが管理するディレクトリも Eclipse とは無関係.

※ なお,「Eclipse 内部の tomcat サーバ」を使えるようするには, Eclipse で「新規サーバの定義」という操作を行う必要がある.これは,1回行うだけで十分です.

Struts について

[image]

次のものが出てきます. 練習の目的は,それぞれの役割と,互いの関係を理解することです.

  1. Web ブラウザにページとして表示される JSP プログラム

    Web ブラウザに表示されるページのデザインと中身(フォーム,動的データなど)が定義される.

    JSP プログラムは,Struts タグライブラリを使って,アクションフォーム・ビーンなどの属性値を取り出す.

  2. クライアントから入力されたフォームデータを格納するStruts アクションフォーム・ビーン・クラス

    Struts アクションフォーム・ビーン・クラスは, 入力フォームとマッピングされ, 入力フォームに記入されたクライアントからのフォームデータの格納と検証を行う. さらに,フォームデータを検証し,エラーがあれば ActionErrors オブジェクトを生成する validate メソッドを持つ.

    Struts アクションフォーム・ビーンの有効期限(スコープ)は, セッションの期間,つまり,個々の HTTP リクエストよりも長く設定でき, この場合, 個々の HTTP リクエストの期間を超えて共有される.

    Struts アクションフォーム・ビーン・クラスには, 入力フォームの項目に対応する属性等が定義される. アクションフォーム・ビーン・クラスの属性名は,入力フォームに登場する属性名と一致させるのが普通である. さらに,属性のゲッター(属性ゲッターメソッドのこと,getXxx の形)とセッター(属性セッターメソッドのこと.setXxx の形)を持つ.ゲッターとセッターは,JSP プログラム,Struts アクションクラス,ビジネスロジックから使用される. さらに,Struts アクションフォーム・ビーンを初期化するためにreset メソッドを持つ.

    Struts アクションフォーム・ビーン・クラスは, Web アプリケーションの,個々の入力フォームに対応して定義されるクラスである. 但し,入力フォームが複数のページにまたがる場合に,Struts アクションフォーム・ビーンがページ数よりも少ないことがありえる. Struts の org.apache.struts.action.ActionForm クラスのサブクラスとして定義される.

  3. システム内部状態が定義されたクラス

    システムの内部状態は,Java ビーンあるいはJava ビーンの集合により表される. システム内部状態が定義されたクラスは,システムの内部状態に関する属性と,属性のセッターとゲッターを持つ.

    有効期限(スコープ)は, セッションの期間,あるいは,システムの稼動期間である. つまり,個々の HTTP リクエストの期間を超えて共有される.

  4. Struts マッピング定義ファイルである struts-config.xml

    画面遷移,アクションマッピング,アクションフォワードに関する定義が行われている設定ファイル.

    1. Struts アクションフォーム・ビーンの定義(識別子とクラス名)
    2. アクションの定義(アクション名,アクションクラス名,アクションフォームビーンを構成する属性名など)

      HTTP リクエスト処理のためにアクションマッピング(HTTPリクエストと,特定のアクション・クラスの execute メソッドとのマッピング)と, アクションフォワードにおける,JSP プログラムのフォワード(Struts アクションマッピングオブジェクトと JSP プログラムとのマッピング)

  5. Struts 入力データ検証用設定ファイルである validation.xml

    入力フォームに記入されるべきフォームデータの各項目について,データの種類や制約が記述されたファイル. データの種類や制約が満足されていることが自動的に検証され,エラーがあれば,所定の処理が行われる.

  6. Struts フレームワークが有するアクションサーブレット

    Struts フレームワークが有するアクションサーブレットが,クライアントからの要求(HTTPリクエスト)を,適切な Struts アクション・クラスに委譲する. (所定の Struts アクション・クラスの execute メソッドが呼び出される). 同時に,フォームデータを,Struts アクションフォーム・ビーンに格納する. このとき,Struts アクションフォーム・ビーンの validate メソッドも使い,入力データの検証が行われる (これは,validation.xml による検証と別のもので,validation.xml では出来ない細かなエラー処理ができる).

  7. アクションに関する処理を行う,Struts アクション・クラス

    Struts アクション・オブジェクトの役割は,大きく2つある. 1つは, HTTPリクエストとビジネスロジックを提供する Java ビーンとの間の仲介役である. もう1つは,アクションフォワードである.

    Struts アクション・オブジェクトは,実際のHTTPリクエストの処理を行うために, ビジネスロジックを提供する Java ビーンを呼び出す. この呼び出しをディスパッチという. 「ディスパッチ」と書いているのは,Struts アクションは処理の振り分けのみで,実質的な処理は,ビジネスロジックで行われるという意味である. このディスパッチのために,Struts アクションフォーム・ビーンに格納されたデータ等が使用される. (アクションフォーム・ビーンを,セッターを使って設定するのは,Struts アクション・クラスの役目である)

    Struts アクション・オブジェクトは, アクションフォワードを行う. これは,Struts アクションフォーム・ビーンに格納されたデータを使い,アクションフォワード・オブジェクトを生成する処理である. アクションフォワード・オブジェクトの値と,JSPプログラムとのマッピングは struts-config.xml に定義されている. これで,次のページへの遷移が行われる.

    Struts アクション・クラスは,Struts の org.apache.struts.action.Action クラスのサブクラスとして定義される. 処理は,execute メソッドに実装される.

  8. ビジネスロジックを提供する Java ビーンのクラス

    アプリケーションの各種機能は,ビジネスロジックを提供する Java ビーンのクラスに実装される.

    アクションフォーム・ビーンを private メンバ属性として保持する(アクションフォーム・ビーンを,セッターを使って設定するのは,Struts アクション・クラスの役目である) ビジネスロジックを提供する Java ビーンにおける処理結果は,別の Java ビーン・オブジェクトに格納される.

準備事項

前準備

JDK (Java Development Kit) のインストール

Eclipse のインストール

その他

設定項目

前もって,Tomcat のバージョンを調べておいて下さい

前もって,Tomcat インストールディレクトリを調べておいてください.このページでは,次のように書く.

Eclipse での Struts プログラムの作成手順

以下,Eclipse を使う. プロジェクトの作成クラスの定義実行という一連の操作を,図解で説明する.

Eclipse の使用にあたって,事前に決めておく事項

Java サーブレット・プログラムを動かすために,Eclipse のプロジェクト等を作る. Web ページでは,プロジェクト名,Java パッケージ名は次のように記述します. (すでに同じ名前のプロジェクトがある,といったときは,プロジェクト名を変えてください).

Struts を使う上で,作業場の重要な点(忘れやすい点)は,次の2つです.忘れずに行うこと.

  1. 動的 Web プロジェクトへの Struts サポートの追加 が必要である.
  2. Struts サポートの追加を行うときは,Web アプリケーションのルートとして,WebContent を指定すること.

ここでは,Struts プログラムの例を使って,作成手順を説明する.ファイル構成は次のようになっています.

├HLgame
 ├
 :
 ├Javaリソース; src
 │└hoge.hoge.com
 │ ├StartAction.java
 │ ├HighAndLowAction.java
 │ ├HighAndLowForm.java
 │ ├HighAndLowData.java
 │ └BusinessLogic.java
 :
 ├WebContent ← Webアプリケーションのルート
  ├WEB-INF
  │ :
  │ ├struts-config.xml
  │ :
  │ ├validation.xml
  │ :
  │ 
  ├index.jsp
  ├game.jsp
  └gameover.jsp

[image]

アクションとアクションフォーム・ビーンとJSPの関係は次のようになっています.

動的 Web プロジェクトの新規作成

下記の手順で,動的 Web プロジェクトを新規に作成する.

  1. (もし,プロジェクト・エクスプローラが開いていなければ)プロジェクト・エクスプローラを開く

    「ウインドウ (Window)」→「ビューの表示 (Show View)」→「プロジェクト・エクスプローラ (Project Explorer)」 と操作する.

  2. プロジェクトの新規作成の開始

    ファイル」→「新規 (New)」→「プロジェクト (Project)
    または,プロジェクト・エクスプローラ内で,右クリック→「新規 (New)」→「プロジェクト (Project)」

  3. Web」の展開

    新規プロジェクトのウインドウが開くので, 「Web」を展開する.

  4. 動的 Webプロジェクト (Dynamic Web Project)」の選択

    展開した「Web」の下にある 「動的 Webプロジェクト (Dynamic Web Project)」を選び, 「次へ」をクリック

    [image]
  5. プロジェクト名の設定など

    設定用のウインドウが開くので,下記の設定を行う. 設定が終わったら,「次へ」をクリック.

    ◆ Tomcat のバージョンが「Apache Tomcat v5.5」の場合の設定例

    [image]
  6. 次の「プロジェクト・ファセット」は,デフォルトのままでよい

    「次へ」をクリック.

    このウインドウが開かないことがある.気にしなくてよい.

    [image]
  7. プロジェクト構成

    [image]
  8. 次の「Web モジュール」は,デフォルトのままでよい

    web.xml デプロイメント記述子の生成」をチェックし、 「終了」をクリック.

  9. もし「関連付けられたパースペクティブを開きますか?」と聞いてきたら,「はい」をクリック

    [image]

    このウインドウが開かないことがある.気にしなくてよい.

  10. 作成されたプロジェクトの確認

    [image]

Eclipse 3.X を使用していて、StrutsIDE をインストールしている場合には、 次の手順で、「動的 Web プロジェクトへの Struts サポートの追加 」を行うことができる.

  1. 新規作成したプロジェクトである「HLgame」の「WebContent」を右クリック.
  2. 「新規」
  3. Strutsサポートの追加

    「その他」→「Amateras」→「Struts」→「Strutsサポートの追加」と操作し, 「次へ」をクリック.

    [image]

    「Strutsサポートの追加」が出てこないときは, Eclipse StrutsIDE プラグイン の手順を行った後に, ここの手順を繰り返す.

  4. Struts サポートの設定の確認

    Webアプリケーションのルートが,<プロジェクト名>/WebContent のようになっていることを確認.

    なっていなければ,Web アプリケーションのルートを,<プロジェクト名>/WebContent のように設定

    <プロジェクト名>/WebContent の設定を忘れたら,プロジェクトの作成からやり直し)

    [image]
  5. 終了

Struts用のJARファイルが設定されるとともに,各種設定ファイルのひな型が生成される.

XML ファイルとJSPファイルのエディタは,デフォルトでは WTP のエディタになっている.デフォルト以外のエディタで開きたいときは, XML ファイルとJSPファイルを右クリックして,エディタを選べる

Apache Structs2 に関する設定

  1. ダウンロード

    http://struts.apache.org/development/2.x/

  2. ダウンロードした ZIP ファイルを分かりやすいディレクトリに置き、展開(解凍)する

    Ubuntu での操作手順例

    unzip struts-2.3.15.3-all.zip
    
  3. jar ファイルの確認

    Ubuntu での操作手順例

    [image]
  4. 解凍したディレクトリ名を覚えておく(あとでインポートする)

Java パッケージ作成

Eclipse のプロジェクト・エクスプローラを使って, Java パッケージを作成します. Java パッケージ名には hoge.hoge.com のようなドメイン名を付ける習慣があることに注意してください. このページでは,作成するJava パッケージ名は,hoge.hoge.com と書く. (Java パッケージ名を変えるときは,読み替えてください).

  1. (もし,プロジェクト・エクスプローラが開いていなければ)プロジェクト・エクスプローラを開く

    「ウインドウ」→「ビューの表示」→「プロジェクト・エクスプローラ」 と操作する.

    Java パッケージの作成,クラスの作成などの作業は,プロジェクト・エクスプローラで行う.

  2. Java パッケージを新規作成すべきプロジェクトの選択

    プロジェクト・エクスプローラに,プロジェクト一覧が表示されているはずです. Java パッケージを新規作成したいプロジェクト名 HLgame右クリックして, 「新規」→「パッケージ」と操作する.

    [image]
  3. Java パッケージ名の指定

    「Java パッケージ (Java package)」名前は,Java パッケージ名 hoge.hoge.comを記入する.その後,「終了」をクリック.

    [image]

Apache Struts2 ファイルのインポート

  1. いま作成したプロジェクトのWEB-INF/libを右クリックし、「インポート」を選ぶ

    [image]
  2. 一般」を展開し「ファイルシステム」を選ぶ

    [image]
  3. 先ほど Apache Struts2 を展開したディレクトリ選ぶ

    jar ファイルが入っているディレクトリを選ぶ

    [image]

クラス定義

5つのクラス StartAction, HighAndLowAction, HighAndLowForm, HighAndLowData, BusinessLogic.java

  1. プロジェクト・エクスプローラで, プロジェクト名の下の 「Java リソース; src」または「src」の下を展開すると,Java パッケージ名 hoge.hoge.com が出ます.
  2. Java パッケージ名 hoge.hoge.com を右クリックして,クラス作成

    [image]

    ◆上記の5つのクラスを作成し終わったところ

    [image]
  3. プロジェクト・エクスプローラで,クラスの「クラス名.java 」ダブルクリック すると,エディタが開きます.下記のプログラムを,カット&ペースト.

StartAction.java

----------------------ここから----------------------
package hoge.hoge.com;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

// アクション・クラス
public class StartAction extends Action {
    
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception{

        //
        // ゲーム開始
        //
        
        HttpSession session = request.getSession();
       
        //システム内部状態オブジェクトを作成.セッション変数に保存
        HighAndLowData highAndLowData = new  HighAndLowData();
        highAndLowData.reset();
        session.setAttribute("data", highAndLowData);
       
        // ビジネスロジックオブジェクトを作成
        BusinessLogic businessLogic = new BusinessLogic();
        businessLogic.setHighAndLowData(highAndLowData);
        businessLogic.startHighAndLowGame();

        return mapping.findForward("success");
    }
}
----------------------ここまで----------------------

HighAndLowAction.java

----------------------ここから----------------------
package hoge.hoge.com;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

// アクション・クラス
public class HighAndLowAction extends Action {
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception{

        HttpSession session = request.getSession();
       
        // システム内部状態オブジェクトは生成済み(のはず)
        HighAndLowData highAndLowData = (HighAndLowData)session.getAttribute("data");
        // 入力フォームオブジェクトは,本メソッドのパラメータ
        HighAndLowForm highAndLowForm = (HighAndLowForm) form;
        
        // 実際の処理は,ビジネスモデルに依頼
        BusinessLogic businessLogic = new BusinessLogic();
        businessLogic.setHighAndLowData(highAndLowData);
        businessLogic.setHighAndLowForm(highAndLowForm);
       
        int betMoney=highAndLowForm.getBetMoney();
        //賭け金が正しくない場合
        if(betMoney > highAndLowData.getBalance()){
            ActionMessages ms = new ActionMessages();
            ActionMessage m = new ActionMessage("エラー:賭け金が所持金を超えています.");
            ms.add(ActionMessages.GLOBAL_MESSAGE, m);
            saveErrors(request, ms);
            return mapping.findForward("betmoneyfault");
        }
        //Highが押された場合
        else if(highAndLowForm.getSubmit().equals("High")){
            boolean result = businessLogic.betHighResult();    //Highを選んだ場合の処理
            businessLogic.choiceNextCard();        //次のカードを決定
        //残金が0となった場合
            if(!result){
                return mapping.findForward("gameover");
            }
            else {
                //highAndLowData = businessLogic.getHighAndLowData();
                session.setAttribute("data", highAndLowData);
                return mapping.findForward("success");
            }
        }
        //Lowが押された場合
        else{
            boolean result = businessLogic.betLowResult();    //Lowを選んだ場合の処理
            businessLogic.choiceNextCard();        //次のカードを決定
        //残金が0となった場合
            if(!result){
                return mapping.findForward("gameover");
            }
            else {
                //highAndLowData = businessLogic.getHighAndLowData();
                session.setAttribute("data", highAndLowData);
                return mapping.findForward("success");
            }
        }
    }
}
----------------------ここまで----------------------

HighAndLowForm.java

----------------------ここから----------------------
package hoge.hoge.com;

import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.validator.ValidatorForm;
import javax.servlet.http.HttpServletRequest;

public class HighAndLowForm extends ValidatorForm {

    private int betMoney = 0;    //賭け金
    private String submit = null;  //サブミットボタン

    public int getBetMoney() {
        return betMoney;
    }
    public void setBetMoney(int betMoney) {
        this.betMoney = betMoney;
    }
    public String getSubmit() {
        return submit;
    }
    public void setSubmit(String submit) {
        this.submit = submit;
    }
    
    public void reset(){
        this.betMoney = 0;
        this.submit = null;
    }
    public ActionErrors validate(ActionMapping mapping, HttpServletRequest request){
        ActionErrors errors = new ActionErrors();
        // betMoney チェック
        if ( getBetMoney() <= 0) {
            errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("errors.detail", "「掛け金」 は必須です.範囲は1以上の整数です"));
            System.out.println("validate ERROR");
            return errors;
        }
        return null;
    }
}
----------------------ここまで----------------------

HighAndLowData.java

----------------------ここから----------------------
package hoge.hoge.com;

public class HighAndLowData {

    private int previousCard;  //前のカード
    private int nextCard;   //次のカード
    private int balance;    //残高
    private int getMoney;   //獲得金額
    
    public int getPreviousCard() {
        return previousCard;
    }

    public void setPreviousCard(int previousCard) {
        this.previousCard = previousCard;
    }

    public int getNextCard() {
        return nextCard;
    }

    public void setNextCard(int nextCard) {
        this.nextCard = nextCard;
    }

    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }

    public int getGetMoney() {
        return getMoney;
    }

    public void setGetMoney(int getMoney) {
        this.getMoney = getMoney;
    }
    
    public void reset(){
        this.previousCard = 8;
        this.nextCard = 1;
        this.balance = 10000;
        this.getMoney = 0;
    }
}
----------------------ここまで----------------------

BusinessLogic.java

----------------------ここから----------------------
package hoge.hoge.com;

public class BusinessLogic {

    /**
     * 内部状態を管理するクラス : HighAndLowData
     *
     * 残金の値を管理する変数 : balance
     * 賭け金の値を管理する変数 : betMoney
     * 前のカードの値を管理する変数 : previousCard
     * 次のカードの値を管理する変数 : nextCard
     */
    private HighAndLowData highAndLowData = null;
    
    public void setHighAndLowData(HighAndLowData data){
        this.highAndLowData = data;
    }
    
    public HighAndLowData getHighAndLowData(){
        return this.highAndLowData;
    }

    /**
     * フォームのデータを管理するクラス : HighAndLowForm
     *
     * 賭け金の値を管理する変数 : betMoney
     */
    private HighAndLowForm highAndLowForm = null;
    
    public void setHighAndLowForm(HighAndLowForm form){
        this.highAndLowForm = form;
    }
    
    public HighAndLowForm getHighAndLowForm(){
        return this.highAndLowForm;
    }
    
    /**
     * 持ち金の初期値
     */
    private int defaultBalance = 10000;
    
    /**
     * 内部状態に対する初期値の設定
     */
    public void startHighAndLowGame(){
        int previousCard = ((int)(Math.random() * 12.99)) + 1;
        this.highAndLowData.setPreviousCard(previousCard);
        int nextCard = ((int)(Math.random() * 12.99)) + 1;
        this.highAndLowData.setNextCard(nextCard);
        this.highAndLowData.setBalance(defaultBalance);
    }
    
    /**
     * 次のカードを決定する関数
     * doubule型のランダムな値を出力関数 Math.random() を使用し1~13の値を次のカードの値とする
     */
    public void choiceNextCard(){
        int nextCard = ((int)(Math.random() * 12.99)) + 1;
        this.highAndLowData.setPreviousCard(this.highAndLowData.getNextCard());
        this.highAndLowData.setNextCard(nextCard);
    }
    
    /**
     * 2つのカードの大小関係を調べる関数
     * このゲームでのカードの強さの関係 : 2 < 3 < ・・・ < 10 < J(11) < Q(12) < K(13) < A(1)
     * 返り値として正の値(1), 0, 負の値(-1)を返す
     *   1 : 実行した結果Highだった場合
     *   0 : 実行した結果同じ数値だった場合
     *  -1 : 実行した結果Lowだった場合
     */
    private int compareTwoCards(){
        
        int previousCard = this.highAndLowData.getPreviousCard();
        int nextCard = this.highAndLowData.getNextCard();
        
        // 2つのカードが同じ数値だった場合
        if(previousCard == nextCard) return 0;
        
        // previousCardが 1 だった場合は無条件でLow
        if(previousCard == 1) return -1;
        
        // nextCardが 1 だった場合は無条件でLow
        if(nextCard == 1) return 1;
        
        // 両カードが2~13のどれかの値であるため単純な大小比較で判断
        if(previousCard < nextCard) return 1;
        else return -1;
    }
    
    /**
     * Highを選択した結果変化する残高を計算する関数
     * 賭け金 betMoney を引数として持つ
     * 返り値としてbooleanを返す
     *  true  : 実行した結果残金の値が残っている場合
     *  false : 実行した結果残金の値が0になった場合
     */
    public boolean betHighResult(){

        int balance = this.highAndLowData.getBalance();
        int betMoney = this.highAndLowForm.getBetMoney();
        
        // 2つのカードの比較
        int result = this.compareTwoCards();
        
        // Highである場合(ユーザの勝ち)
        if(result == 1){
            
            balance += betMoney;
            this.highAndLowData.setBalance(balance);
            this.highAndLowData.setGetMoney(betMoney);
            
            return true;
        }
        // 同じ又はLowである場合(ユーザの負け)
        else{
                        
            balance -= betMoney;
            this.highAndLowData.setBalance(balance);
            this.highAndLowData.setGetMoney(-betMoney);
            
            if(balance == 0) return false;
            else return true;
        }
    }
    
    /**
     * Lowを選択した結果変化する残高を計算する関数
     * 賭け金 betMoney を引数として持つ
     * 返り値としてbooleanを返す
     *  true  : 実行した結果残金の値が残っている場合
     *  false : 実行した結果残金の値が0になった場合
     */
    public boolean betLowResult(){

        int balance = this.highAndLowData.getBalance();
        int betMoney = this.highAndLowForm.getBetMoney();
        
        // 2つのカードの比較
        int result = this.compareTwoCards();
        
        // Lowである場合(ユーザの勝ち)
        if(result == -1){
            
            balance += betMoney;
            this.highAndLowData.setBalance(balance);
            this.highAndLowData.setGetMoney(betMoney);
            
            return true;
        }
        // 同じ又はHighである場合(ユーザの負け)
        else{
            
            balance -= betMoney;
            this.highAndLowData.setBalance(balance);
            this.highAndLowData.setGetMoney(-betMoney);
            
            if(balance == 0) return false;
            else return true;
        }
    }
}
----------------------ここまで----------------------

JSPファイルの作成

3つのJSPファイル index.jsp, game.jsp, gameover.jsp を作成する.

Struts のタグを使う. Struts のタグについては, Struts のタグ一覧 を参考にして下さい.

  1. プロジェクト・エクスプローラで, プロジェクト名 HLgame の下の 「WebContentを展開しておく

    [image]
  2. WebContent を右クリックして,3つの JSP ファイルを作成.

    [image]
  3. 生成したJSPファイルの確認

    [image]
  4. プロジェクト・エクスプローラで,JSP ファイルダブルクリック すると,エディタが開きます.下記のプログラムを,カット&ペースト.

index.jsp

----------------------ここから----------------------
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-nested" prefix="nested" %>

<html:html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=Shift-JIS"/>
    <%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="Windows-31J" %>

 
    <title>Game Start</title>
  </head>
  <body>
    <html:form method="POST" action="/startAction">    

   
      <html:submit property="submit" value="GameStart"/>

   
    </html:form>
  </body>
</html:html>
----------------------ここまで----------------------

game.jsp

----------------------ここから----------------------
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-nested" prefix="nested" %>

<html:html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="Windows-31J" %>
    <title>High and Low Game</title>
  </head>
  <body>
    <html:form method="POST" action="/highAndLowAction">
      <center>
    <h1>High And Low Game</h1>
    <h4>〜ルール〜</h4>
    <table summary="ゲーム説明">
      <tr align=left>
        <td>
          <table border=1 summary="ルール" cellspacing=5 cellpadding=3 bordercolor="#000000">
        <tr>
          <td><ul>
              <li>
            次に引くカードの値が前のカードの値よりも高い(High)か低い(Low)かを当てるゲーム.<br>
            どちらかにお金を賭けて,当たりであれば賭け金は倍になって戻ってくる.<br>
            ハズレであれば賭け金は失なわれる.<br><br></li>
              <li>カードの値の高い・低いは以下の通り
            <ul><li>【高い】 1 > 13 > 12 > ・・・ > 3 > 2 【低い】</li></ul>
            </li></ul>
        </td></tr>
          </table>
        </td>
      </tr>
      <tr><td><br></td></tr>
      <tr align=left><td>
          <ol>
        <li>賭け金を設定してください</li>
        <li>【High】か【Low】かを選び,選んだ方のボタンを押してください</li>
          </ol>

         
          <logic:messagesPresent>
        <STRONG>入力内容が正しくない場合,ゲームができませんので,正しくご入力ください</STRONG>
        <html:messages id="msg" message="false">
          <li style="color: red"><bean:write name="msg" /></li>    
        </html:messages>    
          </logic:messagesPresent>
         
      </td></tr>
    </table>
    <br>
    <table border=1 cellpadding=3 width=260 summary="ゲームテーブル">
      <tr align=center>
        <td>前のカード</td>
        <td>
          <table border=1 width=20pt cellspacing=0 bordercolor="#000000" summary="前のカード">
        <tr align=center>
          <td><bean:write name="data" property="previousCard"/></td>
        </tr>
          </table>
        </td>
      </tr>
      <tr align=center>
        <td>次のカード</td>
        <td>
          <table border=1 width=20pt cellspacing=0 bordercolor="#000000" summary="次のカード">
        <tr align=center>
          <td>?</td>
        </tr>
          </table>
        </td>
      </tr>
      <tr align=center>
        <td>賭け金</td>
        <td>
          <input type="text" name="betMoney" style="text-align:right" size=15/>
        </td>
      </tr>
      <tr align=center>
        <td rowspan="2"> High<br>or<br>Low</td>
        <td>
          <html:submit property="submit" value="High"/>
        </td>
      </tr>
      <tr align=center>
        <td>
          <html:submit property="submit" value="Low"/>
        </td>
      </tr>
      <tr align=center>
        <td>残金</td>
        <td align=right>
          <bean:write name="data" property="balance"/>
        </td>
      </tr>
      <tr align=center>
        <td>前回の獲得金額</td>
        <td align=right>
          <bean:write name="data" property="getMoney"/>
        </td>
      </tr>
    </table>
      </center>
    </html:form>
  </body>
</html:html>
----------------------ここまで----------------------

gameover.jsp

----------------------ここから----------------------
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-nested" prefix="nested" %>

<html:html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Game Over</title>
  </head>
  <body>
    <h1 align=center>GAME OVER</h1>
  </body>
</html:html>
----------------------ここまで----------------------

WebContet\WEB-INF\lib\struts-config.xml

すでに存在する WebContet\WEB-INF\lib\struts-config.xml を,次のものに置き換え

  1. struts-config.xmlを開く.

    プロジェクトを展開,WEB-INF を展開.struts-config.xml を右クリック. 「アプリケーションから開く」→「struts-config.xmlエディタ」

  2. ソースエディタに切り替え

    struts-config.xmlエディタでは, 「フロー」,「ソース」の2つのタブがある. 「ソース」をクリックして,ソースエディタに切り替える.

  3. カット&ペースト
----------------------ここから----------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
  <data-sources>
  </data-sources>
  <form-beans>
    <form-bean name="highAndLowForm" type="hoge.hoge.com.HighAndLowForm"/>
  </form-beans>
  <global-exceptions>
  </global-exceptions>
  <global-forwards>
  </global-forwards>
  <action-mappings>
    <action path="/highAndLowAction" name="highAndLowForm" type="hoge.hoge.com.HighAndLowAction" scope="session" validate="true" input="/game.jsp">
      <forward name="success" path="/game.jsp"/>
      <forward name="betmoneyfault" path="/game.jsp"/>
      <forward name="gameover" path="/gameover.jsp"/>
    </action>
    <action path="/startAction" name="highAndLowForm" type="hoge.hoge.com.StartAction" scope="session" validate="false" input="/index.jsp">
      <forward name="success" path="/game.jsp"/>
    </action>
  </action-mappings>
  <controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/>
  <message-resources parameter="MessageResources"/>
  <plug-in className="org.apache.struts.tiles.TilesPlugin">
    <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml"/>
    <set-property property="moduleAware" value="true"/>
  </plug-in>
  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
  </plug-in>
</struts-config>
----------------------ここまで----------------------

WebContet\WEB-INF\lib\validation.xml

すでに存在する WebContet\WEB-INF\lib\validation.xml を,次のものに置き換え

----------------------ここから---------------------
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE form-validation PUBLIC
          "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
          "https://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">

<form-validation>

    <global>
   
    </global>

    <formset>

        <form name="highAndLowForm">
            <field property="betMoney" depends="required,intRange">
                <!-- return "Bet Money is required." -->
                <msg name="required" key="errors.required"/>
                <arg0 key="Bet Money" resource="false"/>
                <!-- return "Bet Money is not in the range 0 through Balance." -->
                <msg name="intRange" key="errors.range"/>
                <arg0 key="Bet Money" resource="false"/>
                <arg1 key="1" resource="false" />
                <arg2 key="Balance" resource="false" />
                <!-- range setting -->
                <var>
                    <var-name>min</var-name>
                    <var-value>1</var-value>
                </var>
                <var>
                    <var-name>max</var-name>
                    <var-value>2147483647</var-value>
                </var>
            </field>
        </form>

    </formset>

</form-validation>
----------------------ここまで----------------------

Struts サンプルプログラムのテスト実行

Eclipse のプロジェクト・エクスプローラを使用して,テスト実行を行ってみる.

  1. Eclipse のプロジェクト・エクスプローラで,プロジェクト名 HLgame を右クリック
  2. 実行 (Run As)」→「サーバーで実行 (Run on Server)」と操作
  3. Eclipse 内部の tomcat サーバ: が起動(または,再起動)する(結果は,コンソール・ビューに表示される).
  4. 実行結果の確認

    Eclipse の 組み込み Web ブラウザ (Internal Web ブラウザ)が開き,そこに実行結果が出る.

    このウインドウに,index.jsp の表示結果が出れば成功.

    Internal Web ブラウザ内のアドレスバーの部分は,

    http://localhost:8080/HLgame/
    

    のようになっていることを確認しておきます

アクション単位での実行

Tomcatサーバを起動し, Webブラウザで,URL として,「http://localhost:8080/プロジェクト名/任意のアクション名.do」を指定. これで,アクション名を直接指定しての実行ができる.

validate メソッドによる妥当性検証

上記のプログラムでは, アクションフォーム・ビーンの validate メソッドを使って, 「掛け金」が1以上であることを検証している

アクションフォーム・ビーンでの妥当性検証は,入力データとして妥当かのチェックです. 業務ルール的なエラーのチェックです.例えば,持ち金以上を掛け金にできない,という業務ルールのチェックは, アクションフォーム・ビーンでは無く,アクション・クラスで行うことになる.

妥当性検証では,必須属性(空であることを許さない),範囲(○○以上○○以下の整数など),文字列長(最小○○文字,最大○○文字など)などのチェックを行うことになる.

  1. validate メソッド
        public ActionErrors validate(ActionMapping mapping, HttpServletRequest request){
            ActionErrors errors = new ActionErrors();
            // betMoney 範囲チェック
            if ( getBetMoney() <= 0) {
                errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("errors.detail", "「掛け金」 は必須です.範囲は1以上の整数です"));
                return errors;
            }
            return null;
        }
    

    アクションフォームビーンに格納された値は, validate メソッドで妥当性が検証されます. つまり,validate メソッドを自前で書いておくと,アクションの呼び出しの前に,妥当性検証が自動的に行われます.エラーがあれば,アクションが呼び出されません. validate メソッドの書き方は,上記のようになる.

    文字列のチェックであれば,equals(""), isBlankOrNull などを使うことになるでしょう.

  2. game.jsp
    <logic:messagesPresent>
        <STRONG>入力内容が正しくない場合,ゲームができませんので,正しくご入力ください</STRONG>
        <html:messages id="msg" message="false">
            <li style="color: red"><bean:write name="msg" /></li>    
        </html:messages>    
    </logic:messagesPresent>
    

    エラーメッセージの表示について記述します.

  3. (参考) struts-config.xml

    action 要素の input 属性で,エラー時の遷移先(JSP)を指定します.

  4. (参考) MessageResource.properties

    エラーメッセージ表示に関する設定ファイル

[image]

参考Webページ, The Apache Struts Web Application Framework (Struts 提供元): https://jakarta.apache.org/struts/index.html

参考Webページ, The Ja-Jakarta Project Struts翻訳 (Ja-Jakarta Project による Struts ドキュメントの翻訳): http://www.ingrid.org/jajakarta/struts/