142
136

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Struts1.3.10を勉強したのでまとめてみた

Last updated at Posted at 2019-09-09

はじめに

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

strutsの特徴

1.リクエストのハンドリングをstruts-config.xmlで管理

strutsではリスエストに対応する処理をstruts-config.xmlと呼ばれる設定ファイルで管理しています。
リクエストが投げられた際に呼び出されるビジネスロジックや、遷移先の画面を特定するには、struts-config.xmlの内容を理解することが重要です。

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

jspファイル struts-config.xml
<form>タグのアクション属性にAction名を定義 リクエスト時に<action>タグのpath属性と一致するアクションを実行
スクリーンショット 2019-08-27 23.25.43.png

2.validationの提供

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

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

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

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

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

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

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

ブラウザから送信されたトークンとsessionスコープに格納されたトークンを比較することで処理を継続すべきか判定することができ、同じサブミットボタンを二重クリックした場合や、戻るボタンを利用した不正な画面遷移の場合に、エラーとすることが可能です。

不正な画面操作の一例

以下、1-3の流れで遷移を行う機能において、3. 登録完了画面のタイミングでブラウザの戻るボタンを押下し、確認画面へ戻った後に再度登録ボタンを押下する。

  1. 入力画面
  2. 確認画面
  3. 登録完了画面 ←ここでブラウザの戻るボタン押下

このようなケースにおいて、トークンチェックの機能の仕組みを用いることで、確認画面から登録ボタン押下時に不正遷移と判断し、エラー画面に遷移するように実装することが可能です。
3月-29-2020 18-25-08.gif

5.例外処理機能の提供

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

strutsの処理の流れ

strutsの構成・処理の流れは下図となります。2

スクリーンショット 2019-08-18 12.35.30.png

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

  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です。

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

  • org.apache.struts.action.ActionFormを継承したクラスを作成
  • フィールドおよびgetter/setterメソッドを実装

ログイン画面でユーザIDとパスワードを入力するフォームが存在する場合の実装例は以下の通りです。

ActionForm.java
import org.apache.struts.action.ActionForm;

public class UserActionForm  extends ActionForm {

  private String 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.action.ActionForm;
+ import org.apache.struts.validator.ValidatorForm;
- public class UserActionForm  extends ActionForm {
+ public class SampleActionForm extends ValidatorForm {
  private String 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:struts-config.xmlorg.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は半角英数字で入力してくださいというメッセージが出力されるようになります。

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

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

<form>

入力チェック対象のBeanを<form>タグで定義します。

  • name属性:アクションフォームの名前
<form name="SampleActionForm">

<field>

各プロパティに対して実施する入力チェックを<field>タグで定義します。

  • property属性:入力チェックを実施するプロパティ名
  • depends属性:適用する入力チェック名(複数指定する場合はカンマ区切り)
<field property="id" depends="required,mask">

上記定義の場合、idというプロパティに対して、次の2つの入力チェックを実施します。

  • required:必須チェック
  • mask:指定のマスクパターンに合致しているかチェック

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

<msg>

入力チェックが失敗した場合に生成するエラーメッセージを<msg>タグで定義をします。

  • name属性:エラーメッセージ表示対象の入力チェックルール名
    • <field>タグのdepends属性で指定されている値から1つ指定する
  • key属性:表示するメッセージのキー
    • キーに紐づくメッセージはメッセージリソースファイルで定義する必要がある
<msg name="mask" key="field.invalidate" />

<arg>

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

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

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

<var>

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

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

検証ルール名 検証内容 パラメーター<var-name> 指定値<var-value>
required 必須入力チェック
requiredif 条件付きのフィールド必須入力チェック field[数値] 依存するフィールド名
requiredif 条件付きのフィールド必須入力チェック fieldTest[数値] 依存するフィールドに対する条件(NULL or NOTNULL or EQUAL)
requiredif 条件付きのフィールド必須入力チェック fieldValue[数値] 依存するフィールドの比較値(fieldTestがEQUALの場合のみ指定する)
requiredif 条件付きのフィールド必須入力チェック fieldIndexed[数値] 依存するフィールドがindexed形式かどうかを指定する (true or false[default])
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 同名のタグと同等の機能を果たす

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.アクションクラスの概要

アクションクラスはMVC構成のモデルの役割を持つ機能です。

アクションフォームにリクエストが設定された後に実行されるクラスであり、ビジネスロジックを実装するクラスです。

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

  • org.apache.struts.action.Actionを継承
  • Action#executeをオーバーライドして、ビジネスロジックを記述
  • Action#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.xmlpath/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.アクションフォームで説明した通り、フォームから入力されたリクエストデータが保持されています。

ActionFormDynaActionFormに分かれますが、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について

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>

実行結果

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の概要

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でplaceholder属性を追加する方法があります。

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

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> 指定された値と、等しくないかを判定する

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.xmlpath="/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"だった場合に実施される処理が以下となります。

  1. SampleActionというアクションクラスを実行する
  2. SampleActionFormというアクションフォームを利用する
  3. 2.のアクションフォームを保持するスコープがsessionである
  4. 入力チェックを実施する
  5. 4.の入力チェックでエラーだった場合にindex.jspに遷移する
  6. アクションクラスの戻り値が"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処理にて入力値エラーが発生した場合の遷移先を指定

<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>

そのため、リクエストを送信した際のパスは/sample.doとなります。

リクエスト送信時、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

例外処理について

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プロジェクト を選択

プロジェクト名を入力し、「次へ」を押下

そのまま「次へ」を押下

「web.xml デプロイメント記述子の生成」にチェックを入れ、「完了」を押下

Eclipseプロジェクトが作成作成されていることを確認

Struts1のダウンロード

このサイトから、「struts-1.3.10-apps.zip」を選択してダウンロード

ダウンロードした「struts-1.3.10-apps.zip」から、「struts-examples-1.3.10.war」ファイルをzipファイルに変換

「struts-examples-1.3.10.zip」ファイルを解凍する

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

  • pages
  • WEB-INF
  • index.jsp

以下のようなフォルダ構成になっていればOK

サーバーの追加

サーバタブで右クリック > 新規 > サーバー を選択

サーバー名を入力して、「次へ」を押下

今回作成したEclipseプロジェクトを追加して、「完了」を押下

アプリケーションの実行

追加したサーバーを選択して「開始」を押下

http://localhost:8080/プロジェクト名にアクセスして、Welcome画面が表示されることを確認

これでStruts1の環境構築は完了です!!

参考文献

書籍

【特におすすめ】Webサイト

Webサイト

  1. Apache Struts 1 End-Of-Life (EOL) Press Release

  2. Struts逆引き大全333の極意を元に作成

142
136
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
142
136

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?