■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2008年05月25日

    楽しいJava講座 - 初心者から達人へのパスポート
                  vol.105

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


[このメールマガジンは、画面を最大化して見てください。]


========================================================
◆ 01.Strutsのアプリケーション開発
========================================================


さて、ここには以下のようなソース・コードのファイルがリスト
されていますね。

JavaServer Pages
   Simple.jsp
   SimpleResults.jsp

Actions
   SuccessAction.java
   ProcessSimpleAction.java

ActionForm
   SimpleActionForm.java

Configuration files
   struts-config.xml

これらのファイルは、Strutsのユーザー(Strutsを使ってWebアプリ
ケーションを開発する人)が実際に作成しなければならないファイル
です。
(ただし、ファイル名はアプリケーションで独自に命名しますので、
これらと同じファイル名が使われるということではありません。)

そして、これらのうちJavaServer Pages、すなわちJSPは、これまでの
Webアプリケーションのときと同じくWebページを表示するためのファイル
(JSPのファイルがHTMLに変換されてWebブラウザーに返される)で、
新しく登場してきたActionというのはWebアプリケーションの処理の流れ
をコントロールするためのクラスで、同じくActionFormはWebページの
FORMのデータを保持するためのクラスで、Configuration file(構成ファ
イル)(struts-config.xml)というのは、これらのファイルの関係(構成)
を記述するファイルです。


では、まず最初に、これらのサンプル・ファイルを使ってStrutsの
仕組みを大まかに説明しておきましょう。

その前に、struts-cookbook-1.3.8フォルダーの下のWEB-INFフォルダー、
つまり

C:\Tomcat6.0\webapps\struts-cookbook-1.3.8\WEB-INF

の中にある

web.xml

を確認してください。web.xmlというのは、以前出てきたWebアプリ
ケーション・デプロイメント記述子(Web Application Deployment
Descriptor)でしたね。

このweb.xmlをテキスト・エディター(NoEditorなど)で開いて見て
ください。

--------------------------------------------------------
  <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-config-Wildcard.xml
       </param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>

  <!-- Standard Action Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
--------------------------------------------------------

という部分がありますが、この部分は今後、我々がStrutsのアプリケーション
を作っていくときにもそのまま使用することになります。

ここに書いてあることを日本語に翻訳(?)すると、まず

  <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-config-Wildcard.xml
       </param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>

の部分は、org.apache.struts.action.ActionServletというクラスをactionという
サーブレット名(servlet-name)で呼ぶことを指定しています。また、init-param
というタグによって、(サーブレットが初めて呼ばれるときに行われる)初期化の
ときに、(configというパラメーター名で読み込まれる)構成ファイルとしては、
/WEB-INF/struts-config.xmlと/WEB-INF/struts-config-Wildcard.xmlを読み込む
ことを指定しています。
そして、

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

の部分は、*.doすなわち、何とかかんとか.doというURLで呼び出されたときには、
このactionというサーブレットを呼び出すことを指定しています。(ここの*は「任意
の文字列」を意味します。)

Strutsで使われるサーブレットは、このActionServletひとつだけです。
他に複数のサーブレットを使うように指定することも可能ですが、通常は
その必要はありません。

そして、このActionServletは、Strutsによって実装済みであり、我々が実装
する必要はありません。


このActionServletが呼び出されると、さきほどのconfigというパラメーターで指定
されていたstruts-config.xml(とstruts-config-Wildcard.xml)というファイルを
見て(というか、もっと正確には、これらのファイルの内容はサーブレットの初期化
の段階でメモリー上に読み込まれているので、あとはメモリー上から情報を読み取っ
て)、URLに対応付けられたファイルを探します。


ここらへんの動きを具体的に見ていくために、前回Webブラウザーに指定したURL

http://localhost:8080/struts-cookbook-1.3.8/index.jsp

の末尾で指定したindex.jspというJSPファイルの中身を見てみましょう。

┌補足─────────────────────────┐
 web.xmlの下のほうに記述されている

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

という指定は、URLでindex.jspの部分を省略しても、自動的に
index.jspを呼び出してWebページを返してくれることを意味し
ます。したがって、

http://localhost:8080/struts-cookbook-1.3.8/index.jsp

の代わりに

http://localhost:8080/struts-cookbook-1.3.8/

というURLで呼び出してもindex.jspのWebページが返ってくるの
です。
└───────────────────────────┘


C:\Tomcat6.0\webapps\struts-cookbook-1.3.8\index.jsp

をテキスト・エディターで開いて見てください。
この中の59行目の

<html:link action="/prepareSimple">Execute</html:link>

という部分が、前回、我々がクリックしたExecute(vol.104の最後のほうの(4)で
クリックした部分)を表示するソース・コードです。

このhtml:linkというタグについては、後ほど詳しく説明しますが、ここでは
action="/prepareSimple"という記述に注目してください。この記述があると、
表示されたExecuteという文字列をクリックすると、URLに/prepareSimple.do
(後ろに.doが自動的に付加される)というのが指定されてサーブレットが呼び
出されるようになっています。

実際に前回の操作(Executeという文字列をクリックする)を再度行ってみて
ください。Webブラウザーに

http://localhost:8080/struts-cookbook-1.3.8/prepareSimple.do

というURLが自動的に指定されることに気づくでしょう。

このURLが指定されると、さきほどのActionServletが呼び出され(*.doというURL
ですからね)、ActionServletはstruts-config.xmlの中を見て(正確にはメモリー
の中を見るのだが)prepareSimpleというパス(path)の記述を探してきます。

実際にstruts-config.xmlの中を見る(最初のリストの中にあるstruts-config.xml
をクリックするか、もしくは、

C:\Tomcat6.0\webapps\struts-cookbook-1.3.8\WEB-INF\struts-config.xml

を直接テキスト・エディターで開いて見てください)と、

--------------------------------------------------------
        <action path="/prepareSimple"
                type="examples.SuccessAction">
            <forward name="success" path="/jsp/simple/Simple.jsp"/>
        </action>
--------------------------------------------------------

という行が見つかりますね。この行は、「/prepareSimpleというパスがURLに指定
されていたらexamples.SuccessActionというクラスを呼び出し(そのexecuteという
メソッドを実行し)、その結果forwardに"success"という文字列が設定されたら、
/jsp/simple/Simple.jspというJSPファイルを結果のWebページとしてWebブラウザー
に返しなさい。」ということを指定しています。(このforwardとは何なのか?
については、後で説明します。)

したがって、この行を読み取ったActionServletはexamples.SuccessActionという
クラス(のexecuteというメソッド)を呼び出して、その実行結果(戻り値)を判定し、
forwardに"success"という文字列が設定されていたら/jsp/simple/Simple.jspから
変換したWebページをWebブラウザーに返すのです。

では、そのSuccessActionというクラスのソース・コードを開いて見てみましょう。
(最初のリストの中にあるSuccessAction.javaをクリックする。)
この中には、
--------------------------------------------------------
    public ActionForward execute(
        ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {

        return mapping.findForward("success");

    }
--------------------------------------------------------

という行がありますね。つまり、このSuccessActionのexecuteは
mapping.findForward("success")という値を戻り値として返すという
処理をしています。
これが、先ほど言った「forwardに"success"という文字列を設定して
返す」という処理です。(これは極めて単純なサンプルなので、こんな
単純な処理しかしていませんが、普通のアプリケーションではもっと
複雑な処理をします。)

なお、このSuccessActionはActionクラスのサブクラスとして作られている、つまり

--------------------------------------------------------
public class SuccessAction extends Action {
--------------------------------------------------------

という行があることも、ひとまず頭に入れておいてください。
(先ほどのActionServletと、このActionを混同しないでください。この
Actionクラスのほうはサーブレットではなく、サーブレットによって呼び出さ
れるオブジェクトです。)
ActionServletはActionオブジェクト(これにはActionのサブクラスのオブジェク
トも含まれる)のexecuteメソッドを実行して、その戻り値(ActionMapping型)
を受け取り、戻り値(ActionMapping型オブジェクト)のforwardフィールドの値を
struts-config.xmlの中のforwardタグのname属性、すなわち、先ほどの

            <forward name="success" path="/jsp/simple/Simple.jsp"/>

という行に記述されている"success"という値と照合して、一致していれば
/jsp/simple/Simple.jspから作成したWebページに遷移しようとします。

この、ActionMappingオブジェクトのforwardフィールドに値を設定するため
のメソッドが先ほどのfindForwardというメソッドです。

なお、Actionオブジェクトのexecuteメソッドの処理結果によって"success"以外の
値を返す場合には、struts-config.xmlの中にそのためのforwardタグを追加して
おく必要があります。
たとえば、

--------------------------------------------------------
        <action path="/prepareSimple"
                type="examples.SuccessAction">
            <forward name="success" path="/jsp/simple/Simple.jsp"/>
            <forward name="tano_baai" path="/jsp/simple/TaNoBaai.jsp"/>
        </action>
--------------------------------------------------------

というような感じになります。


では、/jsp/simple/Simple.jspのソース・コードを見てみましょう。
今までに出てこなかった新しいタグがいっぱい使われていますね。これらはJSPの
カスタム・タグ・ライブラリーという機能を使ってStrutsが独自に定義したタグ
がふんだんに使われているのですが、詳しいことは後で説明することにします。
今回は、とりあえず

--------------------------------------------------------
<html:form action="/processSimple">
<p>* What's your first name?:<br/><html:text property="name" size="40" maxlength="50"/></p>
<p>* Enter a secret word or phrase:<br/><html:password property="secret" size="40" maxlength="50"/></p>
<p>What is your favorite color?:<br/>
  <html:select property="color">
    <html:option value="red">Red</html:option>
    <html:option value="green">Green</html:option>
    <html:option value="blue">Blue</html:option>
  </html:select>
    </p>
<p><html:checkbox property="confirm"/>Is that really your favorite color?</p>
<p>How much do you like your chosen color?:<br />
<html:radio property="rating" value="1">Actually, I hate it.</html:radio><br />
<html:radio property="rating" value="2">Not so much.</html:radio><br />
<html:radio property="rating" value="3">I'm indifferent</html:radio><br />
<html:radio property="rating" value="4">It's pretty neat</html:radio><br />
<html:radio property="rating" value="5">I painted my whole house with it.</html:radio>
</p>
<p>Enter a message (you may use html tags):<br />
<html:textarea property="message" cols="40" rows="6"/>
</p>
<html:hidden property="hidden" value="Sssh! It's a secret. Nobody knows I'm here."/>
<hr noshade="noshade" />  
<p>
<html:submit>
<bean:message key="button.submit" />
</html:submit>
<html:cancel/>
</p>
</html:form>
--------------------------------------------------------

の部分に注目してください。ここでhtml:formというタグはHTMLのFORMタグに相当
するStruts専用のタグです。また、html:textというタグはHTMLのINPUT type="text"
に相当するStruts専用のタグです。また、html:submitやhtml:cancelというタグは、
HTMLのINPUT type="button"に相当するStruts専用のタグです。
そうやって見ていくと、何となくこれらの行の意味がわかってくるのではないで
しょうか。詳しいことは後で説明することにしても、とりあえず

What's your first name?:

という文字列が並んでいるあたりから、前回、適当に自分の名前(英文字で)の入力
や選択などを行ったページの内容であることがわかりますね。


このWebページで入力を行った後、submitボタンをクリックすると、

<html:form action="/processSimple">

という行で指定されている/processSimpleという文字列にしたがって、/processSimple.do
がURLの末尾に設定されてActionServletが呼び出されることになります(URLとしては
action属性の値にさらに.doが付加されます)。

すると、ActionServletは、/processSimpleというパスを、またまたstruts-config.xml
の中から探して来ます。

実際にstruts-config.xmlの中を見ると

--------------------------------------------------------
        <action path="/processSimple"
                type="examples.simple.ProcessSimpleAction"
                name="simpleForm"
                scope="request"
                input="/jsp/simple/Simple.jsp"
                cancellable="true"
                validate="true">
            <forward name="success" path="/jsp/simple/SimpleResults.jsp"/>
        </action>
--------------------------------------------------------

という行がありますね。
したがって、examples.simple.ProcessSimpleActionのexecuteメソッドが呼び出さ
れることになります。
このとき同時に、

                name="simpleForm"

という行があることにも注目してください。
このsimpleFormという名前は、ずっと上のほうに

        <form-bean name="simpleForm" type="examples.simple.SimpleActionForm"/>

というタグで定義されています。つまり、examples.simple.SimpleActionFormという
クラス名のBeanにsimpleFormという名前を付けてあるのです。

そして、上のstruts-config.xmlの指定に従うと、このSimpleActionFormは、
requestオブジェクト(Webブラウザーから送られてきたデータを保持する
HttpServletRequest型のオブジェクト)の中から取り出したFORMのデータを
取り込んだ状態でProcessSimpleActionのexecuteメソッドに(引数として)渡され
ることになります。
(このexecuteメソッドの引数として渡す作業はActionServletが行ってくれます。)

それともう一つ、

                input="/jsp/simple/Simple.jsp"

という行と

                validate="true">

という行にも注目してください。
このvalidate="true"というのは、さきほどのFORMのデータ(simpleFormオブジェクト)
に対して、データの妥当性チェックを行うことを指定しており、
input="/jsp/simple/Simple.jsp"というのはその妥当性チェックの結果に問題(不正)
があった場合の遷移先を指定しますが、これも後で説明します。

あと、

                cancellable="true"

というのは、cancelボタンを使ってキャンセルができるように指定するものです。



では、ProcessSimpleActionクラスのソース・コードを見てみましょう。
executeメソッドは

--------------------------------------------------------
    public ActionForward execute(
        ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {

        // If user pressed 'Cancel' button,
        // return to home page
        if (isCancelled(request)) {
            return mapping.findForward("home");
        }

        // Forward to result page
        return mapping.findForward("success");
    }
--------------------------------------------------------

というようにコーディングされていますが、このうち引数の
        ActionForm form,
というところに先ほどのsimpleFormオブジェクトが渡されます。(後でわかる
ようにsimpleFormオブジェクト、すなわちSimpleActionFormクラスはActionForm
のサブクラスとして作成されているものです。)

そして、

        if (isCancelled(request)) {
            return mapping.findForward("home");
        }

という行は、cancelボタンがクリックされた場合にforwardに"home"を設定
してreturnすることを指定しています。

また、cancelボタンがクリックされなかった場合(submitボタンがクリックさ
れた場合)には、その下の

        return mapping.findForward("success");

が実行され、forwardに"success"が設定されてreturnすることになります。

では、再度struts-config.xmlの中を見てください。

--------------------------------------------------------
    <global-forwards>
        <forward name="home" path="/Home.do"/>
    </global-forwards>
--------------------------------------------------------

という行がありますね。このglobal-forwardsというのは、個別のactionタグに指定
されていないforward値に対して判定が下されるもので、ここではforward値が"home"
のときには、URLに/Home.doを指定(forwardタグの中のpath属性の場合は現実のURL
に即した記述が必要なので.doを付ける)してサーブレットを呼び出すことを指定
しています。

このURLの/Home.doに対して、ActionServletは、さらにその下にある

--------------------------------------------------------
    <action path="/Home" type="examples.SuccessAction">
        <forward name="success" path="/index.jsp" redirect="true"/>
    </action>
--------------------------------------------------------

という行を見つけて、examples.SuccessActionのexecuteメソッドを呼び出すことに
なります。(actionタグの中のpath属性の場合は.doを付けない。)

一方、forward値が"success"の場合には、先ほどの

--------------------------------------------------------
        <action path="/processSimple"
                type="examples.simple.ProcessSimpleAction"
                name="simpleForm"
                scope="request"
                input="/jsp/simple/Simple.jsp"
                cancellable="true"
                validate="true">
            <forward name="success" path="/jsp/simple/SimpleResults.jsp"/>
        </action>
--------------------------------------------------------

の中にある

            <forward name="success" path="/jsp/simple/SimpleResults.jsp"/>

の記述に従って、/jsp/simple/SimpleResults.jspが呼び出されてWebページが遷移
することになります。

SimpleResults.jspでは、先ほどのsimpleFormに保持されているFORMのデータを
Webページに表示すべくStruts特有のタグがたくさん使われていますが、詳しい
ことは後述します。


では、続いてSimpleActionFormクラスのソース・コードを見てみましょう。


(続く)


では、今日はここまでにします。

何か、わからないところがありましたら、下記のWebページまで質問を
お寄せください。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2008 Future Lifestyle Inc. 不許無断複製