Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
61
Help us understand the problem. What is going on with this article?
@ebichan_88

【Struts入門】今さらStruts1.3.10を勉強したのでまとめてみた【初心者向け】

はじめに

2019年の時点でstruts1でWebアプリケーションを新規開発をする事はほとんどないと思いますが、
それでもstruts1で構築され、現在でも動いているWebアプリケーションはまだまだ存在すると思います。

今後もプロジェクトで関わる可能性が大いにあるフレームワークですが、
すでに枯れた技術でもあり、ほかの技術に比べて、学習できる書籍やサイトがそこまで多くありません。

そこで今回、struts1についてこれまで学習したことをまとめてみました。
自分が新人で初めてstruts1を勉強した時に、
この資料があれば嬉しかったなというものを作ろう!という思いでこの記事を書きました。
今後、少しでも多くの方がこの記事を読んで、struts1の概要を理解してもらえたら幸いです。

本記事が向いている人

  • struts1についての知識がないが、一通り概要を理解したい方

ゴール

  • struts1の構成や特徴などの大枠を理解できる状態
  • この記事を足がかりに、struts1の学習がスムーズに進められる状態

strutsについて

スクリーンショット 2019-08-27 19.13.45.png

strutsはApacheソフトウェア財団が提供している、MVCモデルを採用した、Webアプリケーションを作成するためのオープンソースのフレームワークです。

2000年にリリース後、struts1はJavaベースのWebアプリケーション開発の主流となりました。
その後、2008年12月に最終バージョンであるstruts1.3.10がリリースされ、2013年4月に正式にサポートが終了となりました。1

MVCモデルとは アプリケーションをModel, View, Controllerという役割ごとに分割してコーディングを行うモデルとなります。
 MVCモデルの詳細に関しては、以下の記事を参考になります。
 MVCモデルについて

strutsの特徴

strutsの主な特徴は以下が挙げられます。

1.遷移先などの処理を設定ファイル(struts-config.xml)で管理

★★ ここが一番重要です!! ★★

strutsではリスエストに対応する処理を設定ファイル(struts-config.xml)で管理しており、遷移先や実行処理を修正する際はstruts-config.xmlを修正すれば良いです。

そのため、struts-config.xmlの内容が理解できれば、どの画面に遷移するか、どの処理が実行されるがとても簡単に理解できるようになります。

jspファイルと設定ファイル(struts-config.xml)の関係性は以下となります。

jspファイルと設定ファイル(struts-config.xml)の関係性について

jspファイル 設定ファイル(struts-config.xml)
<form>タグのアクション属性にAction名を定義 リクエスト時に<action>エレメントのpath属性と一致するアクションを実行

スクリーンショット 2019-08-27 23.25.43.png

struts-config.xmlの説明に関してはこちら

2.validationの提供

Strutsでは入力データの必須チェックや文字数チェックの処理などのvalidationの機能が提供されており、入力チェック用のプログラムを実装する手間が省けます。

以下のログイン画面の入力チェックも、strutsが提供しているvalidation.xmlでパラメータの検証ルールを定義し、
メッセージ・リソースファイルを用いてエラーの際に表示するメッセージを設定する事で実装が可能となります。

9月-10-2019 01-10-25.gif

validationの説明に関してはこちら

3.タグライブラリの提供

Strutsは<logic>タグや<bean>タグなど独自のタグライブラリが用意されており、Javaコードの代わりに専用タグライブラリを使用することで、画面(JSP)の可読性の向上や記述レベルの統一が可能となります。

タグライブラリの説明に関してはこちら

4.二度押し防止機能(トークンチェック)の提供

Strutsでは同じ処理が複数回実行されることを防止するため、トランザクショントークンを用いたトークンチェックの機能が提供されています。
ブラウザから送信されたトークンとsessionスコープに格納されたトークンを比較することで処理を継続すべきか判定することができ、同じサブミットボタンを二重クリックした場合や、戻るボタンを利用した不正な画面遷移の場合に、エラーとすることが可能です。

以下の画面例だと、次の遷移をした場合に、
入力画面→確認画面→登録完了画面→(ブラウザの戻るボタンを用いて)確認画面
確認画面から登録ボタン押下時に不正遷移と判断されエラー画面に遷移するように実装されています。
3月-29-2020 18-25-08.gif

二度押し防止機能の説明に関してはこちら

5.例外処理機能の提供

strutsでは例外発生時に、struts-config.xmlの<global-exceptions>タグを用いて、例外が発生した際の処理を定義することができます。
そのため、標準のエラー画面(404エラーなど)が表示されることなく例外処理のハンドリングをすることが可能です。

例外処理機能の説明に関してはこちら

6.その他

  • ログ出力機能(Commons-Loggingを利用)
  • 国際化対応 など

strutsの処理の流れ

strutsの構成・処理の流れは下図となります。
スクリーンショット 2019-08-18 12.35.30.png「Struts逆引き大全333の極意」を元に作成

図の処理の流れをざっくり説明すると以下となります。

1. クライアントからのリクエストを送信
2. アクションサーブレットが設定ファイルをもとに実行する処理を特定
3. クライアントから送信された情報をアクションフォームに設定
4. アクションクラスの実行
5. アクションクラスの実行結果をもとに遷移先を決定

strutsの基本構成

strutsの基本的な構成要素は「strutsの処理の流れ」で図に記載した

  • アクションサーブレット
  • アクションフォーム
  • アクションクラス
  • JSP
  • struts設定ファイル(struts-config.xml)

の5つに加えて

  • Web.xml
  • メッセージ・リソースファイル

などが挙げられます。

1.アクションサーブレット

1-1.アクションサーブレットの概要

アクションサーブレットはMVC構成のコントローラの役割を持つサーブレットです。
リクエストを受け付けると、リクエストを元にパラメータをアクションフォームに格納、アクションクラスのexecuteメソッドの実行、アクションクラスの戻り値を元に画面遷移を実施するなどの処理をRequestProcessorに依頼します。

2.アクションフォーム

2-1.アクションフォームの概要

フォームから入力されたリクエストデータを保持するBeanです。

フォームとは Web上で、利用者からの入力を受け付ける操作要素の集合を指します。
 Webで会員登録する際に氏名や電話番号などを入力するフィールドがそれに該当します。

以下の実装をすることでアクションフォームの作成が可能となります。

  • org.apache.struts.action.ActionFormを継承したクラスを作成
  • プロパティおよび各プロパティのgetter/setterメソッドを実装
ActionForm.java
import org.apache.struts.action.ActionForm;

public class UserActionForm  extends ActionForm {

    private String id; // ユーザーID
    private String pass; // パスワード

    public String getId() {
      return id;
    }
    public void setId(String id) {
      this.id = id;
    }
    public String getPass() {
      return pass;
    }
    public void setPass(String pass) {
      this.pass = pass;
    }
}

2-2.DynaActionFormについて

アクションフォームを定義する上でActionFormを継承したクラスの作成とプロパティのgetter/setterメソッドを実装する必要がありますが、DynaActionFormを用いるとアクションフォームBeanではなく、struts-config.xmlでプロパティを定義出来るため、クラスの作成が不要となります。

DynaActionFormは以下のように記述します。

struts-config.xml
    <form-beans>
    <form-bean name="UserActionForm" type="org.apache.struts.action.DynaActionForm">
      <form-property name="id" type="java.lang.String" initial=""/>
      <form-property name="pass" type="java.lang.String" initial=""/>
       </form-bean>
    </form-beans>

DynaActionFormで記述するエレメントの詳細に関して以下に説明します。

<form-bean>エレメント

<form-bean name="UserActionForm" type="org.apache.struts.action.DynaActionForm">

type属性にorg.apache.struts.action.DynaActionFormを定義します。
(Validation機能を利用したい場合はorg.apache.struts.validator.DynaValidatorFormを定義)

<form-property>エレメント

      <form-property name="id" type="java.lang.String" initial=""/>
      <form-property name="pass" type="java.lang.String" initial=""/>

neme属性にプロパティ名type属性に型initial属性に初期値を定義します。
initial属性を省略した場合には、数字は0に、オブジェクトはnullに初期化されます。

2-3.アクションフォームのvalidationについて

アクションフォームはフォームから入力されたリクエストデータを保持するBeanですが、
リスエストデータを保持する際、各プロパティに対して、Validation(入力値チェック)を行うことが可能です。

validationの処理を追加するには以下の対応をする必要があります。

対応1:「org.apache.struts.validator.ValidatorForm」を継承する。

アクションフォームはActionFormクラスを継承する必要がありますが、継承元をValidatorFormクラスに変更する事で、validationの機能を追加することができます。

ActionForm.java
import org.apache.struts.validator.ValidatorForm;
// ActionFormからValidatorFormに継承元を変更する
public class SampleActionForm extends ValidatorForm {
      private String id;  

      public SampleActionForm(String id) {this.id = id;}

      public void setId(String id) {this.id = id;}
      public String getId() {return id;}

}

対応2:struts-config.xmlに「org.apache.struts.validator.ValidatorPlugIn」を追加する。

アクションフォームだけでなくstruts-config.xmlの設定も変更が必要となります。
struts-config.xmlの<plug-in>タグに以下の定義を追加することで、Validationの機能が追加されます。

struts-config.xml
  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property
        property="pathnames"
        value="/org/apache/struts/validator/validator-rules.xml,
               /WEB-INF/validation.xml"/>
  </plug-in>

Strutsのvalidatorは、<plug-in>タグで定義した、以下の2つの定義ファイルを元に、処理が実行されます。

  • validator-rules.xml:入力チェックのルールを詳細に定義したファイル
  • validation.xml:リクエストやアクションフォーム単位に、入力チェックを定義したファイル

対応3:struts-config.xmlに入力チェックを実施することを明示的に宣言する

struts-config.xml内の<action>エレメントのvalidate属性をtrueにすることでvalidation.xmlで定義した入力値チェックが実施されます。

また、input属性には入力値チェックに引っかかった場合の遷移先を定義する必要があります。

struts-config.xml
<action
 path="xxxxx" type="xxxxx" name="xxxxx" scope="xxxxx"              
 validate="true"               
 input="/index.jsp">           
<forward name="xxxxx" path="xxxxx"/> 
</action>

対応4:validation.xmlに実施する入力チェックの内容を定義する。

アクションフォームとstruts-config.xmlの設定が完了したら、validation.xml

  • 適用する入力チェック
  • エラーメッセージ出力に利用するメッセージリソースのkey

などを定義します。

validation.xml
<form-validation>
    <formset>
        <form name="SampleActionForm">
            <field
                property="id"
                depends="required,mask">
                <msg name="mask" key="field.invalidate" />
                  <arg key="field.id" />
                   <var>
                        <var-name>mask</var-name>
                        <var-value>^[0-9a-zA-Z]*$</var-value>
                    </var>
            </field>
       </form>
    </formset>
</form-validation>
MessageResources.properties
field.invalidate={0} は半角英数字で入力してください
field.id=id

上記の定義の場合、idというプロパティに対して、必須チェックと半角英数字チェックを定義しています。
半角英数字チェックでエラーが発生した場合は「idは半角英数字で入力してください」というメッセージが出力されるようになります。

メッセージリソースファイルの定義方法に関してはこちらを参照してください。
7.メッセージリソースファイル

2-4.validation.xmlで定義される各タグについて

<form>タグ

入力チェック対象のBeanごとに<form>タグを定義し、そのname属性にアクションフォームの名前を指定します。

<form name="SampleActionForm">

<field>タグ

各プロパティに対して実施する入力チェックに関しては<field>タグで定義します。
<field>タグの property属性には入力チェックを実施するプロパティ名を、depends属性には入力チェック名を指定します。(複数適用する場合はカンマで区切る。)

以下の定義の場合、idというプロパティに対して、必須チェック(required)指定のマスクパターンに合致しているかチェック(mask)を実施します。

指定のマスクパターンの詳細は後述する<var>タグで定義します。

<field property="id" depends="required,mask">

<msg>タグ

入力チェックが失敗した場合に生成するエラーメッセージに関しては<msg>タグで定義をします。
name属性はどのルールが通らなかった場合に表示するか指定するもので、タグのdepends属性で指定されている値から1つ指定します。key属性には表示するメッセージのキーを指定します。

key属性に指定したキーに紐づくメッセージはメッセージリソースファイルで定義する必要があります。

<msg name="mask" key="field.invalidate" />

<arg>タグ

メッセージリソースファイルに設定されているメッセージが以下のような形式だった場合

{0} は半角英数字で入力してください

<arg>タグのkey属性で定義した値を{0}の箇所にセットすることが可能となります。

<var>タグ

入力チェックに必要なパラメータを定義しています。

入力チェックルールの定義一覧

検証ルール名 検証内容 パラメーター<var-name> 指定値<var-value>
required 必須入力チェック
requiredif 条件付きのフィールド必須入力チェック field[数値] 依存するフィールド名
requiredif 条件付きのフィールド必須入力チェック fieldTest[数値] 依存するフィールドに対する条件(NULL or NOTNULL or EQUAL)
requiredif 条件付きのフィールド必須入力チェック fieldValue[数値] 依存するフィールドの比較値(fieldTestがEQUALの場合のみ指定する)
requiredif 条件付きのフィールド必須入力チェック fieldIndexed[数値] 依存するフィールドがindexed形式かどうかを指定する (true
requiredif 条件付きのフィールド必須入力チェック fieldJoin 依存するフィールドが複数ある場合、フィールド間の依存条件(AND[default] or OR )
validwhen 関連する複数のフィールドに対する入力チェック test ((otherField == null ) or (this != null))のような式
minlength 指定の長さ以上かをチェック minlength
maxlength 指定の長さ以下かをチェック maxlength
mask 指定のマスクパターンに合致しているかチェック mask Perl5互換の正規表現パターン
byte Byteクラスを生成できる文字列かをチェック byte値の文字列
short Shortクラスを生成できる文字列かをチェック short値の文字列
integer Integerクラスを生成できる文字列かをチェック integer値の文字列
long Longクラスを生成できる文字列かをチェック long値の文字列
float Floatクラスを生成できる文字列かをチェック float値の文字列
double Doubleクラスを生成できる文字列かをチェック double値の文字列
byteLocale プリミティブ型のbyteに変換可能な文字列かをユーザーのロケールを考慮してチェック byte値の文字列
shortLocale プリミティブ型のbyteに変換可能な文字列かをユーザーのロケールを考慮してチェック short値の文字列
integerLocale プリミティブ型のshortに変換可能な文字列かをユーザーのロケールを考慮してチェック integer値の文字列
longLocal プリミティブ型のlongに変換可能な文字列かをユーザーのロケールを考慮してチェック long値の文字列
floatLocale プリミティブ型のfloatに変換可能な文字列かをユーザーのロケールを考慮してチェック float値の文字列
doubleLocale プリミティブ型のdoubleに変換可能な文字列かをユーザーのロケールを考慮してチェック double値の文字列
date Dateクラスを生成できる文字列かをチェック datePattern (任意) 日付パターン文字列。フォーマットはSimpleDateFormatのコンストラクタを参照。datePatternStrictとは排他指定
date Dateクラスを生成できる文字列かをチェック datePatternStrict (任意) 厳密なチェックが行われる以外はdatePatternと同様。datePatternとは排他指定
intRange 指定した2つのInteger値の間にあるかをチェック min 最小値のinteger文字列
intRange 指定した2つのInteger値の間にあるかをチェック max 最大値のinteger文字列
longRange 指定した2つのLong値の間にあるかをチェック min 最小値のlong文字列
longRange 指定した2つのLong値の間にあるかをチェック max 最大値のlong文字列
floatRange 指定した2つのFloat値の間にあるかをチェック min 最小値のfloat文字列
floatRange 指定した2つのFloat値の間にあるかをチェック max 最大値のfloat文字列
doubleRange 指定した2つのDouble値の間にあるかをチェック min 最小値のdouble文字列
doubleRange 指定した2つのDouble値の間にあるかをチェック max 最大値のdouble文字列
creditCard 正当なクレジットカード番号のフォーマットかをチェック
email 正当なメールアドレスのフォーマットかをチェック
url 正当なURLのフォーマットかをチェック allowallschemes (任意) xxx://192.168.1.1/abc/のような未知のスキーマを許可(true or false[default])
url 正当なURLのフォーマットかをチェック allow2slashes (任意) http://1.1.1.1//a/のような2重スラッシュを許可(true or false[default])
url 正当なURLのフォーマットかをチェック nofragments (任意) http://1.1.1.1/a/b.html#c のようなフラグメント識別子を禁止(true or false[default])
url 正当なURLのフォーマットかをチェック schemes (任意) カンマセパレータのスキーマのリスト(default=http,https,ftp)
notEqual 同名のタグと同等の機能を果たす
notMatch 同名のタグと同等の機能を果たす
notPresent 同名のタグと同等の機能を果たす
present 同名のタグと同等の機能を果たす

以下サイトを元に作成
参考サイト:そるでぶろぐ | 株式会社アークシステムの技術者ブログ(https://devlog.arksystems.co.jp/2011/01/24/10500/

2-5.validator-rules.xmlについて

validator-rules.xmlは入力チェックのルールを定義しています。

Struts1.2系との違い

Struts1.2系ではWEB-INF配下にvalidator-rules.xmlが存在しますが、
Struts1.3.10ではstruts-core-1.3.10.jarに含まれています。

struts-config.xml(Struts1.2系)
  <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.xml(Struts1.3.10)
  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames" value="/org/apache/struts/validator/validator-rules.xml,/WEB-INF/validation.xml"/>
  </plug-in>

Struts1.2系で、独自の入力チェックルールを定義する場合は、WEB-INF配下のvalidator-rules.xmlを編集すれば良いですが、Struts1.3.10独自の独自の入力チェックルールを定義する場合は別ファイルを作成し、 WEB-INF配下に置いた上でstruts-config.xmlに追記すればよいです。

validator-rules.xmlの中身と各タグの説明

validator-rules.xml
<form-validation>
    <global>
        <validator name="required"
                   classname="org.apache.struts.validator.FieldChecks"
                   method="validateRequired"
                   methodParams="java.lang.Object,
                       org.apache.commons.validator.ValidatorAction,
                       org.apache.commons.validator.Field,
                       org.apache.struts.action.ActionMessages,
                       org.apache.commons.validator.Validator,
                       javax.servlet.http.HttpServletRequest"
                   msg="errors.required"/>
<!-- -------------------------中略-------------------------- -->
    </global>
</form-validation>
属性 説明
name validatorの名称を指定します
class クラス名を指定します
method メソッド名を指定します
methodParams メソッド引数を指定します
depends 対象のvalidotorルールを実行する前に実行すべきvalidatorルールがある場合に、そのルール名を指定します。
msg 入力チェックエラー時のエラーメッセージのメッセージkeyを指定します。

3.アクションクラス

3-1.アクションクラスの概要

アクションフォームにリクエストが設定された後に実行されるクラスとなります。
アプリケーションで行うビジネスロジックはこのアクションクラスに記述します。

アクションクラスの構成の特徴は以下となります。

  • org.apache.struts.action.Actionを継承
  • executeメソッドをオーバーライドして、ビジネスロジックを記述
  • executeメソッドの戻り値にActionMappingオブジェクトのfindForwardメソッドを用いて、どのjspに遷移するか指定
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public final class SampleAction extends Action {  
    public ActionForward execute(ActionMapping mapping,
            ActionForm form, 
            HttpServletRequest request,
            HttpServletResponse response) {

       //ビジネスロジックの記述

            //設定ファイル(struts-config.xml)のforwardタグのname属性に記載されているjspのパスに遷移
            return mapping.findForward("success");  
    }
}

3-2.executeメソッドの引数について

Actionクラスでメインロジックを記述するexecuteメソッドでは、
以下4つの引数を渡していますが、それぞれのクラスの役割について説明します。

  • ActionMapping
  • ActionForm
  • HttpServletRequest
  • HttpServletResponse
 public ActionForward execute(ActionMapping mapping,
            ActionForm form, 
            HttpServletRequest request,
            HttpServletResponse response)

ActionMappingについて

ActionMappingクラスはstruts-config.xmlの<action>エレメントで定義した内容が保持されています。
主な役割については以下が挙げられます。

ActionMappingの主な役割1:findForwardメソッドを用いた遷移先の指定

ActionMappingはfindForwardメソッドを用いて、遷移先の指定が可能です。

具体的には、findForwardメソッドの引数の値と一致している、struts-config.xmlのforwardタグのname属性に記載されているjspのパスに遷移します。

以下の実装では、findForwardの引数に"success"を指定しており、struts-config.xml内のname属性が"success"のforwardタグを確認すると/WEB-INF/jsp/sample.jspに遷移することがわかります。

SampleAction.java(一部抜粋)
//Actionクラス内でfindForwardの引数に"success"を指定して返却
return mapping.findForward("success");  
struts-config.xml(一部抜粋)
<!-- Actionクラスで返却された文字列と一致したname属性に指定したpathに遷移 -->
<forward name="success" path="/WEB-INF/jsp/sample.jsp"/> 

ActionMappingの主な役割2:<action>エレメント内の属性の取得

getPathメソッドなど<action>エレメント内の属性を取得することが可能です。

struts-config.xmlのpath/type/name/scope/validate/input属性の値を出力する実装例は以下となります。

struts-config.xml
<action
 path="/sample"
 type="package.SampleAction"   
 name="sampleForm"             
 scope="session"              
 validate="true"             
 input="/index.jsp">    
<forward name="success" path="/WEB-INF/jsp/sample.jsp"/> 
</action>
SampleAction.java
public final class SampleAction extends Action {  
    public ActionForward execute(ActionMapping mapping,
            ActionForm form, 
            HttpServletRequest request,
            HttpServletResponse response) {
        //<action>エレメントの属性の取得
        String path = mapping.getPath();
        String type = mapping.getType();
        String name = mapping.getName();
        String scope = mapping.getScope();
        boolean validate = mapping.getValidate();
        String input = mapping.getInput();

        System.out.println("path:" + path);
        System.out.println("type:" + type);
        System.out.println("name:" + name);
        System.out.println("scope:" + scope);
        System.out.println("validate:" + validate);
        System.out.println("input:" + input);

        return mapping.findForward("success");  
    }
}
実行結果
path:/sample
type:package.SampleAction
name:sampleForm
scope:session
validate:true
input:/index.jsp

ActionFormについて

2.アクションフォームで説明した通り、フォームから入力されたリクエストデータが保持されています。

ActionFromとDynaActionFormに分かれますが、executeメソッド内でのフォームの値の取得の実装例は以下となります。

ActionFromの場合

ActionFrom内で実装したgetter/setterを用いて、プロパティの取得及び設定が可能となります。

public final class SampleAction extends Action {  
    public ActionForward execute(ActionMapping mapping,
            ActionForm form, 
            HttpServletRequest request,
            HttpServletResponse response) {

        UserActionForm UserActionForm = (UserActionForm)form;
        String id = UserActionForm.getId();
        String pass = UserActionForm.getPass();

        return mapping.findForward("success");  
    }
}

DynaActionFormの場合

プロパティの取得方法について

getメソッドを用いて取得が可能となります。
引数に取得したいプロパティ名を渡す必要があります。

SampleAction.java(一部抜粋)
        // プロパティの取得
        String id = (String) UserActionForm.get("id");
        String pass = (String) UserActionForm.get("pass");

プロパティの設定方法について

setメソッドを用いて設定が可能となります。
引数に設定したいプロパティ名と、設定値を渡す必要があります。

SampleAction.java(一部抜粋)
        // プロパティの設定
        UserActionForm.set("id", "strutsuser");
        UserActionForm.set("pass", "1111");
SampleAction.java(全量)
public final class SampleAction extends Action {  
    public ActionForward execute(ActionMapping mapping,
            ActionForm form, 
            HttpServletRequest request,
            HttpServletResponse response) {

        UserActionForm UserActionForm = (UserActionForm)form;
        // プロパティの取得
        String id = (String) UserActionForm.get("id");
        String pass = (String) UserActionForm.get("pass");
        // プロパティの設定
        UserActionForm.set("id", "strutsuser");
        UserActionForm.set("pass", "1111");

        return mapping.findForward("success");  
    }
}

HttpServletRequestについて

ActionFormで取得できない情報を取得するために使用します。
また、HttpServletRequest#setAttribute()HttpSession#setAttribute()を用いて、Actionクラスで生成したオブジェクトをJSPに渡すことが可能です。

実装例

BeanWriteTag.java
package model;

import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;

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

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class BeanWriteTag extends Action {
    public ActionForward execute(ActionMapping mapping,
            ActionForm form, 
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();
        Date date = new Date();
        ZoneId zone = ZoneId.of("Asia/Tokyo");
        LocalTime time = LocalTime.now(zone);
        request.setAttribute("time", time);
        session.setAttribute("date", date);
        return mapping.findForward("success");
    }
}
BeanWriteTag.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>request#setAttribute():<bean:write name="date" scope="session"/></p>
<p>session#setAttribute():<bean:write name="time" scope="request"/></p>
</body>
</html>

実行結果

スクリーンショット 2020-09-21 16.44.52.png

HttpServletResponse

forwardを行わずに、このクラス内でHTTPレスポンスを行う場合に使用します。

一例ですが、HttpServletResponseインターフェースで定義されているsetHeaderメソッドを用いてforwardを行わずに遷移をすることが可能です。
(executeメソッドの返り値をnullにした場合にはforward処理は呼び出されません。)

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

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class HttpResponse extends Action { 
    public ActionForward execute(ActionMapping mapping,
            ActionForm form, 
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
        response.setHeader("location", "https://struts.apache.org/");
        return null;    
    }
}

4.JSP

4-1.JSPの概要

MVC構成のビューの役割を持っている機能であり、アクションクラスの処理後に起動され、ブラウザの表示内容を返却します。
また、JSPはStrutsが提供しているタグライブラリを利用することができ、Javaコードの代わりに専用のタグライブラリを使用することによって、可読性を高める事が可能です。

4-2.タグライブラリの使用例 - htmlタグライブラリ

参考として、以下のログイン画面を、strutsのタグライブラリを使用する場合しない場合でどう記述が変わるのか確認します。

スクリーンショット 2019-08-27 11.44.41.png

strutsのタグライブラリを利用しない場合

strutsのタグライブラリを利用しない場合は以下のような記述になります。(一部抜粋)

jsp
<h1>ログイン</h1>
<form action="/アプリケーション名/WebContentからのパス" method="post" >
    <input type="text" name="id" class="id" placeholder="ID" autofocus>
    <br>
    <input type="password"  name="password" class="pass" placeholder="PASSWORD">
    <br>
    <input type="submit" class="login" value="ログイン">
</form>

<input>タグを用いてID、パスワード、送信ボタンを作成しています。

strutsのHTMLタグライブラリを利用した場合

次にstrutsのHTMLタグライブラリを利用した場合は以下のような記述になります。(一部抜粋)

struts
<h1>ログイン</h1>
<html:form action="/xxx" focus="id">
    <html:text styleClass="id"  property="id" value = ""/>
    <br>    
    <html:password styleClass="pass" property="pass"  redisplay="false"/>
    <br>
    <html:submit styleClass="login" property="submit" value="ログイン"/>
</html:form>

このように、<input>タグではなく、strutsで提供されているHTMLタグライブラリを用いても、ほぼ同様の記載が可能となります。
今回の場合は、<input>タグで生成された部品が、<html:text><html:password><html:submit>で記載されている事がわかります。

ただし、strutsのHTMLタグライブラリはHTML5の新規タグには対応していません。

一例ですが、上記に挙げたように、HTML5にあるplaceholder属性をstrutsのHTMLタグライブラリで利用する事ができません。
strutsのHTMLタグライブラリを利用して、HTML5と同様の属性を出力したい場合は、jQueryで以下のコードを追加する必要があります。

jQuery
$(function(){
$(".id").attr('placeholder', 'ID');
$(".pass").attr('placeholder', 'PASSWORD');
});

参考(https://log4jk.hatenadiary.org/entry/20130112/p1)

4-3.タグライブラリの種類

strutsで提供されている主なタグライブラリは以下となります。

タグライブラリ名 概要
Beanタグライブラリ Beanに関連する機能を提供
HTMLタグライブラリ HTMLのフォーム要素などを表示する機能を提供
Logicタグライブラリ 条件分岐や繰り返し処理などの論理的な機能を提供
Nestedタグライブラリ ネストしたプロパティにアクセスする機能を提供し、
複数のプロパティにアクセスする際により簡潔に記載が可能となる

各タグライブラリの利用方法

strutsで用意しているタグライブラリを利用するためには、JSPページの先頭でそれぞれのタグライブラリごとにtaglibディレクティブの宣言が必要となります。

<%-- Beanタグライブラリの宣言 --%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%-- HTMLタグライブラリの宣言 --%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%-- Logicタグライブラリの宣言 --%>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%-- Nestedタグライブラリの宣言 --%>
<%@ taglib uri="http://struts.apache.org/tags-nested" prefix="nested" %>

代表的なBeanタグライブラリ

タグ名 概要
<bean:define> 変数を定義する
<bean:write> Beanのプロパティを取得する
<bean:cookie> クッキーを取得する

代表的なHTMLタグライブラリ

タグ名 概要
<html:button> <input type="button">タグを生成する
<html:checkbox> <input type="checkbox">タグを生成する
<html:form> <form>タグを生成する
<html:hidden> <input type="hidden">タグを生成する
<html:image> <input type="image">タグを生成する
<html:link> <a>タグを生成する
<html:text> <input type="text">タグを生成する
<html:password> <input type="password">タグを生成する
<html:submit> <input type="submit">タグを生成する

代表的なLogicタグライブラリ

タグ名 概要
<logic:iterate> 繰り返し処理を行う
<logic:empty> 指定された値が、空をどうかを判定する
<logic:notEmpty> 指定された値が、空でないかを判定する
<logic:equal> 指定された値と、等しいかを判定する
<logic:notEquals> 指定された値と、等しくないかを判定する

カスタムタグの詳細な説明に関しては、以下のサイトが参考になります。
参考(http://struts.wasureppoi.com/taglib/00_taglib.html

5.struts設定ファイル(struts-config.xml)

5-1.struts設定ファイル(struts-config.xml)の概要

リクエストと各コンポーネントの関連付けを行う定義ファイルです。
アクションサーブレットはこの設定ファイルを参照し、リクエストのアクションに一致するアクションパスから、実行するビジネスロジックや、アクションフォーム、バリデーションの有無や遷移先を指定します。

5-2.実行するビジネスロジックや遷移先の確認方法

一例として、以下のjspファイルからリクエストを送った際に、
ビジネスロジックや遷移先がどう決定するかを確認します。

jspファイル
<!-- <form>タグのアクション属性に実行するアクションを指定 -->
<html:form action="/sample" method="post"></html:form>

上記jspのaction="/sample"はリクエストの際に
struts-config.xmlの<action>エレメントに記載された/sampleを参照して
と解釈すれば良いです。
そしたら次は、struts-config.xmlのpath="/sample"と記述されている<action>エレメントに定義されている処理を実行します。

struts-config.xml(一部抜粋)
<form-beans>
 <form-bean
  name="sampleForm"
  type="package.SampleActionForm"/>
</form-beans>  
<action-mappings>
<action
 path="/sample"
 type="package.SampleAction"   
 name="sampleForm"             
 scope="session"               
 validate="true"               
 input="/index.jsp"><forward name="success" path="/WEB-INF/jsp/sample.jsp"/></action>
</action-mappings>

アクションが"/sample"だった場合に実施される処理が以下となります。
①:SampleActionというアクションクラスを実行する
②:SampleActionFormというアクションフォームを利用する
③:②のアクションフォームを保持するスコープがsessionである
④:入力チェックを実施する
⑤:④の入力チェックでエラーだった場合にindex.jspに遷移する
⑥:①のアクションクラスの戻り値が"success"の場合に"/WEB-INF/jsp/sample.jsp"に遷移する

5-3.エレメントの概要

設定ファイルに記述されている、各エレメントの概要は以下となります。

<action>エレメントの主な属性

属性 説明
path jspのアクションとStrutsの設定ファイルを結びつける名称
type アクションに対応するアクションクラスのクラス名(完全修飾名)
name アクションに対応するアクションフォーム名(アクションフォーム名は<form-beans>エレメントに記載)
scope アクションフォームを格納するスコープをrequestまたはsessionで指定。(デフォルトはsession)
sessionの場合、HttpSession#setAttribute()でアクションフォームのインスタンスがセッションに保持される。
requestの場合、HttpServletRequest#setAttribute()でアクションフォームのインスタンスがリクエストに保持される。
parameter 汎用目的で使用されるActionのパラメータ
アクションクラスで固有のパラメータを利用するために定義する。(ActionMapping#getParameter()で取得可能)
validate バリデーションを行う場合はtrueを指定。行わない場合はfalseを指定
input Validation処理にて入力値エラーが発生した場合の遷移先を指定

scopeとは スコープとは、インスタンスを保存できる領域です。
 各スコープごとにインスタンスの保存期間が異なり、
 リクエストスコープに関してはリクエストごとに生成され、レスポンスが返却されるまで有効となります。
 セッションスコープに関しては複数のリクエストをまたいでインスタンスが有効となり、ブラウザを削除するか明示的に削除するまで継続されます。
 strutsのスコープに関して、以下のサイトが参考となります。
 Struts1のアクションフォームの寿命はいつまでなのか調べる

forwardとは forwardとは他のリソース(「HTML」「JSP」「Servlet」)に処理を転送する機能です。

<form-beans>エレメントの主な属性

属性 説明
name アクションフォームの名前を指定
<action>エレメントのname属性のアクションフォーム名と一致
type アクションフォーム名のクラス名(完全修飾名)

<forward>エレメントの主な属性

属性 説明
name アクションクラスのexecuteメソッドの戻り値と結びつける名称
forward 遷移先のjspファイル名

<action><form-beans><forward>以外のエレメントの概要は以下となります。

エレメント 概要
<data-sources> データソースの定義
<global-exceptions> 共通の例外処理設定
<global-forwards> 共通のアクションフォワード設定
<controller> コントローラの定義
<message-resources> メッセージリソースの定義
<plug-in> プラグインの定義

6.web.xml

6-1.web.xmlの概要

web.xmlはServletコンテナがWebアプリケーションの動作を制御するための設定ファイルです。
Struts固有のファイルではありませんが、今回はstrutsに関わるweb.xmlの記述について説明していきます。

6-2.リクエストとアクションサーブレットの関係

リクエストから、実行するアクションを指定するまでの流れを追って、strutsにおけるweb.xmlの役割をみていきたいと思います。

jspファイル(再掲)
<!-- <form>タグのアクション属性に実行するアクションを指定 -->
<html:form action="/sample" method="post"></html:form>

上記のように、jspファイルに<html:form>タグを記述すると、フォワード時に生成されるHTMLファイルのformタグは以下となり、action属性に拡張子「.do」が付与されていることが分かります。

jspファイル(再掲)
<form name="アクションフォーム名" method="post" action="/コンテキストパス/sample.do"></form>

↓ リクエスト時のURL
スクリーンショット 2019-08-17 18.57.33.png

上記のactionでサーバ側にリクエストを送信した際、web.xmlで定義されている設定ファイルに基づいて、実行するアクションが決定します。
strutsのweb.xmlは通常、以下のように定義されています。

web.xml
<servlet>
 <servlet-name>action</servlet-name>
 <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml</param-value> <!-- (2) -->
  </init-param>
<!-- 中略 -->
</servlet>
<!-- 中略 -->
<servlet-mapping>
 <servlet-name>action</servlet-name>
  <url-pattern>*.do</url-pattern> <!-- (1) -->
 </servlet-mapping>

(1)web.xmlに記載されているURLパターンから、拡張子「.do」のリクエストがActionServlet
(org.apache.struts.action.ActionServlet)
に渡されるということがわかります。

(2)<param-value>にActionServletの制御を記述した設定ファイルのパスが記載されています。
今回の場合、struts-config.xmlがリクエストとアクションの関連付けを行なっており、
リクエストに指定されたパスhttp://ホスト名/コンテキスト名/xxx.doxxxstruts-config.xml<action>エレメントのpath属性が一致したアクションを実行しています。

(2)の説明から分かるように、設定ファイルの宣言は<param-value>で行なっているので、
設定ファイルを追加したい場合は、<param-value>内に、ファイル名を追加で記述すれば良いです。

web.xml(設定ファイルを追加する場合)
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml,
                /WEB-INF/struts-config-xxx.xml,
                /WEB-INF/struts-config-xxx.xml,
                /WEB-INF/struts-config-xxx.xml,
                .
                .
                .
   </param-value>

7.メッセージリソースファイル

7-1.メッセージリソースファイルの概要

メッセージリソースファイルはstruts内で利用されるメッセージを管理するためのファイルです。

7-2.メッセージリソースファイルの定義方法

struts-config.xml内の<message-resources>タグのparameter属性に\WEB-INF\classesディレクトリ以降の配置ディレクトリを指定します。

struts-config.xml
<message-resources parameter="MessageResources"/>

7-3.メッセージリソースファイルの定義内容

キーとメッセージで管理するメッセージを記載します。キーとメッセージの間は「=」で区切ります。

MessageResources_jp.properties
# -- standard errors --
errors.header=<div class="err-font" >
errors.prefix=
errors.suffix=<br />
errors.footer=</div >
# -- validator --
# --中略 --
errors.required={0} を入力してください。
# --中略 --
field.id=ログインID
field.pass=パスワード
errors.login=パスワードに誤りがあります

7-4.定義したメッセージの表示方法

メッセージリソースファイルで定義したメッセージを出力する一例として以下が挙げられます。

  • <bean:message>タグのkey属性に表示するメッセージのメッセージ・リソースファイルのkeyを定義して出力
  • ActionMessageオブジェクトの引数にメッセージ・リソースファイルのkey属性を指定して<html:errors>タグ<html:message>タグでメッセージを出力

7-5.メッセージリソースファイルの日本語化について

メッセージリソースファイルは日本語をUnicodeでエンコードする必要があり、日本語をそのまま定義しても文字化けします。

日本語をUnicodeでエンコードするにはnative2asciiコマンドを利用しする必要があります。

native2asciiコマンド

native2ascii [ -encoding エンコード方式 ] [ -reverse ] 変換前ファイル 変換後ファイル
-encoding:変換前ファイルのエンコード方式を指定。
-reverse:Unicodeでエンコードされたファイルを元に戻す。

MessageResources_jp.properties(変換前)
field.id=ログインID
MessageResources_jp.properties(変換後)
field.id=\u30ED\u30B0\u30A4\u30F3ID

その他のStruts1の機能について

例外処理について

strutsにおいて共通的な例外処理を定義したい場合は、struts-config.xmlの<global-exceptions>タグを用います。
また、処理する例外を複数定義したい場合は、 <exception>タグを複数記載する必要があります。

struts-config.xml
<global-exceptions>
   <exception
     type="java.lang.NumberFormatException"
     key="errors.numberformat"
     handler="package.exception.ExceptionHandler"
     path="/jsp/error.jsp" />
</global-exceptions>

<exception>エレメントの属性の概要は以下となります。

属性 概要
type 例外クラス名
key 例外発生時に表示するエラーメッセージのメッセージkey
handler 例外発生時に実行するクラス
path 例外発生時の遷移先のjspファイル名

二度押しチェックについて

Strutsでは同じ処理が複数回実行されることを防止するため、トランザクショントークンを用いたトークンチェックの機能が提供されています。
流れとしてはざっくり以下となります。

  • アクションクラスでトークンを生成
  • 生成したトークンはsessionスコープに格納すると共にHTMLのhiddenタグとしてブラウザ側に返却
  • 次に呼び出されたアクションクラスで、ブラウザとsessionスコープのトークンを比較 スクリーンショット 2020-03-29 19.09.15.png

トークンの生成

トークンの生成はorg.apache.struts.action.ActionクラスのsaveTokenメソッドを利用します。

protected void saveToken(HttpServletRquest req)

saveTokenメソッドで生成されたトークンはsessionスコープにorg.apache.struts.taglib.html.TOKENというキー名で登録します。
また、sessionスコープにトークンが登録された場合は、出力されるhtmlには自動的にhiddenタグが挿入され、トークンがセットされます。

トークンの比較

リクエストとsessionスコープのトークンの値を比較するにはorg.apache.struts.action.ActionクラスのisTokenValidメソッドを利用します。

protected boolean isTokenValid(HttpServletRquest req, boolean reset)

以下の条件に一致する場合はfalseを返却します。

  • リクエストとsessionスコープのトークンの値が異なる
  • リクエストにトークンが存在しない
  • sessionスコープにトークンが存在しない

トークンの削除

saveTokenメソッドでsessionスコープに格納されたトークンを削除するには、resetTokenメソッドを利用します。

protected void resetToken(HttpServletRquest req)

Struts1の環境構築

Struts1の環境構築の方法について、今回は自力で構築する方法を紹介していきます。
なお、環境構築の手順は以下のサイトを参考にしました。
Struts1.3.10でWebアプリケーション作成

また、今回は触れませんが、Mavenを利用して環境構築をする手順は以下が参考になります。
[Java]Eclipseでstruts1.3を開発するための環境構築手順

Eclipseプロジェクトの作成

プロジェクト・エクスプローラを右クリック > 新規 > 動的Webプロジェクト を選択
スクリーンショット 2020-08-23 12.06.17.png

プロジェクト名を入力し、「次へ」を押下
スクリーンショット 2020-08-23 12.07.06.png

そのまま「次へ」を押下
スクリーンショット 2020-08-23 12.56.01.png

「web.xml デプロイメント記述子の生成」にチェックを入れ、「完了」を押下
スクリーンショット 2020-08-23 12.56.19.png

Eclipseプロジェクトが作成作成されていることを確認
スクリーンショット 2020-08-23 12.57.03.png

Struts1のダウンロード

以下のサイトから、「struts-1.3.10-apps.zip」を選択してダウンロード
https://struts.apache.org/download.cgi
スクリーンショット 2020-08-23 13.01.29.png

ダウンロードした「struts-1.3.10-apps.zip」から、「struts-examples-1.3.10.war」ファイルをzipファイルに変換
スクリーンショット 2020-08-23 13.03.21.png

「struts-examples-1.3.10.zip」ファイルを解凍する
スクリーンショット 2020-08-23 13.03.41.png

解凍したファイルから、以下のファイルを今回作成したEclipseプロジェクトにコピーする

  • pages
  • WEB-INF
  • index.jsp

スクリーンショット 2020-08-23 13.04.46.png

以下のようなフォルダ構成になっていればOK
スクリーンショット 2020-08-23 13.38.44.png

サーバーの追加

サーバタブで右クリック > 新規 > サーバー
スクリーンショット 2020-08-23 13.39.24.png

サーバー名を入力して、「次へ」を押下
スクリーンショット 2020-08-23 13.39.52.png

今回作成したEclipseプロジェクトを追加して、「完了」を押下
スクリーンショット 2020-08-23 13.40.13.png

アプリケーションの実行

追加したサーバーを選択して「開始」を押下
スクリーンショット 2020-08-23 13.40.55.png

以下のURLにアクセスして、Welcome画面が表示されることを確認
http://localhost:8080/プロジェクト名
スクリーンショット 2020-09-20 13.09.59.png

これでStruts1の環境構築は完了となります!!

ログイン画面作成して動作を確認

実装する機能

ログイン画面

・ユーザIDとパスワードを入力して、ログインを実施
・パスワードは全ユーザ共通で「1111」
・入力チェックを行い、問題があればログイン画面にエラーメッセージを表示

スクリーンショット 2019-09-12 18.58.08.png

実行結果画面

・「ログインに成功しました」というメッセージと、ログインしたユーザIDを表示

スクリーンショット 2019-09-12 18.58.42.png

ログアウト画面

・セッションを破棄して、ログアウトしましたのメッセージを表示

スクリーンショット 2019-09-12 18.59.02.png

ディレクトリ構成

struts
├── WebContent
│   ├── META-INF
│   ├── WEB-INF
│   │   ├── classes
│   │   │   └── MessageResources.properties
│   │   ├── jsp
│   │   │   ├── loginResult.jsp
│   │   │   └── logout.jsp
│   │   ├── src
│   │   │   └── java
│   │   │       └── MessageResources.properties
│   │   ├── struts-config.xml
│   │   ├── validation.xml
│   │   └── web.xml
│   ├── css
│   │   └── style.css
│   └── index.jsp  
└── src
    └── model
        ├── LoginAction.java
        ├── LogoutAction.java
        └── UserActionForm.java

jsp

ログイン画面

index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%> 
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<!DOCTYPE html>
<html>
<head>
<title>ログイン</title>
<link rel="stylesheet" type="text/css" href="<html:rewrite page="/css/style.css"/>" >
</head>
<body>
<html:errors />
<div class="main-div">
<h1>ログイン</h1>
<html:form action="/loginResult" focus="id">
    <html:text styleClass="id"  property="id" value = ""/>
    <br>    
    <html:password styleClass="pass" property="pass"  redisplay="false"/>
    <br>
    <html:submit styleClass="login" property="submit" value="ログイン"/>
</html:form>
</div>
</body>
</html>

ログイン実行結果画面

loginResult.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>

<logic:notPresent name="id" scope="session">
    <logic:redirect forward="fail"/>
</logic:notPresent>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>メイン</title>
<link rel="stylesheet" type="text/css" href="<html:rewrite page="/css/style.css"/>" >
</head>
<body>
<div class="main-div">
<h1>ログイン結果</h1>
    <p>ログインに成功しました</p>
    <p>ユーザID:<bean:write name="id" scope="session"/></p>
    <html:link action="/logout">ログアウト</html:link>
</div>
</body>
</html>

ログアウト画面

logout.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ログアウト</title>
<link rel="stylesheet" type="text/css" href="<html:rewrite page="/css/style.css"/>" >
</head>
<body>
<div class="main-div">
<h1>ログアウト</h1>
<p>ログアウトしました</p>
<a href="/struts/">トップへ</a>
</div>
</body>
</html>

アクションクラス

LoginAction.java
package model;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.*;

public final class LoginAction extends Action { 
    public ActionForward execute(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) {
        //セッション情報の取得
        HttpSession session = request.getSession();  
     //(1)ActionMessageオブジェクトの生成
        ActionMessages errors = new ActionMessages(); 
     
        UserActionForm UserActionForm = (UserActionForm)form;
        String id = UserActionForm.getId();
        String pass = UserActionForm.getPass();

        if(!(pass.equals("1111"))) { 
       //(2)ActionMessageオブジェクトの登録
            errors.add(ActionMessages.GLOBAL_MESSAGE,
                new ActionMessage("errors.login"));
       //(3)ActionMessagesオブジェクトをrequestスコープに登録
            saveErrors(request, errors);
            return (mapping.findForward("fail"));
        } else {
            session.setAttribute("id", id);
            return mapping.findForward("success");
        }
    }
}

(1)ActionMessageオブジェクトを生成します
(2)ActionMessage#addメソッドを使用し、ActionMessageオブジェクトを登録します。第一引数にはActionMessages.GLOBAL_MESSAG、第二引数に登録するActionMessageオブジェクトを指定します。ActionMessageオブジェクトのコンストラクタの引数にメッセージ・リソースファイルのキーと可変置き換え文字を指定します。
(3)メッセージをJSPで使用するためにsaveErrorsメソッドを使用して、ActionMessagesオブジェクトをrequestスコープに登録します。

LogoutAction.java
package model;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.*;

public final class LogoutAction extends Action {  
    public ActionForward execute(ActionMapping mapping,
            ActionForm form, 
            HttpServletRequest request,
            HttpServletResponse response) {

        HttpSession session = request.getSession();
       //(1)セッションの削除
        session.invalidate();

        return mapping.findForward("success");

    }
}

(1)session.invalidate();でセッションの削除を実施し、画面遷移をしています。

アクションフォーム

UserActionForm
package model;
import org.apache.struts.action.*;
import org.apache.struts.validator.*;

public class UserActionForm  extends ValidatorForm {

      private String id; // ユーザー名
      private String pass; // パスワード


      public UserActionForm() {}

      public UserActionForm(String id, String pass) {
        this.id = id;
        this.pass = pass;
      }
      public String getId() {
        return id;
      }
      public void setId(String id) {
            this.id = id;
          }
      public String getPass() {
        return pass;
      }
      public void setPass(String pass) {
            this.pass = pass;
          }
}

設定ファイル(strtus-config.xml)

struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
    <form-beans>
        <form-bean
            name="UserActionForm"
            type="model.UserActionForm"/>
    </form-beans>  
    <global-forwards>
        <forward name="fail" path="/index.jsp"/>
    </global-forwards>
    <action-mappings>
        <action
            path="/Welcome"
            forward="/pages/Welcome.jsp"/>        
        <action
            path="/loginResult"
            type="model.LoginAction"
            name="UserActionForm"
            scope="session"
            validate="true"
            input="/index.jsp">
        <forward name="success" path="/WEB-INF/jsp/loginResult.jsp"/>
        <forward name="fail" path="/index.jsp"/>
        </action>   
        <action
            path="/logout"
            type="model.LogoutAction">
        <forward name="success" path="/WEB-INF/jsp/logout.jsp"/>    
        </action> 
    </action-mappings>        
    <message-resources parameter="resources.application"/>
    <message-resources parameter="MessageResources"/>
  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property
        property="pathnames"
        value="/org/apache/struts/validator/validator-rules.xml,
               /WEB-INF/validation.xml"/>
  </plug-in>
</struts-config>

Validation.xml

validation.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- 中略 -->
<!DOCTYPE form-validation PUBLIC
     "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN"
     "http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">
<form-validation>
<!-- 中略 -->
    <formset>
        <form name="UserActionForm">
            <field
                property="id"
                depends="required">
                  <arg key="field.id" />
            </field>
            <field
                property="pass"
                depends="required">
                  <arg key="field.pass" />
            </field>
        </form>
    </formset>
    <formset language="fr">
        <constant>
            <constant-name>postalCode</constant-name>
            <constant-value>^[0-9a-zA-Z]*$</constant-value>
        </constant>
        <form name="logonForm">
            <field
                property="username"
                depends="required">
                    <arg key="logonForm.username"/>
            </field>
            <field
                property="password"
                depends="required,mask">
                    <arg key="logonForm.password"/>
                    <var>
                        <var-name>mask</var-name>
                        <var-value>^[0-9a-zA-Z]*$</var-value>
                    </var>
            </field>
        </form>
   </formset>
</form-validation>

メッセージ・リソースファイル

MessageResources_jp.properties
# -- standard errors --
errors.header=<div class="err-font" >
errors.prefix=
errors.suffix=<br />
errors.footer=</div >
# -- validator --
# --中略 --
errors.range={0} is not in the range {1} through {2}.
errors.required={0} を入力してください。
# --中略 --
field.id=ログインID
field.pass=パスワード
errors.login=パスワードに誤りがあります

特に勉強になった書籍、サイト

参考文献と重複しますが、特に勉強になった書籍とサイトを記載します。
この記事を見た後にもっと詳しく勉強したい方は、以下の書籍とWebサイトを参考にしてください。

書籍

Struts逆引き大全333の極意
https://www.amazon.co.jp/Struts%E9%80%86%E5%BC%95%E3%81%8D%E5%A4%A7%E5%85%A8333%E3%81%AE%E6%A5%B5%E6%84%8F-%E5%9D%82%E7%94%B0-%E5%81%A5%E4%BA%8C/dp/4798007358

webサイト

忘れっぽいエンジニアのJakarta Struts リファレンス
http://struts.wasureppoi.com
Webアプリ開発エンジニアのための技術情報サイト[テックスコア]
https://www.techscore.com/tech/Java/ApacheJakarta/Struts/index/
フリー教材/Struts1日入門
https://www.knowledge-ex.jp/opendoc/struts.html
株式会社アークシステム Strutsをはじめとするオープンソースプロダクト情報
https://www.arksystems.co.jp/closeupit/struts/

参考文献

書籍 

Struts逆引き大全333の極意
https://www.amazon.co.jp/Struts%E9%80%86%E5%BC%95%E3%81%8D%E5%A4%A7%E5%85%A8333%E3%81%AE%E6%A5%B5%E6%84%8F-%E5%9D%82%E7%94%B0-%E5%81%A5%E4%BA%8C/dp/4798007358

スッキリわかるサーブレット&JSP入門
https://book.impress.co.jp/books/1112101008

Webサイト

忘れっぽいエンジニアのJakarta Struts リファレンス
http://struts.wasureppoi.com

Webアプリ開発エンジニアのための技術情報サイト[テックスコア]
https://www.techscore.com/tech/Java/ApacheJakarta/Struts/index/

フリー教材/Struts1日入門
https://www.knowledge-ex.jp/opendoc/struts.html

株式会社アークシステム Strutsをはじめとするオープンソースプロダクト情報
https://www.arksystems.co.jp/closeupit/struts/

@IT Strutsを使うWebアプリケーション構築術
https://www.atmarkit.co.jp/ait/series/2515/

struts - 機能リファレンス
http://pgbox.grush.jp/ref/java/struts/refs/

SEさんの外部記憶装置 まだまだ苦戦
https://ameblo.jp/system-eng1neer/entry-10385236995.html

世界」旅と子育てとガジェットを愛するエンジニアリングマネージャーのブログ Struts1.3.5でValidatorを使う
https://daipresents.com/2008/struts135validator/

雑廉堂の雑記帳 いまさらながらStruts – ActionMessages
https://www.rough-and-cheap.jp/java/struts_meno_actionmessages/

ウィリアムのいたずらの開発?日記 TomcatからStrutsの流れを確認する 
https://blog.goo.ne.jp/xmldtp/e/8da26250101a830f58e0896d0c767333

IT技術三昧 java+struts開発でメッセージ・リソースファイルで日本語を利用(native2asciiコマンド)
https://www.zanmai.net/blog/data/83.html

log4jk Strutsのカスタムタグで任意の属性を出力したい
https://log4jk.hatenadiary.org/entry/20130112/p1

Struts 1.3インストールガイド
http://struts.nomaki.jp/struts1.3/install/document.html

liliel_OvO’s blog Struts1.3.10でWebアプリケーション作成
https://liliel.hateblo.jp/entry/2018/09/05/145011

61
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
61
Help us understand the problem. What is going on with this article?