はじめに
2019年の時点でstruts1を用いたWebアプリケーションを新規開発をする事はほとんどないと思いますが、それでもstruts1で構築され、現在でも動いているWebアプリケーションはまだまだ存在すると思います。
今後もプロジェクトで関わる可能性が大いにあるフレームワークですが、すでに枯れた技術でもあり、ほかの技術に比べて、学習できる書籍やサイトがそこまで多くありません。
そこで今回、struts1についてこれまで学習したことをまとめてみました。
自分が新人で初めてstruts1を勉強した時に、 この資料があれば嬉しかったなというものを作ろう! という思いでこの記事を書きました。
今後、少しでも多くの方がこの記事を読んで、struts1の概要を理解してもらえたら幸いです。
本記事が向いている人
- struts1についての知識がないが、一通り概要を理解したい方
ゴール
- struts1の構成や特徴などの大枠を理解できる状態
- この記事を足がかりに、struts1の学習がスムーズに進められる状態
strutsについて
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属性と一致するアクションを実行 |
2.validationの提供
Strutsでは入力データの必須チェックや文字数チェックの処理などのvalidationの機能が提供されており、入力チェック用のプログラムを実装する手間が省けます。
以下のログイン画面の入力チェックも、strutsが提供しているvalidation.xmlでパラメータの検証ルールを定義し、メッセージ・リソースファイルを用いてエラーの際に表示するメッセージを設定する事で実装が可能となります。
3.タグライブラリの提供
Strutsは<logic>タグや<bean>タグなど独自のタグライブラリが用意されており、Javaコードの代わりに専用タグライブラリを使用することで、画面(JSP)の可読性の向上や記述レベルの統一が可能となります。
4.二度押し防止機能(トークンチェック)の提供
Strutsでは同じ処理が複数回実行されることを防止するため、トランザクショントークンを用いたトークンチェックの機能が提供されています。
ブラウザから送信されたトークンとsessionスコープに格納されたトークンを比較することで処理を継続すべきか判定することができ、同じサブミットボタンを二重クリックした場合や、戻るボタンを利用した不正な画面遷移の場合に、エラーとすることが可能です。
不正な画面操作の一例
以下、1-3の流れで遷移を行う機能において、3. 登録完了画面のタイミングでブラウザの戻るボタンを押下し、確認画面へ戻った後に再度登録ボタンを押下する。
- 入力画面
- 確認画面
- 登録完了画面 ←ここでブラウザの戻るボタン押下
このようなケースにおいて、トークンチェックの機能の仕組みを用いることで、確認画面から登録ボタン押下時に不正遷移と判断し、エラー画面に遷移するように実装することが可能です。

5.例外処理機能の提供
strutsでは例外発生時に、struts-config.xmlの<global-exceptions>タグを用いて、例外が発生した際の処理を定義することができます。
そのため、標準のエラー画面(404エラーなど)が表示されることなく例外処理のハンドリングをすることが可能です。
strutsの処理の流れ
strutsの構成・処理の流れは下図となります。2
図の処理の流れをざっくり説明すると以下となります。
- クライアントからのリクエストを送信
- アクションサーブレットが設定ファイルをもとに実行する処理を特定
- クライアントから送信された情報をアクションフォームに設定
- アクションクラスの実行
- アクションクラスの実行結果をもとに遷移先を決定
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とパスワードを入力するフォームが存在する場合の実装例は以下の通りです。
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は以下のように記述します。
<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の機能を追加することができます。
- 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.xmlにorg.apache.struts.validator.ValidatorPlugInを追加する
アクションフォームだけでなくstruts-config.xmlの設定も変更が必要となります。
struts-config.xmlの<plug-in>タグに以下の定義を追加することで、Validationの機能が追加されます。
<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属性には入力値チェックに引っかかった場合の遷移先を定義する必要があります。
<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
などを定義します。
<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>
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 | 正当なクレジットカード番号のフォーマットかをチェック | – | – |
| 正当なメールアドレスのフォーマットかをチェック | – | – | |
| 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に含まれています。
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
<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の中身と各タグの説明
<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に遷移することがわかります。
//Actionクラス内でfindForwardの引数に"success"を指定して返却
return mapping.findForward("success");
<!-- 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属性の値を出力する実装例は以下となります。
<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>
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.アクションフォームで説明した通り、フォームから入力されたリクエストデータが保持されています。
ActionFormと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メソッドを用いて取得が可能となります。
引数に取得したいプロパティ名を渡す必要があります。
// プロパティの取得
String id = (String) UserActionForm.get("id");
String pass = (String) UserActionForm.get("pass");
プロパティの設定方法について
setメソッドを用いて設定が可能となります。
引数に設定したいプロパティ名と、設定値を渡す必要があります。
// プロパティの設定
UserActionForm.set("id", "strutsuser");
UserActionForm.set("pass", "1111");
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に渡すことが可能です。
実装例
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");
}
}
<%@ 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のタグライブラリを使用する場合、しない場合でどう記述が変わるのか確認します。
strutsのタグライブラリを利用しない場合
strutsのタグライブラリを利用しない場合は以下のような記述になります。(一部抜粋)
<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タグライブラリを利用した場合は以下のような記述になります。(一部抜粋)
<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属性を追加する方法があります。
$(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ファイルからリクエストを送った際に、ビジネスロジックや遷移先がどう決定するかを確認します。
<!-- <form>タグのアクション属性に実行するアクションを指定 -->
<html:form action="/sample" method="post"></html:form>
上記jspのaction="/sample"はリクエストの際に
struts-config.xmlの<action>タグに記載された/sampleを参照して
と解釈すれば良いです。
次に、struts-config.xmlのpath="/sample"と記述されている<action>タグに定義されている処理を実行します。
<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というアクションフォームを利用する
- 2.のアクションフォームを保持するスコープがsessionである
- 入力チェックを実施する
- 4.の入力チェックでエラーだった場合に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処理にて入力値エラーが発生した場合の遷移先を指定 |
<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の役割をみていきたいと思います。
<!-- <form>タグのアクション属性に実行するアクションを指定 -->
<html:form action="/sample" method="post"></html:form>
上記のように、jspファイルに<html:form>タグを記述すると、フォワード時に生成されるHTMLファイルのformタグは以下となり、action属性に拡張子「.do」が付与されていることが分かります。
<form name="アクションフォーム名" method="post" action="/コンテキストパス/sample.do"></form>
そのため、リクエストを送信した際のパスは/sample.doとなります。
リクエスト送信時、web.xmlで定義されている設定ファイルに基づいて、実行するアクションが決定します。
strutsの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.doのxxxとstruts-config.xmlの<action>タグのpath属性が一致したアクションを実行しています。
(2)の説明から分かるように、設定ファイルの宣言は<param-value>で行なっているので、設定ファイルを追加したい場合は、<param-value>内に、ファイル名を追加で記述すれば良いです。
<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ディレクトリ以降の配置ディレクトリを指定します。
<message-resources parameter="MessageResources"/>
7-3.メッセージリソースファイルの定義内容
キーとメッセージで管理するメッセージを記載します。キーとメッセージの間は「=」で区切ります。
# -- 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でエンコードされたファイルを元に戻す。
変換例
field.id=ログインID
field.id=\u30ED\u30B0\u30A4\u30F3ID
例外処理について
strutsにおいて共通的な例外処理を定義したい場合は、struts-config.xmlの<global-exceptions>タグを用います。
また、処理する例外を複数定義したい場合は、 <exception>タグを複数記載する必要があります。
<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スコープのトークンを比較
トークンの生成
トークンの生成は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 デプロイメント記述子の生成」にチェックを入れ、「完了」を押下

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
サーバーの追加
今回作成したEclipseプロジェクトを追加して、「完了」を押下

アプリケーションの実行
http://localhost:8080/プロジェクト名にアクセスして、Welcome画面が表示されることを確認
これでStruts1の環境構築は完了です!!











