Strutsユーザガイド
クイックリンク
ホーム
目次
はじめに
モデル コンポーネント
ビュー コンポーネント
コントローラ コンポーネント
リソース
私たちは誰でしょう
4. コントローラコンポーネントの構築
4.1 概要

これまでで、私たちはアプリケーションのモデルとビューコンポーネントの構築の方法を理解していますので、Controllerコンポーネントに焦点をあてる時がきました。Strutsは、リクエストされたURIをActionクラスにマッピングするという基本的な機能を実装したServeltを含んでいます。 したがって、コントローラーに関連する主要な作業は次のとおりです。

  • 受け取るであろう論理的な各リクエストに対する Actionクラス(org.apache.action.Actionの継承クラス)を書く
  • サブミットされるであろう論理的な各リクエストに対する ActionMapping(XML形式)を設定する。 このXML設定ファイルは通常、struts-config.xmlという名前である
  • アプリケーションのために、必要なStrutsコンポーネントを含むように Webアプリケーション配置記述子ファイル(XML形式)を更新する
  • あなたのアプリケーションに適切なコンポーネントを追加する
4.2 Actionクラス

ActionクラスはServlet環境に応じて実行される2つのメソッドを定義しています。

public ActionForward perform(ActionMapping mapping,
                             ActionForm form,
                             ServletRequest request,
                             ServletResponse response)
  throws IOException, ServletException;

public ActionForward perform(ActionMapping mapping,
                             ActionForm form,
                             HttpServletRequest request,
                             HttpServletResponse response)
  throws IOException, ServletException;

ほとんどのプロジェクトは、"HttpServeltRequest"バージョンのみを使うでしょう。

Actionクラスのゴールは、perform()メソッドでリクエストを処理し、コントロールがどこに転送されるべきか(たとえばJSPページ)を識別するActionForwardオブジェクトを返して、適切なレスポンスを提供することです。 MVC/Model 2デザインパターンにおいて、典型的なActionクラスは、 perform()メソッドに下記のようなロジックを実装します。

  • ユーザのセッションの現在の状態の検証(たとえばユーザがログオンに成功したかのチェック)。もし、Actionクラスが未ログオンを検出したなら、リクエストはJSPページに転送され、ログオンのためのユーザ名とパスワードのプロンプトが表示されます。これは、ユーザがアプリケーションの途中(ブックマークから)に直接入ろうとした場合や、セッションがタイムアウトして、Servletコンテナが新しくリクエストを生成した場合に発生します。
  • もし、検証が完了していない場合、必要に応じてフォームBean属性を検証します。 もし問題があれば、適切なエラーメッセージのキーをリクエスト属性に保存します。そして、エラーを修正できるように、コントロールを入力フォームへ戻します。
  • このリクエスト(データベースへ列を保存するような)を扱うように要求された処理を実行します。これは、Actionクラス自身のロジックコードに埋め込む事で可能です。しかし、一般的には、ビジネスロジックBeanの適切なメソッドを呼ぶ事により実行されるべきです。
  • ユーザインタフェースの次のページを作成するのに使われるサーバサイドのオブジェクト (典型的なケースでは、リクエストスコープまたはセッションスコープのBeanです。 どのくらいの時間、このオブジェクトを有効とする必要があるかに依存します) を更新します。
  • 適切なActionForwardオブジェクトを返します。これは、新しく更新されたBeanに基づいて、このレスポンスを生成するJSPページを特定します。 典型的には、(論理名がこのマッピングに対してローカルなら)ActionMappingオブジェクトに対して、(論理名がアプリケーションに対してグローバルなら)コントローラServlet自身に対して、findForward()を呼び出すことで、そのようなオブジェクトへの参照を受け取ります。

Actionクラスのコーディングをする場合には、下記のようなデザインの問題を含んでいる事を思い出してください。

  • コントローラServletはActionクラスとそれを使う全てのリクエストに対して、ただ1つのインスタンスを作ります。したがって、マルチスレッド環境内での正確に動作するように、Actionクラスをコード化する必要があります。 Servletのservice()メソッドを安全にコード化するのと同じです。
  • スレッドセーフコーディングを助けるもっとも重要な指針は、Actionクラスのインスタンス変数ではなく、ローカル変数のみを使う事です。 ローカル変数は、それぞれのリクエストスレッドのスタックに(JVMによって)割り当てられて作られます。よって、これらの共有の心配をする必要がありません。
  • システムのモデルを表現するBeanは、データベースや他のリソースへのアクセスの問題により例外を投げるかもしれません。そのような場合、perform()メソッドのロジックで、全ての例外をトラップしなくてはなりません。 そして、servlet.log("Error message text", exception)メソッドを呼び、アプリケーションログファイルに(対応するスタックトレースと共に)記録します。
  • 概して、少ない資源を割り付けて同じユーザ(ユーザセッション)からのリクエストを跨って維持する事は、スーケラビリティーの問題を引き起こすかもしれません。適切なビューコンポーネントへコントロールをフォワードする前に、そのようなリソースを開放する為の努力をするべきです-- たとえ、呼び出したbeanのメソッドが例外をthrowしたとしてもです。

さらに、Actionクラスが大きくなりすぎないように注意してください。 最も簡単にこれを発生させてしまう方法は、個別のビジネスロジックBeanの中で機能をコード化せずに、Actionクラス自身に埋め込んでしまうことです。 Actionクラス自身を理解することもメンテナンスすることも難しくなるのに加え、このアプローチはビジネスロジックの再利用も難しくします。なぜならコードが、Webアプリケーションの環境でしか実行できない1コンポーネント(Actionクラス)内に埋め込まれるためです。

Actionは、すべての必要とされる属性がメソッドの引数から渡される限り、いくつかのローカルメソッドへ分解することができます。 JVMはスタックを使ってそういった属性を処理するので、それらはスレッド・セーフです。

Strutsに含まれるサンプルアプリケーションは、ビジネスロジックがActionクラス自身に含まれているので、この設計指針を少々踏みにじっています。 これは、Strutsアーキテクチャ組込の機能、あるいは真似るべきアプローチではなく、サンプルアプリケーションのデザイン上のバグとみなされるべきです。

4.3 ActionMappingの実装

操作を成功させるために、StrutsコントローラServletは、個々のリクエストURIが適切なActionクラスにマップされる方法について、幾つかの事柄を知っている必要があります。 必要な情報は、ActionMappingという名前のJavaインタフェースでカプセル化されています。最も重要な属性は次のものです:

  • type - このマッピングによって使用されるActionの実装クラスの完全修飾されたJavaクラス名。
  • name - このアクションで使用する設定ファイル中で定義された、 フォームBeanの名前。
  • path - このマッピングを選択する場合に一致するリクエストURIのパス。一致処理がどう動くかの例は後述します。
  • unknown - このアプリケーションにおいて、他のアクションで処理されない全てのリクエストを処理するデフォルトのアクションに設定する場合tureにセットしてください。1つのアプリケーションには、ただ1つのデフォルトを定義することが可能です。
  • validate - このマッピングのアクションに関連付けされたvalidate()メソッドを呼ぶ場合、trueに設定してください。
  • forward - このマッピングが呼ばれた時に、制御が渡されるリクエストURIパス。これは、type属性とどちらか1つを宣言します。
4.4 アクションマッピング設定ファイル

コントローラServletは、あなたの必要とするマッピングをどうやって得るのでしょうか?それは、単にActionMappingのインスタンスを新たに作り、適切な全てのセッターメソッドを呼ぶような、小さなJavaのクラスを記述する事で可能です(が単調です)。 このプロセスをより容易にするために、StrutsはDigesterモジュールを含んでいます。これは適切なマッピングのXMLベースの記述を読み込み、適切なオブジェクトを生成することができます。Digesterに関する詳しい情報は、APIドキュメント を参照してください。

開発者が行う事は、struts-config.xmlという名前のXMLファイルを作成し、アプリケーションのWEB-INFディレクトリに置く事です。 このドキュメントのフォーマットは、"struts-config_1_0.dtd"に定義が規定されています。最も外側のXML要素は、<struts-config> でなければなりません。

<struts-config>要素の内部に、アクションのための2つの重要な要素を記述します

<form-beans>
このセクションは、フォームBeanの定義を含みます。 それぞれのフォームBeanに<form-bean>要素を適用する場合、下記の属性が重要です。
  • name:このBeanに対するユニークな識別子で、対応するアクションマッピングの中で、それを参照するために使用されます。 通常、このフォームBeanが格納されるリクエストまたはセッション属性の名前でもあります。
  • フォームBeanの完全修飾されたJavaクラス名。
<action-mappings>
この章の内容は、アクションの定義です。 各アクションを <action>要素を用いて定義します。 それぞれのアクション要素は下記の属性の定義を要求します
  • path: アクションのアプリケーションコンテキスト相対パス
  • type: アクションクラスの完全修飾されたJavaクラス名
  • name: このアクションで使う<form-bean>要素の名前

サンプルアプリケーションのstruts-config.xmlは、“ログオン”機能のための下記のマッピングエントリを含んでおり、これを使って要件を説明します。 注:他の全てのアクションへのエントリーは省きました

<struts-config>
  <form-beans>
    <form-bean
      name="logonForm"
      type="org.apache.struts.example.LogonForm" />
  </form-beans>      
  <global-forwards
      type="org.apache.struts.action.ActionForward" />
    <forward name="logon" path="/logon.jsp"
         redirect="false" /> 
  </global-forwards>      
  <action-mappings>     
    <action
        path="/logon" 
        type="org.apache.struts.example.LogonAction"
        name="logonForm"
       scope="request"
       input="/logon.jsp"
     unknown="false"
    validate="true" />          
  </action-mappings>
</struts-config>

はじめに、フォームBeanを定義します。基本的な"org.apache.struts.example.LogonForm"クラスのBeanは、論理名"logonForm"としてマップします。 この名前は、フォームBeanをセッションまたはリクエスト属性で使う時の名前です。

"global-forwards"セクションは、一般的に用いられるJSPページの論理名マッピングを作る場合に使います。 これらの各フォワードは、アクションマッピングインスタンスへの呼び出しによって利用可能となります。すなわち、actionMappingInstance.findForward("logicalName")です。

ここに示したように、マッピングはパス/logonにマッチします (実際には、サンプルアプリケーションでは、拡張子マッピングを使っています。 JSPページ内で指定する要求リクエストURIは/logon.doで終わるでしょう)。 このパスとマッチするリクエストが届いた時、 LogonActionクラスのインスタンスが作られ(初回のみ)、そして使用されます。 コントローラServletは、キーlogonFormで、 セッションスコープ内のBeanを探し、もし必要なら指定されているクラスのBeanを作成し保存します。

オプションですがとても有用なのは、ローカルな"forwardエレメントです。 サンプルアプリケーションでは、多くのアクションがアクションマッピングの一部として、ローカルな"success"または"failure"のフォワードを含んでいます。

<!-- Edit mail subscription -->
<action    path="/editSubscription"
  type="org.apache.struts.example.EditSubscriptionAction"
  name="subscriptionForm"
  scope="request"
  validate="false">
  <forward name="failure" path="/mainMenu.jsp"/>
  <forward name="success" path="/subscription.jsp"/>
  </action>

これら2つの特別なプロパティを使えば、 サンプルアプリケーションのActionクラスは、 ページデザイナーが用いるJSPページの実際の名前には、ほとんど依存しません。 ページは、(たとえば)再デザインの間にリネームが可能であり、 Actionクラス自身はまったくその影響を受けません。 もし、"next"という名前のJSPページがActionクラス内に直接記述されていたとしたら、 それら全てのクラスに変更が必要になるでしょう。 もちろん、アプリケーションのためのローカルフォワードプロパティを何でも定義可能です。

もう1つの有用なセクションは<data-sources>で、アプリケーションで使用するデータソースを指定します。 これは、アプリケーションの基本的なデータソースをstruts-config.xmlの中に指定するやり方です。

<struts-config>
  <data-sources>
    <data-source
      autoCommit="false"
     description="Example Data Source Description"
     driverClass="org.postgresql.Driver"
        maxCount="4"
        minCount="2"
        password="mypassword"
             url="jdbc:postgresql://localhost/mydatabase"
            user="myusername"/>
  </data-sources>
</struts-config>

データソースの探し方の情報は、 Accessing Relational Databasesを参照してください。

4.5 Webアプリケーション配置記述子

アプリケーションセットアップの最終ステップは、 アプリケーション配置記述子(WEB-INF/web.xmlにある)に、 要求される全てのStrutsコンポーネントを含むように設定を行う事です。 サンプルアプリケーションの配置記述子をガイドとして使い、 以下のエントリーを作成または修正される必要があるを確認しましょう。

4.5.1 アクションServletインスタンスの設定

アクションServlet自身の定義を適切な初期化パラメータと一緒に追加します。 エントリーは次のようになります。

<servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>
    org.apache.struts.action.ActionServlet
  </servlet-class>
  <init-param>
    <param-name>application</param-name>
    <param-value>
      org.apache.struts.example.ApplicationResources
    </param-value>
  </init-param>
  <init-param>
    <param-name>config</param-name>
    <param-value>
      /WEB-INF/struts-config.xml
    </param-value>
  </init-param>
  <init-param>
    <param-name>debug</param-name>
    <param-value>2</param-value>
  </init-param>
  <init-param>
    <param-name>mapping</param-name>
    <param-value>
      org.apache.struts.example.ApplicationMapping
    </param-value>
  </init-param>
  <load-on-startup>2</load-on-startup>
</servlet>

コントローラServletによってサポートされる初期化パラメータを、 以下に記述します。 (詳しくは、Javadocs の ActionServletクラス を参照してください)。 角括弧内は、初期化の値が指定されなかった場合のデフォルト値です。

  • application - アプリケーションリソースバンドル ベースクラスのJavaクラス名。[NONE]
  • bufferSize - ファイルアップロード処理時に用いる、 入力バッファサイズ。[4096]
  • config - 設定情報をもつXMLリソースへのコンテキスト相対パス。 [/WEB-INF/struts-config.xml]
  • content - 各レスポンスにセットするデフォルトのコンテントタイプと、キャラクタエンコーディング。おそらくフォワードされるServlet又はJSPページで上書きされます。[text/html]
  • debug - このServletのデバッグの詳細レベル。 どれだけの情報をログに残すかをコントロールする。[0]
  • detail - initMapping()内で利用しているDigesterのデバッグの詳細レベル。 servletログの代わりに System.outへ出力をする。[0]
  • factory - アプリケーションのMessageResources オブジェクトを作る為に利用するMessageResourcesFactoryのJavaクラス名。 [org.apache.struts.util.PropertyMessageResourcesFactory]
  • formBean - ActionFormBeanの実装に用いるJavaクラスの名前。 [org.apache.struts.action.ActionFormBean].
  • forward - ActionForwardの実装に用いるJavaクラスの名前。 [org.apache.struts.action.ActionForward]. あなたが使いたくなる、2つの便利なクラスは:
    • org.apache.struts.action.ForwardingActionForward - org.apache.struts.action.ActionForwardのサブクラスで、 デフォルトのredirectプロパティはfalse (ActionForwardのデフォルトの値と同じ)
    • org.apache.struts.action.RedirectingActionForward - org.apache.struts.action.ActionForward のサブクラスで、 デフォルトのredirectプロパティはtrue
  • locale - もし、trueにセットされていれば、ユーザセッションにまだ、Localeオブジェクトが無い場合に、適切な java.util.Localeオブジェクトを識別し、ユーザセッションに保存します(標準の識別キーはAction.LOCALE_KEY)。[true]
  • mapping - ActionMappingの実装に利用するJavaクラス名 [org.apache.struts.action.ActionMapping]。 あなたが使いたくなる、2つの便利なクラスは:
    • org.apache.struts.action.RequestActionMapping - org.apache.struts.action.ActionMapping のサブクラス であり、デフォルトのscopeプロパティは"request"です。
    • org.apache.struts.action.SessionActionMapping - org.apache.struts.action.ActionMapping のサブクラス であり、デフォルトのscopeプロパティは"session"です (ActionMappingのデフォルト値と同じ)
  • maxFileSize - ファイルアップロードの時にうけとるファイル の最大サイズ(単位はバイト)。数値の後に"K","M","G"を付けるとそれぞれ、 "キロバイト"、"メガバイト"、"ギガバイト"という意味になる。[250M]
  • multipartClass - ファイルアップロードを処理する為の MultipartRequestHandlerを実装する完全修飾されたクラス名。 [org.apache.struts.upload.DiskMultipartRequestHandler]
  • nocache - trueにセットされている場合、生成またはフォワードする全てのレスポンスに対するブラウザキャッシングを無効にするためのHTTPヘッダを、全てのレスポンスに追加する。[false]
  • null - trueにセットされている場合、知らないメッセージキーを用いた場合、アプリケーションリソースはnullを返します。さもなければ、不正なメッセージキーを含んだエラーメッセージが返却されます。[true]
  • tempDir - ファイルアップロード処理時に用いる作業ディレクトリです。[このWebアプリケーションのServletコンテキスト属性として提供されます]
  • validate - 新しい設定ファイルフォーマットを使うか?[true]
  • validating - 設定ファイルの処理には、検証XMLパースを使うか(強く推奨します)?[true]
4.5.2 アクションServletマッピングの設定
注釈:このセクションの中の項目は、Struts固有のものではありません。Servletマッピングの設定は、Java Servlet 仕様に定義されています。 このセクションは、Strutsアプリケーションを設定する最も一般的な方法について記述します。

コントローラServletに処理されるURLの定義方法には、プレフィックスマッチングと、拡張子マッチングの2つのアプローチがある。それぞれのアプローチの適切なマッピングエントリは以下のようになります

プレフィックスマッチングは、(コンテキストパス部分の後に)特定の値で始まるURLのリクエストの全てを、このServletに送る事を意味します。以下のようなエントリになります。

  <servlet-mapping>
     <servlet-name>action</servlet-name>
     <url-pattern>/execute/*</url-pattern>
   </servlet-mapping>

この場合の、/logonパスと一致するリクエストURIは 以下のようになります。

http://www.mycompany.com/myapplication/execute/logon

この、/myapplicationは、 アプリケーションが配置されるコンテキストのパスです。

一方でエクステンションマッピングは、アクションServletへのリクエストURIがピリオドに続く定義されたキャラクタセットで終わるという事実にもとづいてマッチします。 例えば、JSPを処理するServletは、*.jspパターンにマップされ、 全てのJSPページのリクエストを処理するために呼ばれます。 *.do拡張子を使うためには、以下のようにマッピングエントリを記述します。

  <servlet-mapping>
     <servlet-name>action</servlet-name>
     <url-pattern>*.do</url-pattern>
   </servlet-mapping>

そして、/logonパスとマッチするリクエストURIは以下のようになります

http://www.mycompany.com/myapplication/logon.do
4.5.3 Strutsタグライブラリの設定

次に、Strutsタグライブラリを定義するエントリを追加しなくてはなりません。 現在、4つのtabligがStrutsのパッケージに含まれています

struts-bean タグライブラリは、Beanとそのプロパティにアクセスするのに有用なタグや、(これらのアクセスに基づいた)新しいBeanを定義するタグを含んでいます。 このBeanは、スクリプト変数やページスコープの属性を通して、ページからアクセス可能です。 リクエストクッキー、ヘッダーおよびパラメータの値に基づいた、 新しいBeanを作成する便利なメカニズムもまた提供されます。

struts-html タグライブラリは、HTMLベースのユーザインタフェースを作成するのに便利な、struts入力フォームを作成するためのタグを含んでいます。

struts-logic タグライブラリは、出力テキストの生成状態を管理するのに有用なタグと 、出力テキストの繰り返し生成をオブジェクトのコレクション毎に行うタグと、アプリケーションのフロー制御のタグを含んでいます。

struts-template タグライブラリは、テンプレートの仕組みを定義するタグを含んでいます。

アプリケーションで全てのタグライブラリを使うには、下記のように指定します。 実際には、アプリケーションで使うものだけを指定します。

<taglib>
  <taglib-uri>
    /WEB-INF/struts-bean.tld
  </taglib-uri>
  <taglib-location>
    /WEB-INF/struts-bean.tld
  </taglib-location>
</taglib>
<taglib>
  <taglib-uri>
    /WEB-INF/struts-html.tld
  </taglib-uri>
  <taglib-location>
    /WEB-INF/struts-html.tld
  </taglib-location>
</taglib>
<taglib>
  <taglib-uri>
    /WEB-INF/struts-logic.tld
  </taglib-uri>
  <taglib-location>
    /WEB-INF/struts-logic.tld
  </taglib-location>
</taglib>
<taglib>
  <taglib-uri>
    /WEB-INF/struts-template.tld
  </taglib-uri>
  <taglib-location>
    /WEB-INF/struts-template.tld
  </taglib-location>
</taglib>

これは、このライブラリ用のタグライブラリ記述子を何処(アプリケーションのWEB-INFディレクトリ内、 またはインターネット上のどこか)から見つけるかをJSPシステムに教えています。

4.5.4 Strutsコンポーネントをアプリケーションに追加

Strutsを使う時には、必要な .tldファイルをWEB-INFディレクトリにコピーしなければなりません。また、struts.jar(と、commons-*.jarファイルの全て) をWEB-INF/libディレクトリにコピーする必要があります。

Next: Strutsリソース


[訳注: これは黒住 幸光が翻訳しました。日本語訳に対するコメントがあれば、report@jajakarta.orgに送って下さい。]
Copyright (c) 2000-2002, Apache Software Foundation