strutsの使い方メモ(1.2系)
LastUpdate : 09/04/25
自分用に、strutsのまとめを書いておこうと思い、このページを作成しました。丁寧な解説は皆無ですw
実行結果と、ソースしかのっけてませんが、まぁ、ソースだけみればなんとなくわかるんじゃないかなぁ〜と思います。
※注意
内容について、大してチェックしてないので、間違ってる点があるかもしれません・・・。
間違っていたら、ごめんなさいtt
私は、主に以下の本を参考に勉強しました。
『プログラミング Jakarta Struts』(オライリー・ジャパン)
『StrutsによるWebアプリケーションスーパーサンプル 第2版』(ソフトバンク クリエイティブ)
このページでのstruts対象バージョンは1.2.9を基本としています。
前提とする環境
jsp内で画面遷移させる方法(画面のredirectとforward)
各種入力フォームの基本的な使い方
入力フォームの初期値をActionBean内で指定する(+Iteratorタグの使い方
DynaActionFormの使い方
動的に増える入力フォームの扱い方
一つのフォームに複数のsubmitボタンがある場合(LookupDispatchAction)
tokenを使う(二度押し防止)
単純に画面遷移させる方法
一つのフォームに複数のsubmitボタンがある場合(DispatchAction)
struts上でのメッセージの扱い方
struts上での例外の処理方法
strutsによる入力チェック方法
strutsによる入力チェック方法(DynaValidatorFormの使用)
tileタグの基本的な使い方
基本的な各種タグの使い方のサンプル
strutsのモジュール分割機能の利用方法(サブアプリケーション)
ActionMappingの拡張方法
struts-config.xmlをファイル分割する方法
http://struts.apache.org/より、strutsをDLします。今回使用したのは「 struts-1.2.9.zip 」です。
解凍後、webappsディレクトリ内の、struts-blank.warファイルを解凍したものを基本として使用します(普通にアーカイバで解凍できます)。
私の実行環境は、
WindowsVista HomeBasic
Eclipse3.4
Tomcat6.0
JDK1.6.0_11
InternetExplorer7
です。
単純な画面の、forward/redirectについてです。
index.jspページにアクセスすると、sample1.jspページへ遷移します。遷移方法にforwardとredirectが指定可能ですので、その方法について記述しています。
index.jspの中にコメントとして簡単な説明が書いてあります。
今回作成したファイルは以下のものです。
strutsを使う場合、jspも、strutsのタグライブラリを使用し、記述していきます。
以下のような遷移をするプログラムが、今回使用するサンプルです。
サンプルのような動作をさせるため、以下のようなファイルを用意しました。
以下のような動作をします。
■各種フォームに値を入力し、「submit」ボタンを押下(inputPage.jsp)
■前画面で入力された値を一覧表示する(result.jsp)
画面の入力フォームに、動的に初期値を設定したい時があります。ActionBean内で初期値を設定し、次画面でその値がデフォルト値として入力済みの状態にすることが可能です。
今回は、以下のようなファイルを作成しました。
■トップ画面(input.jsp)
↓
■初期値がActionBeanによって設定されている(result.jsp)
DynaActionFormを使うと、フォームBeanの作成を省略することができます。よい点というのが、フォームBeanのファイルの数が減らせる点・・・ぐらい??
今回のサンプルでは、以下のようなファイルを作成しました。
■トップ画面(index.jsp)
↓
■結果画面(result.jsp)
この場合、フォームBeanにて、ちょっとした細工が必要になります。普通、setXXXメソッドを呼び出し、フォームBeanに値がセットされますが、jspタグにて、indexed="true"がつけられると(詳しくは、showList.jspを参照)、フォームBeanで値をセットする際、setXXXメソッドではなく、getXXX(index値)のメソッドが呼ばれます。strutsは、その帰ってきたインスタンスに対し、setXXXメソッドを呼びます(そういう仕様らしい??)。
なので、フォームBeanとしては、さきほど、getXXX(int index)で生成したインスタンスを保持しておく必要があります(サンプルではリンクリストにいれてます)。
まぁ・・・この仕組みはすぐに、私は理解できませんでした・・・。結構複雑ですね。
今回、作成したものは以下の通りです。
■トップ画面(index.jsp)
↓
■中間画面(showList.jsp)
↓
■結果画面(result.jsp)
一つのフォームに複数のsubmitボタンを配置し、それぞれのボタンが押下された場合、処理を行うロジックの出しわけを行いたい場合があります。今回はそれの対応方法です。
DispatchActionクラスを使用する方法もあるのですが、こちらは、個人的に、使いづらいと思っているため扱わないこととします(struts
DispatchActionでググればすぐ出てくると思います)。
今回作成したのは、以下のファイルです。
■トップ画面(index.jsp)
↓
■「submit1」ボタンを押下した場合の、結果画面(result1.jsp)
strutsにより、セッション上に、(たぶん)重複のないtokenを保存しておき、それを画面のhidden値として埋め込みます。そして、submitを受け取るアクションBeanにて、そのtokenが有効化チェックしてやることで、二重押し、または、ブラウザの「戻る」ボタンを使い、複数回、submitボタンが押下されたのか、チェックを行うことができます。
サンプルでは、二重押しの場合はエラー画面(result_error.jsp)へ遷移し、正常ならば、正常画面(result_ok.jsp)へ遷移するようにしています。
今回作成したのは、以下のファイルです。
■トップ画面(index.jsp)
↓
■二重押しチェックが有効なボタンがある画面(chec.jsp)
↓
■正常系結果画面(resut_ok.jsp)
■異常系結果画面(result_error.jsp)
「jsp内で画面遷移させる方法(画面のredirectとforward)」にて書いた方法は、そのjspが表示された時、処理が走り、別ページに自動的に遷移するものでした。
今回のものは、submitボタンが押下された場合です。
submitボタンが押下されると、その後はstrutsが用意しているアクションBeanに処理させるため、struts-config.xmlと遷移先の画面のjspだけ用意すればOKです。
今回用意したものは、以下のものです。遷移に、ForwardとIncludeが使えますので、それぞれの処理結果を表すため、結果画面を二つ(result_include.jspとresult_forward.jsp)用意しています。
struts-config.xmlにて、どうやらフォームBeanを指定しなければいけないらしく(指定してやらないと動作しない)、そのため、とりあえずということで、tmpという名前でDynaFormBeanを定義して、それを使ってます。これ、なしで実行する方法はあるのかしら・・・?
「一つのフォームに複数のsubmitボタンがある場合(LookupDispatchAction)」にて書いた方法以外に、DispatchActionを使用する方法もあります。
しかし、この方法は、メソッド名が外部へ公開されてしまうため、使用するのは好ましくないと思い触れない予定でしたが、とりあえず書いておきます。メソッド名を外部に出さず、struts-config.xmlに直接指定可能な「MappingDispatchAction」がありますが、基本的にLookupDispatchActionを使えば万事解決ですので、省略しています。
サンプルには、POSTでやる方法、GETでやる方法、ふたつ一緒に例を挙げています。
■トップ画面(index.jsp)
↓
■submit1ボタンを押下した際の結果画面(result1.jsp)
strutsでは、MessageResources.propertiesに、メッセージに対する名前、そしてメッセージ本文を記述し、ソースからはメッセージに対する名前でを指定し、それに紐づいているメッセージが画面に表示される・・・、というような仕組みを提供しています(このMessageResources.propertiesの名前は変更できるんだろうけど、変更したことがないw)
アクションBean内でのメッセージの設定方法、jspからメッセージの呼び出し方法をサンプルに載せています。
今回作成したのは以下のファイルです。
■トップ画面(index.jsp)
↓
■結果画面(result.jsp)
例外が発生した場合の、struts的に、それを拾い上げ、画面遷移が突然例外画面にならないように制御することが可能です。
例外の拾わせ方の設定として、指定のアクションBeanに対するものの、設定と、グローバル設定があります。特性のアクションBeanで処理中に例外が発生した場合、struts-config.xml内の、actionタグ内に設定してあるexceptionをまず検索し、一致する例外クラスがあるか調べ、その次に、global-exceptionで定義していあるexception内に一致する例外クラスがあるか・・・を探しに行く様子です。
また、exceptionの並び順も意味があり、上から順に評価され、一致するものが選ばれる様子です。
アクションBeanに対し、例外が発生した場合に、呼ばれる処理も指定が可能らしい(exception の中に、handlerdeで設定を行う)。しかし、あまり使わないであろうという個人的な理由からサンプルより割愛しています。
サンプル中、例外が起きる条件がそれぞれ異なるため、目的の例外を発生させる以外の、そのたの例外を発生させるソースはコメントアウトしてあります。なので、詳しくはソースを参照してください。コメントを書いてあります。
今回作成したのは以下のものです。
■トップ画面(index.jsp)
↓
■エラー画面[代表例として、NullPointerExceptionが発生し、action内のexceptionで設定した例外設定にフックされた状態](error.jsp)
strutsが提供しているユーザ入力値のチェックはいくらかあります。とりあえず、(1)〜(3)にて基本的な方法を説明し、その後、実際のソースをおいておきます。
正直なところ、validator関連のことはよくわかってません。理解不足です。
が・・・、まぁ、実際動かしてみて動いたので良しとします(笑)
validatorは結構やることが多く、面倒です。正直なところ、使いたくないというのが個人的感想です。
また、今回のテーマとは関係ありませんが、エラーメッセージを画面へ表示する際(html:errorsタグで表示させているところ)、今回は、errors.header、errors.prefix、errors.suffix、errors.footerを使用しています。動作はサンプルを見てみてください。こういうこともできるんだーという例です
今回作成したのは、以下のものです。〜1となっているものが(1)に該当し〜2となっているものが(2)の説明に該当します。
代表例として(2)のケースの画面遷移(画面の表示的には、(1)〜(3)同じです。ただし(3)の場合は、JavaScriptのダイアログでエラーメッセージが表示されますが・・・)
■トップ画面(index2.jsp)
↓
■トップ画面[エラーメッセージ有り](index2.jsp)
↓
■結果画面(result2.jsp)
DynaActionFormを使用するところで、Struts Validatorを使用したい場合は、DynaValidatorFormクラスをsturts-config.xmlで指定します。
上のやつの補足でよく使いそうな入力チェックの、入力文字列の制限の例もはいっています(上のだと、数値の範囲のチェックになってる)。
基本的にform-beanの定義のところにて、使用するフォームのクラスがDynaActionFormだったものを、DynaValidatorFormに指定するだけです。
今回作成したのは以下のファイルです。
入力制限として、10文字以上、20文字以下、入力可能な文字は[0-9a-zA-Z]で、未入力は不可とする・・・です。
■トップ画面(index.jsp)
↓
■入力エラーがあった場合のトップ画面(index.jsp)
■(正しい入力をした場合の)結果画面(result.jsp)
tileタグは、普通にjspの中に以下のようにすることで、やりたいことはできるのですが・・・。
jsp内にてタグライブラリを読み込み・・・ <%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %> 指定のページをincludeしたい場所に、insertタグを記述・・・・ <tiles:insert page="/footer.jsp"/> |
以下のやりかたで、読み込むページ(「/footer.jsp」と指定している箇所)をxmlファイルに記述し、外部化することが可能です。サンプルでは設定の継承を行ったものを示します(ただ、extendsと書いて修正が必要なところだけ再定義しただけ)。
■トップ画面(index.jsp)
↓
■mainLayoutEx(tileタグを使用し構成された画面)
私が思いついた、各種タグの基本的な使い方のサンプルです。以下のものを扱っています。
内容 | サンプルソースの対応する箇所 |
(1)メッセージリソースの文字列を画面へ表示 | index.jsp L24〜L39 |
(2)自分のページのところへリンクを張る | result.jsp L105 |
(3)フォームBean外にセットしたデータを使用する方法 | InputAction.java L21〜L26, result.jsp L18〜L26 |
(4)値が未入力かどうかチェック | result.jsp L29〜L47 |
(5)Iteratorの使い方 | result.jsp L50〜L63 |
(6)エラーメッセージの表示方法 | index.jsp L16〜L22 |
(7)bean:parameterの使い方 | result.jsp L66〜L74 |
(8)bean:defineの使い方 | result.jsp L76〜L86 |
(9)nested:rootの使い方 | result.jsp L88〜L99 |
今回作成したのは以下のファイルです。
■トップ画面(index.jsp)
↓
■結果画面(result.jsp)
そもそも、どういう意味かといいますと、いつも、http://アドレス/コンテキストルート/index.jsp なんてアクセスしていますが、これに・・・ http://アドレス/コンテキストルート/モジュール名/index.jsp という構成にし、この「モジュール名」ごとに、1アプリ的な扱いをし、本当は1つのwarなんだけど、モジュール名でアドレスを変えることで複数のアプリが共存しているようにみえるよーって話らしい。
まぁ、とりあえず、分けれるらしい。それぞれのモジュール毎に、struts-config.xmlファイルを作成することになります。
今回、サンプルとして、このモジュール分割機能を使用せず、いつもどおりのサーブレット呼び出し方法と、モジュール分割機能を使って分けた「module1」というモジュールのページを呼び出す・・・という処理をサンプルとして記述しました。
今回作成したファイルは以下のものです。
サンプルを記述していて、注意しなければなぁと思ったのは以下の点です。
(1) actionタグを記述しているところで、別モジュールへ画面を遷移させる際は、「 contextRelative="true" 」を記述せねばならないらしい(今回のサンプルでは、struts-config.xmlのL31〜L41あたり)。
(2) モジュール分割する・・・というのはstruts側の制御なので、サーブレットを介してページ遷移を行わなければ(今回の例で言うと「index.jsp画面からボタンを押してmodule1のトップ画面に遷移する・・・など」)正常に動作しない。そのまま、サーブレットやjspをアクセスしにいっても、だめ。
画面遷移は今回はボタンが多いので、代表例として、トップ画面から、一番したの「module1へ」ボタンを押下したパターンを乗せます。
■トップ画面(index.jsp)
↓ (一番下の「module1」ボタンを押下)
■module1のトップ画面(module1/index.jsp)
↓(送信!ボタンを押下)
■module1の結果画面(module1/result2.jsp)
↓(module1へボタンを押下)
↓(TOPへリンクを押下)
(最初の画面に戻ります)
ActionMappingクラスを独自に拡張し、使用するサンプルです。
やりかたとしては、ActionMappingクラスを継承し、拡張します。そして、そのクラスを使用するように、struts-config.xml内にて指定します(action-mappingsタグの属性としてtype="<ActionMappingクラスを継承したクラス>"で、指定します)。
今回作成したのは、以下のファイルです。
■トップ画面(index.jsp)
↓
■結果画面(result.jsp)
この結果画面に表示されている文字列は、拡張したActionMappingExクラスから取得したものです。この文字列はどこで指定しているかというと、actionタグ内の、set-propertyタグにて行っています。
※備考
今回、action-mappingタグにtypeという属性にて使用するアクションマッピングクラスを指定すると、すべてのactionに対して、適応されることになります。
指定のactionタグのところだけ、別のアクションマッピングを使用したい場合、それぞれのactionタグごとに個別に指定する方法があるらしい。
以下のような感じで指定します。
<action-mappings> <action path="/Input" type="InputAction" name="Input" scope="request" className="ActionMappingEx"> <forward name="success" path="/result.jsp"/> <set-property property="originalMessage" value="nyannnyannnyannnyann"/> </action> </action-mappings> |
acitonタグのclassNameにて使用するアクションマッピングクラスを指定しています。
struts-config.xmlは、画面制御のすべてを保持するデータなので、すぐに肥大化してしまいます。これを、〜の部分は〜.xmlに記述し、〜の部分は〜.xmlに記述する・・・というような運用が可能です。
ただし、フォーム名や、アクション名が重複していると予期せぬ動きをしますので、名前の管理だけは開発者の責任で管理しなければなりません(重複していても、エラーにならず普通に動いてしまいます)。
web.xmlのstruts-config.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, /WEB-INF/struts-config2.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> |
それぞれ、struts-config.xmlとstruts-config2.xmlは以下のように普通に記述します。
struts-config.xml |
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="Input" type="InputForm"/> </form-beans> <action-mappings> <action path="/Input" type="InputAction" name="Input" scope="request"> <forward name="success" path="/result.jsp"/> </action> </action-mappings> </struts-config> |
struts-config2.xml |
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <action-mappings> <action path="/Input2" type="InputAction" name="Input" scope="request"> <forward name="success" path="/result.jsp"/> </action> </action-mappings> </struts-config> |
このサンプルでは、Inputのフォームがすでに、struts-config.xmlに記述してあるため、struts-config2.xmlでは記述していませんが、実行可能です。