Top > MyPage
 

strutsの基本の基本

とりあえず詳細は避けて、とりあえず動かして、だいたいの流れを押さえましょう!

strutsの動作確認

ここでは次のような簡単な、アプリケーションを作成して、しっかり動くかどうかと、strutsを使ったアプリケーションの作成のだいたいの手順を覚えてしまおう(実際のもっと難しい話はまた後で)。

  1. htmlのフィールドが1つしかないフォームに名前を入力させて、実行ボタンをクリックする。
  2. そしたら、「こんにちは、???さん」というページに遷移する(???のところに、先ほどの名前が入る)。
  3. もし、フォームに何も入れないか、或いは11文字以上が入力されたら、エラーページに遷移して、そのエラーの種類を提示する。

たったこれだけのアプリケーション。逆にこんなに単純なものを作成するのに結構面倒だな、というのが大方の感想かもしれませんが、そんな単純な内容の仕事などないでしょうし、複雑なものを作る場合には、ある程度の手順というものがあった方が結局楽だったりするわけで、特に後半は「お決まり」ということで手順を覚えてください。

いずれにしろ、今回は次の点をしっかり(このページ以外の本や他のホームページで)勉強してください。

  1. web.xmlの書き方
  2. struts-config.xmlの書き方
  3. strutsのactionの書き方
  4. strutsのformの書き方
  5. actionとformの関係
  6. validate(入力された値の検証)の仕方
  7. JSPの書き方
  8. strutsのJSPにおけるタグの書き方

ダウンロードと展開

まずはstrutsのダウンロードサイトにアクセスし、jakarta-struts-1.2.4.tar.gzをダウンロード。

これをどこか適当なところに解凍しておく。

eclipseで新規プロジェクト

eclipseのFileメニューから、新規->プロジェクトを選んで、

  • Tomcatプロジェクトを選び、 新規プロジェクト1
  • プロジェクト名をwebcmsに(とりあえず)して、 新規プロジェクト3
  • とにかく終了ボタンを押す。

新規プロジェクト3

すると、次のような(ちょっと見づらいけれど)webcmsというのがナビゲータに現れます。

新規プロジェクト4

web.xmlの作成

eclipseのxml用のプラグイン(EclipseHTMLEditor)をインストール

web.xmlなどを編集するのに(別にエディタでもかまわないので、必要を感じなければここは飛ばしてOK)、

eclipseプラグインXmlエディタ(あまてらす)

からtk.eclipse.plugin.htmleditor_1.6.4.zipをダウンロード、そして

c:/eclipseに展開。eclipseが立ち上がっている場合には、再起動。

実際の作成

eclipseのメニューから(自分のエディタを使う場合は下のものを全てコピペしてもOK)

新規->その他->HTML->xml

を選び、ファイル名をweb.xmlと入力して、「次へ」をクリック。

次に、DTDを公開するをチェックし、

公開ID:-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN

システムID:http://java.sun.com/dtd/web-app_2_3.dtd

と入力して、終了ボタンをクリックすると、次のようなファイルができる。

 
<?xml version="1.0" encoding="Windows-31J"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
</web-app> 

encodingはMS932などとなっている可能性もありますが、それはeclipseのデフォルトのencodingで、むしろそのeclipseのencodingを変更した方がよいかも(ただし変更の際、選択肢にないので直接入力する必要があります。

これに、最低限の設定をまず書き込んでいく。実際には、以下のようになります(多少の説明は後にします)。

 
<?xml version="1.0" encoding="Windows-31J"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems,
  Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <display-name>Web CMS</display-name>
  <description>
    Web CMS created by Chikkun with Tomcat and Struts
  </description>
  <filter>
    <filter-name>Set Character Encoding</filter-name>
    <description>character_encoding></description>
<filter-class>com.chikkun.common.SetCharacterEncodingFilter</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>Windows-31J</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>Set Character Encoding</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<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>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>/action/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<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-bean.tld</taglib-uri>
  <taglib-location>/WEB-INF/struts-bean.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/pager-taglib.tld</taglib-uri>
  <taglib-location>/WEB-INF/pager-taglib.tld</taglib-location>
</taglib>
<taglib>
  <taglib-uri>/WEB-INF/struts-nested.tld</taglib-uri>
  <taglib-location>/WEB-INF/struts-nested.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-app>
 
  • display-nameとdescriptionタグは「Tomcat Webアプリケーションマネージャ」に使われる。

    下の表示名。

    Tomcat

  • filterというのは、ここでは詳しくは触れませんが、これを書いておき、後述する実際のfilterというクラスを作ると、日本語が化けなくてみんな幸せになれるのでした。

  • servletは今回のstrutsのミソ。これによって、strutsによるservletを起動する。

     
    <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>
      </init-param>
      <load-on-startup>1</load-on-startup>
    </servlet>
     
  • welcome-file-listは単に、apacheの

     DirectoryIndex index.php index.html index.html.var 
  • taglibはstrutsのタグライブラリを使うためのもの。

struts-config.xmlの作成

blankのコピー

これは、最初から作るのが面倒なので、このページの最初にダウンロードし、展開しておいたjakarta-struts-1.2.4.tar.gzの中の

jakarta-struts-1.2.4/webapps/struts-blank.war

をさらに展開する。このwarという拡張子のファイルも圧縮してあるので、適当なところで展開。これにはコマンドラインで、

jar xvf struts-examples.war

で展開される。そうすると

  • pages

  • WEB-INF

  • META-INF

という3つのディレクトリーができていて、このなかのWEB-INF以下のファイル・ディレクトーを全て(ただし、先ほど作成したweb.xmlを除く!!)

C:\eclipse\workspace\webcms\WEB-INF

以下にコピーしてしまう。

struts-config.xmlの編集

eclipse/workspace/webcms/WEB-INFstruts-config.xmlがあるので、これを編集します。最初は以下のようになっています。

作成するソースは全てで4つ。

HelloWorldAction
これが実際のアプリケーション
HelloWorldActionForm
これは値を保存するbean
HelloWorldMenuAction
単にhtmlのformを表示させる中身のないaction
SetCharacterEncodingFilter
文字化けしないようにするfilter
 
<?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">
<!--
     This is a blank Struts configuration file with an example
     welcome action/page and other commented sample elements.

Tiles and the Struts Validator are configured using the factory defaults
     and are ready-to-use.

NOTE: If you have a generator tool to create the corresponding Java classes
for you, you could include the details in the "form-bean" declarations.
Otherwise, you would only define the "form-bean" element itself, with the
     corresponding "name" and "type" attributes, as shown here.
-->
<struts-config>
<!-- ======================================= Data Source Configuration -->
<!--
<data-sources>
<data-source type="org.apache.commons.dbcp.BasicDataSource">
    <set-property
      property="driverClassName"
      value="org.postgresql.Driver" />
    <set-property
      property="url"
      value="jdbc:postgresql://localhost/mydatabase" />
    <set-property
      property="username"
      value="me" />
    <set-property
      property="password"
      value="test" />
    <set-property
      property="maxActive"
      value="10" />
    <set-property
      property="maxWait"
      value="5000" />
    <set-property
      property="defaultAutoCommit"
      value="false" />
    <set-property
      property="defaultReadOnly"
      value="false" />
    <set-property
      property="validationQuery"
      value="SELECT COUNT(*) FROM market" />
</data-source>
</data-sources>
-->
<!-- =========================================== Form Bean Definitions -->
    <form-beans>
    <!-- sample form bean descriptor for an ActionForm
        <form-bean
            name="inputForm"
            type="app.InputForm"/>
    end sample -->
    <!-- sample form bean descriptor for a DynaActionForm
        <form-bean
            name="logonForm"
            type="org.apache.struts.action.DynaActionForm">
            <form-property
                name="username"
                type="java.lang.String"/>
            <form-property
                name="password"
                type="java.lang.String"/>
       </form-bean>
    end sample -->
    </form-beans>
<!-- ==================================== Global Exception Definitions -->
    <global-exceptions>
        <!-- sample exception handler
        <exception
            key="expired.password"
            type="app.ExpiredPasswordException"
            path="/changePassword.jsp"/>
        end sample -->
    </global-exceptions>
<!-- ==================================== Global Forward Definitions -->
    <global-forwards>
        <!-- Default forward to "Welcome" action -->
        <!-- Demonstrates using index.jsp to forward -->
        <forward
            name="welcome"
            path="/Welcome.do"/>
    </global-forwards>
<!-- ====================================== Action Mapping Definitions -->
    <action-mappings>
            <!-- Default "Welcome" action -->
            <!-- Forwards to Welcome.jsp -->
        <action
            path="/Welcome"
            forward="/pages/Welcome.jsp"/>
    <!-- sample input and input submit actions
        <action
            path="/Input"
            type="org.apache.struts.actions.ForwardAction"
            parameter="/pages/Input.jsp"/>
        <action
            path="/InputSubmit"
            type="app.InputAction"
            name="inputForm"
            scope="request"
            validate="true"
            input="/pages/Input.jsp"/>
            <action
                path="/edit*"
                type="app.Edit{1}Action"
                name="inputForm"
                scope="request"
                validate="true"
                input="/pages/Edit{1}.jsp"/>
    end samples -->
    </action-mappings>
<!-- ======================================== Controller Configuration -->
    <controller
       processorClass="org.apache.struts.tiles.TilesRequestProcessor"/>
<!-- =================================== Message Resources Definitions -->
    <message-resources parameter="MessageResources" />
<!-- ========================================== Plug Ins Configuration -->
  <!-- ================================================== Tiles plugin -->
  <!--
This plugin initialize Tiles definition factory. This later can takes some
    parameters explained here after. The plugin first read parameters from
web.xml, thenoverload them with parameters defined here. All parameters
       are optional.
     The plugin should be declared in each struts-config file.
       - definitions-config: (optional)
            Specify configuration file names. There can be several comma
                  separated file names (default: ?? )
       - moduleAware: (optional - struts1.1)
Specify if the Tiles definition factory is module aware. If true
            (default), there will be one factory for each Struts module.
If false, there will be one common factory for all module. In this
later case, it is still needed to declare one plugin per module.
The factory will be initialized with parameters found in the first
initialized plugin (generally the one associated with the default
            module).
                        true : One factory per module. (default)
                        false : one single shared factory for all modules
         - definitions-parser-validate: (optional)
Specify if xml parser should validate the Tiles configuration file.
true : validate. DTD should be specified in file header (default)
                        false : no validation
        Paths found in Tiles definitions are relative to the main context.
  -->
    <plug-in className="org.apache.struts.tiles.TilesPlugin" >
      <!-- Path to XML definition file -->
      <set-property property="definitions-config"
                       value="/WEB-INF/tiles-defs.xml" />
      <!-- Set Module-awareness to true -->
      <set-property property="moduleAware" value="true" />
    </plug-in>
<!-- ================================================ Validator plugin -->
  <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>
 

ほとんどがコメントアウトされているので、見やすくするために以下のように、すっきりさせましょう(コピペしてOK)。

 
<?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 Bean Definitions -->
    <form-beans>
        <form-bean
            name="logonForm"
            type="org.apache.struts.action.DynaActionForm">
       </form-bean>
    </form-beans>
<!-- ======================================= Action Mapping Definitions -->
    <action-mappings>
        <action
            path="/InputSubmit"
            type="app.InputAction"
            name="inputForm"
            scope="request"
            validate="true"
            input="/pages/Input.jsp"/>
   </action-mappings>
<!-- ==================================== Message Resources Definitions -->
    <message-resources parameter="MessageResources" />
<!-- ================================================= Validator plugin -->
  <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 version="1.0" encoding="ISO-8859-1" ?> 
						

 <?xml version="1.0" encoding="Windows-31J"?> 
						

にします。

form-beanの書き換え

  1. form-beanタグの中の「name="logonForm"」を「name="helloWorldForm"」。このnameが論理名(これがわかりづらい呼び名ですが、単なる名前ということ---クラス名は長いので)。
  2. 「type="org.apache.struts.action.DynaActionForm">」を「type="com.chikkun.webcms.test.HelloWorldActionForm">」にします。このtypeは実際のクラス名。

つまり

 
<form-beans>
    <form-bean
        name="logonForm"
        type="org.apache.struts.action.DynaActionForm">
   </form-bean>
</form-beans>	
 

 
<form-beans>
    <form-bean
        name="helloWorldForm"
        type="com.chikkun.webcms.test.HelloWorldActionForm">
   </form-bean>
</form-beans>
 

になります。

actionの書き換え

  1. 「path="/InputSubmit"」を「path="/helloWorld"」に。このpathはブラウザでhttp://localhost:8080/webcms/action/helloWorldとすると、このJavaのアプリケーションが実行されることを意味します。
  2. 「type="app.InputAction"」を「type="com.chikkun.webcms.test.HelloWorldAction"」にします。これが、この後作成するJavaのクラス名になります。
  3. 「name="inputForm"」を「name="helloWorldForm"」に。これは先ほどのform-beanの時の論理名になります。
  4. scopeとvalidateはそのまま。
  5. 「input="/pages/Input.jsp"」を「input="/WEB-INF/jsp/input.jsp"」にします。これはどこでも良いのですが、WEB-INF以下のファイルは直接ユーザは見ることができないので、セキュリティ上、とりあえず、そうしておきます。このinputというのは、そのすぐ上の「validate="true"」になっていて、validateしたときにひっかかった場合の遷移先になります。今回は最初のフォームのページと同じにしてあります。

そしてもう1つ。単にhtmlのフォームを表示させるためのHelloWorldMenuActionについても追加します。

 
<action-mappings>
    <action
        path="/InputSubmit"
        type="app.InputAction"
        name="inputForm"
        scope="request"
        validate="true"
        input="/pages/Input.jsp"/>

</action-mappings>
 

 
<action-mappings>
    <action
        path="/helloWorld"
        type="com.chikkun.webcms.test.HelloWorldAction"
        name="helloWorldForm"
        scope="request"
        validate="true"
        input="/WEB-INF/jsp/input.jsp">
         <forward
           name="success"
           path="/WEB-INF/jsp/hello.jsp"
           redirect="false"/>
    </action>

    <action
        path="/helloWorldMenu"
        type="com.chikkun.webcms.test.HelloWorldMenuAction"
        scope="request" >
         <forward
           name="success"
           path="/WEB-INF/jsp/input.jsp"
           redirect="false"/>
    </action>

</action-mappings>
 

となります。

ApplicationResourcesの名前、パスの変更

 
<message-resources parameter="MessageResources" />
 

 
<message-resources parameter="Resources.ApplicationResources"/>
 

に変更します。これは、アプリケーションからここに書かれてある設定の値などを取り出すためのファイルで、詳細は実際作る場面で説明します。

最終的なstruts-config.xml

 
<?xml version="1.0" encoding="Windows-31J"?>

<!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 Bean Definitions -->

    <form-beans>
        <form-bean
            name="helloWorldForm"
            type="com.chikkun.webcms.test.HelloWorldActionForm">
       </form-bean>
    </form-beans>

<!-- ====================================== Action Mapping Definitions -->

    <action-mappings>
        <action
            path="/helloWorld"
            type="com.chikkun.webcms.test.HelloWorldAction"
            name="helloWorldForm"
            scope="request"
            validate="true"
            input="/WEB-INF/jsp/input.jsp">
             <forward
               name="success"
               path="/WEB-INF/jsp/hello.jsp"
               redirect="false"/>
        </action>

        <action
            path="/helloWorldMenu"
            type="com.chikkun.webcms.test.HelloWorldMenuAction"
            scope="request" >
             <forward
               name="success"
               path="/WEB-INF/jsp/input.jsp"
               redirect="false"/>
        </action>

   </action-mappings>

<!-- ================================== Message Resources Definitions -->

   <message-resources parameter="Resources.ApplicationResources"/>

<!-- =============================================== Validator plugin -->

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

eclipseのクラスパスの設定

さて、あとはクラスを作成して、validationのルールを作って、ApplicationResources.propertiesを書き、さらにjspファイルを2つ作ります。その前にクラスパスの設定。

更新&ファイル選択

まずは、先ほどblankを解凍して、WEB-INF以下をコピーしたので、ファイルの中身が変わっていることをeclipseに知らせるために、カーソルをwebcms(上記の赤いところを)にしてから「f5」か右クリックして「更新」を選択します。

次に、同様に右クリックして、一番下にある「プロパティ」を選択。上から4つめにある「Java Build Path」を選択。そして右に方にある、「add JARs」を選択して、webcms->WEB-INF->libにあるファイルを全て(shiftなどを使って)選択してOKをクリックする。

チェックマークを入れる

さらに、一番右にある、Order and Exportを選択して、チェックマークの入っていないものを全てチェックを入れて(とりあえず順番は変えなくても大丈夫)、「OK」ボタンをで、設定終了。

classの作成

これで一応開発環境はそろったので、いよいよソースの作成。

まずはパッケージの作成

webcms/WEB-INF/srcで右クリックして、新規->packageを選択して、

パッケージの新規作成

「com.chikkun.webcms.test」と入力して、終了。

パッケージの入力

actionのひな形作成

通常strutsではactionというのが、実際のアプリケーションで、formといのがactionの補助となる値などを格納するもの。そのactionを作成しよう。

先ほど作ったパッケージのtestというところで右クリックして、新規->Classを選択。デフォルトでは以下のような中身のものができているはず(多少環境によって違うかもしれないし、また、コメントは変えられるので、いずれ変えた方がよい。)。

 
/*
 * Created on 2005/05/07
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.chikkun.webcms.test;

/**
 * @author Administrator
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class HelloWorldAction {

}
						</source>
<p class="subsection">
この
</p>
<source>
public class HelloWorldAction {

}
</source>
<p class="subsection">
を
</p>
<source>
public class HelloWorldAction extends Action{

}
 

に書き加える。そうすると、Actionのところで、赤い波線が出るけれど、これは「Actionって何」とeclipseがわからないので、怒っている。その怒りを静めるために、ソースの画面の中で、右クリックして、Source->Organize Importを選択し(ショートカットもある!)、org.apache.struts.action.Actionを選択して、終了させると、荒ぶるeclipseが静まる(実際にはライブラリーが必要なので、それをimportする文を挿入してくれる---import org.apache.struts.action.Action;)。

次に、

 
public ActionForward execute(ActionMapping mapping, ActionForm actionForm,
        HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException {

    return mapping.findForward("success");
}
</source>
<p class="subsection">
をクラス内に挿入。ここでも赤い波線の嵐。同様に、Source-&gt;Organize Importを実行する。
</p>
<p class="subsection">
その結果以下のようになっているはずです。
</p>
<source>
/*
 * Created on 2005/05/07
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.chikkun.webcms.test;

import java.io.IOException;

import javax.servlet.ServletException;
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;

/**
 * @author Administrator
 * 
 * TODO To change the template for this generated type comment go to Window 
 * Preferences - Java - Code Style - Code Templates
 */
public class HelloWorldAction extends Action {

    public ActionForward execute(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

        return mapping.findForward("success");
    }

}
 

これで、中身がないactionが出来た。そして、フォーム表示用のHelloWorldMenuActionも作成します。

そこでformのひな形を作ります。

formのひな形作成

先ほどのactionとほぼ同様に「HelloWorldActionForm」という名前のクラスを作成。クラス名だけが違うけれど、ほとんどactionと同じファイルが出来たはず(以下)。

 
/*
 * Created on 2005/05/07
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.chikkun.webcms.test;

/**
 * @author Administrator
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class HelloWorldActionForm {

}
</source>
<p class="subsection">
この
</p>
<source>
public class HelloWorldActionForm extends ValidatorForm{

}
 

を書き加える。またeclipseが怒るけれど、Source->Organize Importで静める(今回は他に同名のクラスがないので、すぐにimport文が挿入されると思う)---「静める」は「鎮める」かな(--;)?。

formを完成させる

今回は名前をフォームから取得するだけですが、それではあまりにも悲しいので、次のものを入力します

 
//名前格納用
private String name = null;

//ipアドレス格納用
private String ip = null;

//以降日付など
private String year = null;
private String month = null;
private String day = null;
private String hour = null;
private String minute = null;
private String second = null;
private String aDayOfTheWeek = null;
 

これだけだと、単に変数の宣言だけですので、これに対する、setter、getterメソッドを作成します。詳細は避けますが、直接他のクラスから、このformの変数にアクセスできないようにして(private)、値を入力するsetterと値を取得するメソッドを通じて値のやりとりをします。

また、このsetterがあると、strutsが自動的に名前を入力するフォームから名前を代入してくれます。

さてそれらのメソッドはeclipseのソースの画面上で、Source->Generate Setters and Gettersを選択すると、自動でそれらを作ってくれます。

以下のようなソースが出来ていればOK。

 
/*
 * Created on 2005/05/07
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.chikkun.webcms.test;

import org.apache.struts.validator.ValidatorForm;

/**
 * @author Administrator
 * 
 * TODO To change the template for this generated type comment go to Window
 * Preferences - Java - Code Style - Code Templates
 */
public class HelloWorldActionForm extends ValidatorForm {


    //  名前格納用(validationをかける)
    private String name = null;

    //    ipアドレス格納用
    private String ip = null;

    //    以降日付など
    private String year = null;

    private String month = null;

    private String day = null;

    private String hour = null;

    private String minute = null;

    private String second = null;

    private String dayOfTheWeek = null;
    /**
     * @return Returns the aDayOfTheWeek.
     */
    public String getDayOfTheWeek() {
        return dayOfTheWeek;
    }
    /**
     * @param dayOfTheWeek The aDayOfTheWeek to set.
     */
    public void setDayOfTheWeek(String dayOfTheWeek) {
        this.dayOfTheWeek = dayOfTheWeek;
    }
    /**
     * @return Returns the day.
     */
    public String getDay() {
        return day;
    }

    /**
     * @param day
     *            The day to set.
     */
    public void setDay(String day) {
        this.day = day;
    }

    /**
     * @return Returns the ip.
     */
    public String getIp() {
        return ip;
    }

    /**
     * @param ip
     *            The ip to set.
     */
    public void setIp(String ip) {
        this.ip = ip;
    }

    /**
     * @return Returns the minute.
     */
    public String getMinute() {
        return minute;
    }

    /**
     * @param minute
     *            The minute to set.
     */
    public void setMinute(String minute) {
        this.minute = minute;
    }

    /**
     * @return Returns the month.
     */
    public String getMonth() {
        return month;
    }

    /**
     * @param month
     *            The month to set.
     */
    public void setMonth(String month) {
        this.month = month;
    }

    /**
     * @return Returns the name.
     */
    public String getName() {
        return name;
    }

    /**
     * @param name
     *            The name to set.
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return Returns the second.
     */
    public String getSecond() {
        return second;
    }

    /**
     * @param second
     *            The second to set.
     */
    public void setSecond(String second) {
        this.second = second;
    }

    /**
     * @return Returns the year.
     */
    public String getYear() {
        return year;
    }

    /**
     * @param year The year to set.
     */
    public void setYear(String year) {
        this.year = year;
    }
    /**
     * @return Returns the hour.
     */
    public String getHour() {
        return hour;
    }
    /**
     * @param hour The hour to set.
     */
    public void setHour(String hour) {
        this.hour = hour;
    }
} 
 

そうそう、言い忘れていましたが、eclipseは確かデフォルトでファイルを保存すると、自動でコンパイルしてしまいます。コンピュータが非力な場合は変更した方が良いかもしれません(projectメニューの「自動でビルド」のチェックをはずせば良い)。ただしそのときはソースを書き終えたら、必ずコンパイルしてください。

actionを完成させる。

とりあえず、htmlのフォームで入力された名前はHelloWorldActionFormのnameというプロパティへ代入されているので、それ以外の日付などをここでformにセットしよう。

また、ここでは本来はactionを分けた方がよいのかもしれないのですが、別に作るのも面倒だし、セッションの勉強にもなるので、sessionがあったら初めてアクセスなので、htmlのフォームへforwardさせ、そうでないときは処理をして「こんにちは、???さん」のページへ飛ばします。時々入力していると「赤い波線」が出ますが、無視してやっていて、消えないときは

  • 入力ミス
  • import文がない

入力ミスはいいとして、import文は、例えば、下のCalendarなどというクラスを使うときに必要なるので、import文を書く。これはいつもの「Source->Generate Setters and Getters」をすると、自動で書き込んでくれる。

でき上がったものは以下のよう。

 
/*
 * Created on 2005/05/07
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.chikkun.webcms.test;

import java.io.IOException;
import java.util.Calendar;

import javax.servlet.ServletException;
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;

/**
 * @author Administrator
 * 
 * TODO To change the template for this generated type comment go to Window
 * Preferences - Java - Code Style - Code Templates
 */
public class HelloWorldAction extends Action {

    public ActionForward execute(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        //strutsがアクションフォームのインスタンスをactionFormにセットしているので、それをキャストして取得。
        HelloWorldActionForm form = (HelloWorldActionForm) actionForm;

        //今日の日付を取得するため
        Calendar cal = Calendar.getInstance();

        //formに年をセット(int型をString型にキャスト・・・「+ ""」でもOK)
        form.setYear(Integer.toString(cal.get(Calendar.YEAR)));
        //formに月をセット、ただし月は0が1月なので1を足している
        form.setMonth(Integer.toString(cal.get(Calendar.MONTH) + 1));
        //formに日にちをセット    

        form.setDay(Integer.toString(cal.get(Calendar.DATE)));
        //formに時刻をセット
        form.setHour(Integer.toString(cal.get(Calendar.HOUR_OF_DAY)));
        //formに分をセット
        form.setMinute(Integer.toString(cal.get(Calendar.MINUTE)));
        //formに秒をセット
        form.setSecond(Integer.toString(cal.get(Calendar.SECOND)));
        //曜日を配列に入れて
        String[] aDayOfTheWeek = { "日", "月", "火", "水", "木", "金", "土" };
        //formに曜日をセット
        form.setDayOfTheWeek(aDayOfTheWeek[cal.get(Calendar.DAY_OF_WEEK)]);

        //処理が終わったのでstruts-config.xmlで定義したsuccessへforward

        return mapping.findForward("success");
    }

}
 

もう1つのは(フォーム表示用)全くひな形のままでOK。つまり

 
/*
 * Created on 2005/05/09
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.chikkun.webcms.test;

import java.io.IOException;

import javax.servlet.ServletException;
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;

/**
 * @author Administrator
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class HelloWorldMenuAction extends Action{

    public ActionForward execute(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

        return mapping.findForward("success");
    }
}
 

filterを作成

先ほども簡単に触れた文字化け防止用のfilter。これは

WEB-INF/src/com/chikkun/common

というディレクトリを作成して、そこに次のようなソースを書き込みます。人様の作成したものなので、コメントが多いけれど、そのまま載せます。これをコピペしてください(もちろんコンパイルも)。

 
/*
 * $Header: /var/cvs/SDOC/src/documentation/content/xdocs/und/document/java/primary/struts.xml,v 1.1 2009/08/24 08:37:10 chikkun Exp $
 * $Revision: 1.1 $
 * $Date: 2009/08/24 08:37:10 $
 *
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * [Additional notices, if required by prior licensing conditions]
 *
 */
package com.chikkun.common;


import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;


/**
 * <p>Example filter that sets the character encoding to be used in parsing the
 * incoming request, either unconditionally or only if the client did not
 * specify a character encoding.  Configuration of this filter is based on
 * the following initialization parameters:</p>
 * <ul>
 * <li><strong>encoding</strong> - The character encoding to be configured
 *     for this request, either conditionally or unconditionally based on
 *     the <code>ignore</code> initialization parameter.  This parameter
 *     is required, so there is no default.</li>
 * <li><strong>ignore</strong> - If set to "true", any character encoding
 *     specified by the client is ignored, and the value returned by the
 *     <code>selectEncoding()</code> method is set.  If set to "false,
 *     <code>selectEncoding()</code> is called <strong>only</strong> if the
 *     client has not already specified an encoding.  By default, this
 *     parameter is set to "true".</li>
 * </ul>
 *
 * <p>Although this filter can be used unchanged, it is also easy to
 * subclass it and make the <code>selectEncoding()</code> method more
 * intelligent about what encoding to choose, based on characteristics of
 * the incoming request (such as the values of the <code>Accept-Language</code>
 * and <code>User-Agent</code> headers, or a value stashed in the current
 * user's session.</p>
 *
 * @author Craig McClanahan
 * @version $Revision: 1.1 $ $Date: 2009/08/24 08:37:10 $
 * @web.filter
 *    description="character encoding"
 *    name="Set Character Encoding"
 * @web.filter-init-param
 *    name="encoding"
 *    value="Windows-31J"
 * @web.filter-mapping
 *    url-pattern="/*"
 *    servlet-name="Set Character Encoding"
 */
public class SetCharacterEncodingFilter implements Filter {


    // ----------------------------------------------------- Instance Variables


    /**
     * The default character encoding to set for requests that pass through
     * this filter.
     */
    protected String encoding = null;


    /**
     * The filter configuration object we are associated with.  If this value
     * is null, this filter instance is not currently configured.
     */
    protected FilterConfig filterConfig = null;


    /**
     * Should a character encoding specified by the client be ignored?
     */
    protected boolean ignore = true;


    // --------------------------------------------------------- Public Methods


    /**
     * Take this filter out of service.
     */
    public void destroy() {

        this.encoding = null;
        this.filterConfig = null;

    }


    /**
     * Select and set (if specified) the character encoding to be used to
     * interpret request parameters for this request.
     *
     * @param request The servlet request we are processing
     * @param result The servlet response we are creating
     * @param chain The filter chain we are processing
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
	throws IOException, ServletException {

        // Conditionally select and set the character encoding to be used
        if (ignore || (request.getCharacterEncoding() == null)) {
            String encoding = selectEncoding(request);
            if (encoding != null)
                request.setCharacterEncoding(encoding);
        }
        
	// Pass control on to the next filter
        chain.doFilter(request, response);

    }


    /**
     * Place this filter into service.
     *
     * @param filterConfig The filter configuration object
     */
    public void init(FilterConfig filterConfig) throws ServletException {

	this.filterConfig = filterConfig;
        this.encoding = filterConfig.getInitParameter("encoding");
        String value = filterConfig.getInitParameter("ignore");
        if (value == null)
            this.ignore = true;
        else if (value.equalsIgnoreCase("true"))
            this.ignore = true;
        else if (value.equalsIgnoreCase("yes"))
            this.ignore = true;
        else
            this.ignore = false;

    }


    // ------------------------------------------------------ Protected Methods


    /**
     * Select an appropriate character encoding to be used, based on the
     * characteristics of the current request and/or filter initialization
     * parameters.  If no character encoding should be set, return
     * <code>null</code>.
     * <p>
     * The default implementation unconditionally returns the value configured
     * by the <strong>encoding</strong> initialization parameter for this
     * filter.
     *
     * @param request The servlet request we are processing
     */
    protected String selectEncoding(ServletRequest request) {

        return (this.encoding);

    }


}

 

次はvalidation.xml

何度か出てきた最初の頃に解凍したblankをWEB-INF以下をコピーした際、その中にvalidation.xmlのひな形があるので、それを編集します。

最初のひな形は

 
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE form-validation PUBLIC
          "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
          "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">

<form-validation>

<!--
     This is a minimal Validator form file with a couple of examples.
-->

    <global>

        <!-- An example global constant
        <constant>
            <constant-name>postalCode</constant-name>
            <constant-value>^\d{5}\d*$</constant-value>
        </constant>
        end example-->

    </global>

    <formset>

        <!-- An example form -->
        <form name="logonForm">
            <field
                property="username"
                depends="required">
                    <arg key="logonForm.username"/>
            </field>
            <field
                property="password"
                depends="required,mask">
                    <arg key="logonForm.password"/>
                    <var>
                        <var-name>mask</var-name>
                        <var-value>^[0-9a-zA-Z]*$</var-value>
                    </var>
            </field>
        </form>

    </formset>

    <!-- An example formset for another locale -->
    <formset language="fr">

        <constant>
            <constant-name>postalCode</constant-name>
            <constant-value>^[0-9a-zA-Z]*$</constant-value>
        </constant>

        <!-- An example form -->
        <form name="logonForm">
            <field
                property="username"
                depends="required">
                    <arg key="logonForm.username"/>
            </field>
            <field
                property="password"
                depends="required,mask">
                    <arg key="logonForm.password"/>
                    <var>
                        <var-name>mask</var-name>
                        <var-value>^[0-9a-zA-Z]*$</var-value>
                    </var>
            </field>
        </form>

   </formset>

</form-validation>

 

で、少々長いので、コメントを取ってしまって

 
<?xml version="1.0" encoding="Windows-31J" ?>
<!DOCTYPE form-validation PUBLIC
   "-//Apache Software Foundation//
    DTD Commons Validator Rules Configuration 1.1.3//EN"
   "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">

<form-validation>
    <formset>

   </formset>
</form-validation>
 

と縮めて

 
	<formset>
 

 
	</formset>
 

の間に、

 
<form name="com.chikkun.webcms.test.HelloWorldActionForm">
  <field property="name"
         depends="required,maxlength">
    <msg name="required" key="errors.empty" />
    <msg name="maxlength" key="errors.maxlength" />
    <var>
      <var-name>maxlength</var-name>
      <var-value>10</var-value>
    </var>
    <arg name="maxlength" key="name" position="0" />
    <arg name="maxlength" key="${var:maxlength}" position="1"
     resource="false"/>
    <arg name="required" key="name" position="0" />
  </field>
</form>
 

を書き込んでください。意味はしっかり勉強してください(あまり詳しく説明すると本が書けてしまいます(--;)。

最終的には

 
<form-validation>
  <formset>
    <form name="com.chikkun.webcms.test.HelloWorldActionForm">
      <field property="name"
        depends="required,maxlength">
        <msg name="required" key="errors.empty" />
        <msg name="maxlength" key="errors.maxlength" />
        <var>
          <var-name>maxlength</var-name>
          <var-value>10</var-value>
        </var>
        <arg name="maxlength" key="name" position="0" />
        <arg name="maxlength" key="${var:maxlength}" position="1"
         resource="false"/>
        <arg name="required" key="name" position="0" />
      </field>
    </form>
  </formset>
</form-validation>
 

てな感じですかな。

ApplicationResources.propertiesを作成

英語だと、何もせずにここに書き込んだものが使えるのだが、残念ながら日本語は日本語のまま書き込んだものを変換して、使わなくてはならない。これが結構面倒だけれどしょうがない。

そこで、とりあえず

websms/WEB-INF/conf/ApplicationResources_ja.properties

というファイルを作成する。

すぐ上のvalidation.xmlの設定で「key=・・・」を書き込んでいく。

 errors.empty={0}は必須です。 
						errors.maxlength={0}は{1}以下でなくてはなりません。 name=名前 

その次に、dosプロンプトから

native2ascii.exe ApplicationResources_ja.properties ApplicationResources.properties

とたたき、できあがったファイルApplicationResources.properties

WEB-INF/classes/Resources

というディレクトリにコピーする。

注意として、eclipseは時々、f5などで「更新」させるとソースを全てコンパイルするのですが、その際、classesディレクトリをいったん削除してからそれを行います。つまり、せっかくコピーしたApplicationResources.propertiesなくなってしまいます。今回、実は、それではまって1時間以上無駄にしました(--;)。

ようやく最後のJSP

色々なhtmlのタグじゃないタグがありますが、頑張って勉強してください(ただし、実際にはほとんど最近はjspを僕は使っておらず、その代わりvelocityというものを使っています。ただ全く知らないと困るので、やはり、多少は勉強しておいた方が良いでしょう。

名前を入力するためのinput.jsp
 
<%@page pageEncoding="Windows-31J"
  contentType="text/html; charset=Windows-31J" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<html:html locale="true">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-31J"/>
<title>The First Experience of Struts</title>
</head>
<body>

<h2>初めてのStruts</h2>


<html:messages id="msg" message="false">
  <bean:write name="msg" ignore="true" filter="false"/>
</html:messages>

<html:form action="/helloWorld" method="post">


お名前(10文字以下):<html:text property="name"/>

<html:submit value="実行"/>

</html:form>
</body>
</html:html>

 
入力された名前と日付を表示するhello.jsp
 
<%@page pageEncoding="Windows-31J"
   contentType="text/html; charset=Windows-31J" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-31J"/>
<title>こんにちは、赤ちゃん</title>
</head>
<body>

こんにちは、<bean:write name="helloWorldForm" property="name" scope="request"/>さん。


<br/>
<br/>

今日の日時は
<bean:write  name="helloWorldForm" property="year"/>年
<bean:write  name="helloWorldForm" property="month"/>月
<bean:write  name="helloWorldForm" property="day"/>日
(
<bean:write  name="helloWorldForm" property="dayOfTheWeek"/>曜日
) 
<bean:write  name="helloWorldForm" property="hour"/>時
<bean:write  name="helloWorldForm" property="minute"/>分
<bean:write  name="helloWorldForm" property="second"/>秒
 です。
<br/>
<html:link action="helloWorldMenu">戻る</html:link>
</body>
</html>
 
さああああ実行

tomcatが立ち上がっていることを確認して、

http://localhost:8080/webcms/helloWorldMenu

をブラウザでたたいて、名前を入力する画面が出て、名前を入力して、実行ボタンを押すと

 こんにちは、坂井さん。 今日の日時は 2005年 5月 9日 ( 火曜日 )  13時 
							41分 12秒 です。 戻る 

なんて表示されればOKです。

そして、名前を入力しないで実行ボタンを押すと、上記のようなページに飛ばされず、「 名前は必須です。」というメッセージが表示されたり、10文字以上の名前を入力したら「 名前は10文字以下でなくてはなりません。」なんていうメッセージが表示されたら、

それでかんぺき

ふう、意外に時間がかかった。

by 知久和郎