開発関連の覚書

開発関連の覚書メニューへ
■STRUTS1.2

Struts1.2を使った簡単なサンプル
1.本のキーワードを入力して、一覧を表示する簡単なサンプルを以下に示す。
1.1. Struts基本動作の流れ
 添付資料参照。

1.1.1. Sun One Stdioでの新規開発フロー
1.1.2. Sun One Stdioでの通常開発フロー
1.2. web.xml
 必要な部分を追加する。すべてのクライアントからの要求を受け取るアクションサーブレットの定義は必ず設定すること。
また、必要に応じてタグライブラリの設定を追加する。
<?xml version="1.0" encoding="UTF-8"?>
<!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>
<servlet>
    <servlet-name>action</servlet-name>                    ・・・・・・・・・    (1)
    <servlet-class>
    org.apache.struts.action.ActionServlet
    </servlet-class>
    <init-param>
      <param-name>config</param-name>                      ・・・・・・・・・    (2)
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>debug</param-name>                       ・・・・・・・・・    (3)
      <param-value>2</param-value>
    </init-param>
    <init-param>
      <param-name>detail</param-name>
      <param-value>2</param-value>
    </init-param>
    <init-param>
      <param-name>validate</param-name>
      <param-value>true</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>

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

<taglib>
    <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>          ・・・・・・・・・    (4)
    <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>・・・・・・・・・    (5)
  </taglib>
  <taglib>
    <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
  </taglib>
  <!-- The Usual Welcome File List -->
  <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-app>

(1)	すべてのクライアントからの要求を受け取るためのサーブレットを設定する。(このサーブレットはStrutsライブラリに含まれている)
(2)	「ActionServlet」の振る舞いを記述した設定ファイルをアプリケーションルートからの位置で指定する。
(3)	デバッグ出力のレベルを指定する。0から6の数字で指定し、6の場合は全てのログが出力される。0の場合は出力されない。デフォルト値は「0」。
(4)	プログラムで利用するURLを設定する。
(5)	ローカルに保存されているタグライブラリファイル名を指定する。

1.3. struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>

<struts-config>
  <form-beans>
    <form-bean name="indexForm"                              ・・・・・・・・・    (5)
               type="sample.IndexForm"/>                     ・・・・・・・・・    (6)
    </form-beans>
  <global-forwards>
     <forward   name="success" path="/sample/result.jsp"/> ・・・・・・・・・    (7)
  </global-forwards>
  <action-mappings>
    <action path="/index"
            type="sample.IndexAction"
            name="indexForm"
            scope="request"
            input="/sample/index.jsp"                          ・・・・・・・・・    (1)
            validate="true">                                 ・・・・・・・・・    (2)
    <forward name="success" path="/sample/result.jsp"/>    ・・・・・・・・・    (3)
    </action>
  </action-mappings>
   <message-resources parameter="ApplicationResources"/>   ・・・・・・・・・    (4)
</struts-config>

(1)	エラーが発生した場合の遷移先画面を指定する(例では、遷移元と同じキーワード入力画面)。
(2)	送信データの入力チェックを行うに設定する。
(3)	入力エラーなしの場合の遷移先画面を設定する。
(4)	メッセージリソースファイルの設定する。
(5)	ActionForm Beanを識別するための名前。
(6)	ActionForm Beanクラス名
(7)	共通のActionで利用できる遷移先を設定する。例えばシステムエラーなど。

1.4. メッセージリソースファイル(ApplicationResources)
・
errors.required={0} \u3092\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002
・
errors.general=The process did not complete. Details should follow.
errors.token=Request could not be completed. Operation is not in sequence.
index.message=keyword

1.5. 各プログラムで利用するBeansの作成
1.5.1. Bookクラス(一部省略)
 例では、本のタイトル名を保持するJavaBeansにしている。
package sample;
import java.beans.*;
public class Book extends Object implements java.io.Serializable {
    private String title = null;
    public Book(String title) {
        propertySupport = new PropertyChangeSupport( this );
        this.title=title;
    }
    public void setTitle(String title) {
        this.title=title;
    }
    public String getTitle() {
        return this.title;
    }
}

1.5.2. BookListクラス
 例として、検索実行(メソッド名:search)を行うことにより、各本の検索データを保持する。検索データの取得は、アクセサメソッドを利用する。
検索実行メソッドの戻り値を検索結果としても良いが、StrutsのIterateタグでは、JavaBeansであることが前提となっているので、検索データを保持する構造としている。
package sample;
import java.util.Vector;
import java.beans.*;
public class BookList extends Object implements java.io.Serializable {
    private static final String PROP_SAMPLE_PROPERTY = "SampleProperty";
    private String sampleProperty;
    private Book[] books = null;
    private PropertyChangeSupport propertySupport;
    public BookList() {
        propertySupport = new PropertyChangeSupport( this );
    }
    public String getSampleProperty() {
        return sampleProperty;
    }
    public void setSampleProperty(String value) {
        String oldValue = sampleProperty;
        sampleProperty = value;
        propertySupport.firePropertyChange(PROP_SAMPLE_PROPERTY, oldValue, sampleProperty);
    }
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertySupport.addPropertyChangeListener(listener);
    }
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertySupport.removePropertyChangeListener(listener);
    }
    //  本来はDBから検索する
    public void search(String keyword) {
        this.books = new Book[5];
        this.books[0] = new Book("A00000");
        this.books[1] = new Book("B00000");
        this.books[2] = new Book("C00000");
        this.books[3] = new Book("D00000");
        this.books[4] = new Book("E00000");
    }
    public Book[] getBooks() {
        return this.books;
    }
    public void setBooks(Book[] book) {
        this.books = book;
    }
}

1.6. アクションフォームBeanの作成(一部省略)
 このクラスはリクエストデータの入れ物と考えるので、フォームの入力項目数分だけプロパティーが必要となる。
package sample;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public final class IndexForm extends ActionForm {
    private String keyword = null;

    public String getKeyword() {
	  return (this.keyword);
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }
    public void reset(ActionMapping mapping, HttpServletRequest request) {
        this.keyword = null;
    }
    public ActionErrors validate(ActionMapping mapping,
                                 HttpServletRequest request) {
        ActionErrors errors = new ActionErrors();
        if ((keyword == null) || (keyword.length() < 1))
            errors.add("keyword", new ActionError("error.required"));	・・・・・・・・		(1)
        return errors;
    }
}
(1)	このメソッドは、クライアントからリクエストが送信されるたびに自動的に呼び出される。
例では、検索キーワードが未入力の場合にエラーメッセージを設定している。
ActionError生成の第二引数は、メッセージリソースファイルの該当項目に設定されている{0}と対応している。また、引数は最大4個まで指定可能である。

1.7. アクションクラスの作成(一部省略)
 このクラスにビジネスロジックを記述する。ビジネスロジック実行後の処理結果をJSPにリダイレクトする。
package sample;
・略
import sample.book.*;
public final class IndexAction extends Action {
    private Log log = LogFactory.getLog("org.apache.struts.webapp.Example");
    public ActionForward execute(ActionMapping mapping,
				 ActionForm form,
				 HttpServletRequest request,
				 HttpServletResponse response)
	throws Exception {
	Locale locale = getLocale(request);
	MessageResources messages = getResources(request);
	ActionErrors errors = new ActionErrors();
        //  キーワードを受け渡して、検索処理を実行する
        String keyword = (String)PropertyUtils.getSimpleProperty(form, "keyword");
        BookList booklist = new BookList();
        booklist.search(keyword);
        request.getSession().setAttribute("booklist", (BookList)booklist);
return (mapping.findForward("success"));
    }
}

1.8. JSPの作成
1.8.1. index.jsp
<%@ page contentType="text/html" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld"  prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html:html>
<head>
<title></title>
</head>
<body bgcolor="white">
<html:errors/>                   ・・・・・・・・    (1)
<html:form action="/index">
	<html:text name="indexForm" property="keyword" size="16" maxlength="256"/>
	<p>
	<html:submit property="submit" value="Submit"/>
	<html:reset/>
</html:form>
</body>
</html:html>
(1)	ActionErrorsサイズが0の場合には何も処理を行わないが、エラーメッセージが設定されている場合には、エラーメッセージを読み込んで表示する。

1.8.2. result.jsp
<%@ page contentType="text/html" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld"  prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html:html locale="true">
<head><title></title><html:base/></head>
<body bgcolor="white">
<html:errors/>
<logic:iterate id="bk" name="booklist" property="books" indexId="index">    ・・・・・・・・・    (1)
    <bean:write name="bk" property="title"/>
</logic:iterate>
</body>
</html:html>
(1) すべての検索結果データを表示する。Idは、終了Iterateタグの間で利用するJavaBeansのアクセスキー、
   nameは、アクションサーブレットでフォワードしたデータ名、indexは現在ループしているカウンター値が設定される。

1.9. まとめ
1.9.1. 長所
・ 画面定義をGUIで設定し、Javaコードを生成してくれるオーサリングツールを利用することで開発負担が軽減する。 (参考URL:http://www3.coara.or.jp/~agt/struts/beanmaker/beanmaker.html)
1.9.2. 短所
・ 画面遷移に必要となるクラスが、アクションクラスとアクションフォームクラスの2組になるために、クラスファイルが増大する。(次章で解説するサンプルではアクションフォームBeanクラスを減らすことが可能。)
1.9.3. 開発時の課題
・ 画面系はすべてStrutsを利用して構成することにするのか?通常のServlet構造に適している画面はないのか? ・ メッセージリソースファイルの項目定義方法(命名規約) ・ 日本語処理
1.9.4. サンプルプログラム
 /sample/SimpleStruts.zip
1.9.5. 参考URL
2. Strutsを利用した色々なサンプル(Template・Validate・DynaValidatorForm)
2.1. サンプル概要
 Strutsを利用した実際のアプリケーションを想定して、いくつか画面数があるサンプルを用意した。
このサンプルでは、各画面の概観を統一するためにTemplateタグを利用し、クラスの増大を防ぐためにアクションフォームBeanはDynaValidateFormクラスを利用してクラスを自動生成している。
また、各画面の入力チェックには、Plug-Inを利用している。
2.2. web.xml(一部省略)
 以下の太字部分を追加する。今回のサンプルでは、Templateタグを利用するためにTemplateタグライブラリを追加する。
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
  <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>
    <init-param>
      <param-name>validate</param-name>
      <param-value>true</param-value>
   </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <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-app>

2.3. struts-config.xml(一部省略)
<?xml version="1.0" encoding="ISO-8859-1" ?>
<struts-config>
  <form-beans>
    <form-bean name="searchForm" dynamic="true"
type="org.apache.struts.validator.DynaValidatorForm">・・・・・・・・		(1)
        <form-property name="title" type="java.lang.String"/>		・・・・・・・・		(2)
        <form-property name="isbn" type="java.lang.String"/>
    </form-bean>
    <form-bean name="registForm" dynamic="true"
type="org.apache.struts.validator.DynaValidatorForm">	・・・・・・・・		(1)
        <form-property name="title" type="java.lang.String"/>・・・・・・・・		(2)
<form-property name="author" type="java.lang.String"/>
        <form-property name="isbn" type="java.lang.String"/>
        <form-property name="memo" type="java.lang.String"/>
        <form-property name="date" type="java.lang.String"/>
  </form-bean>
  </form-beans>
  <global-forwards>
     <forward   name="success"                path="/sample/resultIndex.jsp"/>
  </global-forwards>
  &l;taction-mappings>
    <action path="/search"
            type="sample.SearchAction"
            name="searchForm"
            scope="request"
            input="/sample/index.jsp"				・・・・・・・・		(3)
            validate="true">				・・・・・・・・		(4)
    <forward name="success" path="/sample/searchResultIndex.jsp"/>
    </action>
    <action path="/regist"
            type="sample.RegistAction"
            name="registForm"
            scope="request"
            input="/sample/registIndex.jsp"
            validate="true">
    <forward name="success" path="/sample/registResultIndex.jsp"/>
    </action>
  </action-mappings>
  <message-resources parameter="ApplicationResources"/>
   <plug-in className="org.apache.struts.validator.ValidatorPlugIn">	・・・・・・・・		(5)
     <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
                                         /WEB-INF/validation.xml"/>
  </plug-in>
</struts-config>

(1)	アクションフォームBeanを自動生成するためのクラスを指定する
(2)	自動生成したアクションフォームBeanのプロパティーを指定する
(3)	入力エラーが発生した場合の表示画面を指定する
(4)	入力エラーチェックを有効にする
(5)	Plug-inを設定する。(validatetor-rules.xmlは各画面のエラーチェックルール、validatetor.xmlは特に理由が無い限りコピーして利用する)

2.4. 各プログラムで利用するBeansの作成
2.4.1. BookDataクラス(一部省略)
 典型的なJavaBeansであるが、JSPでiterateタグを利用するために配列を返すメソッドが定義されている。(太字部分)
package sample;
import java.util.*;
public class BookData implements BookImpl {
    private String isbn = null;
    private String title = null;
    private String author = null;
    private String memo = null;
    private String date = null;
    private BookData[] bookDataList = null;
    public java.lang.String getIsbn() { return this.isbn; }
    public void setIsbn(java.lang.String isbn){ this.isbn = isbn;}
	・
		・
    public BookData[] getBookDataList(){ return this.bookDataList; }
    public void setBookDataList(BookData[] bookDataList){ this.bookDataList = bookDataList; }
    public BookData() {}
    public BookData(java.lang.String isbn, java.lang.String title, java.lang.String memo,
java.lang.String author, String date) {
        setIsbn(isbn);
        setTitle(title);
        setMemo(memo);
        setAuthor(author);
        setDate(date);
    }
}

2.4.2. MaintainStatusクラス
 データベース(EJB)を利用する代わりにBookDataを保持するテストクラス。
package sample;
import java.util.*;
public class MaintainStatus {
    private static java.util.Vector memData = null;
    private static MaintainStatus maintainStatus = null;
    private MaintainStatus() {}
    static public MaintainStatus getInstance() {
        if( maintainStatus == null ) {
            maintainStatus = new MaintainStatus();
            memData = new Vector();
        }
        return maintainStatus;
    }
    static public void insert(BookImpl src) {
        memData.add(src);
    }
    static public BookImpl select(String title) {
        for(int i=0; i

2.5. アクションフォームBeanの作成
 DynaValidatorFormクラスが自動生成するために作成する必要はない。
2.6. アクションクラスの作成
2.6.1. SearchActionクラス(一部省略)
 入力されたタイトルを受け取って、本を検索した結果をJSPにディスパッチするサンプル。
package sample;
public final class SearchAction extends Action {
    private Log log =
        LogFactory.getLog("org.apache.struts.webapp.Example");
    public ActionForward execute(ActionMapping mapping,
				 ActionForm form,
				 HttpServletRequest request,
				 HttpServletResponse response)
		throws Exception {
ServletContext context = getServlet().getServletContext();
MessageResources messages = getResources(request);
ActionErrors errors = new ActionErrors();

        //  キーワードを受け渡して、検索処理を実行する
        String title = (String)PropertyUtils.getSimpleProperty(form, "title");

        MaintainStatus data = MaintainStatus.getInstance();
        BookData book = (BookData)data.select(title);
        request.setAttribute("bookData", book);

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

2.6.2. RegistActionクラス(一部省略)
 入力されたデータから、BookDataBeanを生成し保持するサンプル。
package sample;
public final class RegistAction extends Action {
    private Log log =
        LogFactory.getLog("org.apache.struts.webapp.Example");
    public ActionForward execute(ActionMapping mapping,
				 ActionForm form,
				 HttpServletRequest request,
				 HttpServletResponse response)
throws Exception {

MessageResources messages = getResources(request);
ActionErrors errors = new ActionErrors();
      String isbn = (String)PropertyUtils.getSimpleProperty(form, "isbn");
      String memo = (String)PropertyUtils.getSimpleProperty(form, "memo");
String author = (String)PropertyUtils.getSimpleProperty(form, "author");
      String title = (String)PropertyUtils.getSimpleProperty(form, "title");
      String date = (String)PropertyUtils.getSimpleProperty(form, "date");

      MaintainStatus data = MaintainStatus.getInstance();
      sample.BookData book = new sample.BookData(isbn, title, memo, author,date);
      data.insert(book);

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

2.6.3. ListActionクラス(一部省略)
 例では、JSPで直接データを取得しているが、このサーブレットで設定することが望ましい。
package sample;
public final class ListAction extends Action {
    private Log log =
        LogFactory.getLog("org.apache.struts.webapp.Example");

    public ActionForward execute(ActionMapping mapping,
				 ActionForm form,
				 HttpServletRequest request,
				 HttpServletResponse response)
throws Exception {
	    return (mapping.findForward("success"));
    }
}

2.7. HTML・JSPの作成
2.7.1. header.html
 静的コンテンツはコンパイル不要のためhtml形式が望ましい。
<table>
   <tr>
      <td><b>Here is Header Area.</b></td>
   </tr>
</table>

2.7.2. footer.html
<table>
   <tr>
      <td><b>Here is Footer Area.</b></td>
   </tr>
</table>

2.7.3. index.jsp
 このページ(検索)が読み込まれると、insertタグで指定されているファイルに置き換わる。Putタグがnameに対応する個所に該当ファイルを割り当てる。他のページ(検索結果、登録、一覧)とは太字部分が異なる。
<%@ taglib uri='/WEB-INF/struts-template.tld' prefix='template' %>・・・・・・・・		(1)
<template:insert template='/sample/indexTemplate.jsp'>・・・・・・・・		(2)
  <template:put name='title' content='Templates' direct='true'/>
    <template:put name='header' content='/sample/header.html' />・・・・・・・・		(3)
  <template:put name='sidebar' content='/sample/sidebar.jsp' />
  <template:put name='content' content='/sample/search.jsp'/>
  <template:put name='footer' content='/sample/footer.html' />
</template:insert>

(1)	Templateタグライブラリの利用宣言
(2)	このページに取り込む共通テンプレートを指定する
(3)	取り込んだファイルの各nameに対応する該当ファイルを指定する

2.7.4. indexTemplate.jsp
 検索、検索結果、登録、一覧画面を構成するテンプレートファイル。
<%@ taglib uri='/WEB-INF/struts-template.tld' prefix='template' %>
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title></title>
<link rel="stylesheet" href="css/templates.css"
      charset="ISO-8859-1" type="text/css">
</head>
<body>
<table>
   <tr valign='top'>
      <td><template:get name='sidebar'/></td>
      <td><table>
            <tr><td><template:get name='header'/></td></tr>
            <tr><td><template:get name='content'/></td></tr>
            <tr><td><template:get name='footer'/></td></tr>
          </table>
      </td>
   </tr>
</table>
</body>
</html>

2.7.5. sidebar.jsp
<table width='145'>
    <tr><td><a href='/sample/index.jsp'>
        <!--検索-->SEARCH</a></td></tr>
    <tr><td><a href='/sample/registIndex.jsp'>
       <!-- 登録-->REGIST</a></td></tr>
    <tr><td><a href='/sample/listIndex.jsp'>
        <!--一覧-->LIST</a></td></tr>
</table>

2.7.6. search.jsp
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld"  prefix="bean" %>
<html:errors/>
<html:form action="/search">
<bean:message key="search.keyword"/>
<bean:message key="search.message.title"/>
<html:text name="searchForm" property="title" size="64" maxlength="256"/>
<bean:message key="search.message.isbn"/>
<html:text name="searchForm" property="isbn" size="64" maxlength="256"/>
<html:submit property="submit" value="Submit"/>
<html:reset/>
</html:form>

2.7.7. searchResultIndex.jsp
 他のページ(キーワード入力、登録、一覧)とは太字部分が異なる。
<%@ taglib uri='/WEB-INF/struts-template.tld' prefix='template' %>
<template:insert template='/sample/indexTemplate.jsp'>
  <template:put name='title' content='Templates' direct='true'/>
  <template:put name='header' content='/sample/header.html' />
  <template:put name='sidebar' content='/sample/sidebar.jsp' />
  <template:put name='content' content='/sample/searchResult.jsp'/>
  <template:put name='footer' content='/sample/footer.html' />
</template:insert>

2.7.8. searchResult.jsp
<jsp:useBean id="bookData" scope="request" class="sample.BookData" //>
<jsp:getProperty name="bookData" property="isbn"//>
<jsp:getProperty name="bookData" property="title"//>
<jsp:getProperty name="bookData" property="author"//>
<jsp:getProperty name="bookData" property="memo"//>
<jsp:getProperty name="bookData" property="date"/>

2.7.9. registIndex.jsp
 他のページ(キーワード入力、検索結果、一覧)とは太字部分が異なる。
<%@ taglib uri='/WEB-INF/struts-template.tld' prefix='template' %>
<template:insert template='/sample/indexTemplate.jsp'>
  <template:put name='title' content='Templates' direct='true'/>
  <template:put name='header' content='/sample/header.html' />
  <template:put name='sidebar' content='/sample/sidebar.jsp' />
  <template:put name='content' content='/sample/regist.jsp'/>
  <template:put name='footer' content='/sample/footer.html' />
</template:insert>

2.7.10. regist.jsp
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld"  prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html:errors/>
<html:form action="/regist">
<bean:message key="regist.message.isbn"/>
<html:text name="registForm" property="isbn" size="16" maxlength="16"/>
<bean:message key="regist.message.title"/>
<html:text name="registForm" property="title" size="64" maxlength="256"/>
<bean:message key="regist.message.author"/>
<html:text name="registForm" property="author" size="64" maxlength="256"/>
<bean:message key="regist.message.date"/>
<html:text name="registForm" property="date" size="32" maxlength="32"/>
<bean:message key="regist.message.memo"/>
<html:text name="registForm" property="memo" size="64" maxlength="256"/>
<html:submit property="submit" value="Submit"/>
<html:reset/>
</html:form>

2.7.11. listIndex.jsp
 他のページ(キーワード入力、検索結果、登録)とは太字部分が異なる。
<%@ taglib uri='/WEB-INF/struts-template.tld' prefix='template' %>
<template:insert template='/sample/indexTemplate.jsp'>
  <template:put name='title' content='Templates' direct='true'/>
  <template:put name='header' content='/sample/header.html' />
  <template:put name='sidebar' content='/sample/sidebar.jsp' />
  <template:put name='content' content='/sample/list.jsp'/>
  <template:put name='footer' content='/sample/footer.html' />
</template:insert>

2.7.12. list.jsp
<%@ page language="java"
	 import= "sample.*,java.util.*"%>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld"  prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%
    //  本来は、ActionServletで設定する
    MaintainStatus maintainStatus = MaintainStatus.getInstance();
    BookData book = new BookData();
    book.setBookDataList(maintainStatus.list());
    BookData[] books = book.getBookDataList();
    pageContext.setAttribute("books", books, PageContext.PAGE_SCOPE);
%>
<TABLE>
<logic:iterate id="bk" name="books">
    <TR><TD><bean:write name="bk" property="isbn"/></TD>
        <TD><bean:write name="bk" property="title"/></TD>
        <TD><bean:write name="bk" property="author"/></TD>
        <TD><bean:write name="bk" property="memo"/></TD>
        <TD><bean:write name="bk" property="date"/></TD>
    </TR>
</logic:iterate>
</TABLE>

2.8. まとめ
2.8.1. 長所
・ DynaInvalidatorFormを利用することで、アクションフォームBeansを作成する必要が無くなる。
・ Templateタグを利用することで、共通部分を各画面で利用できる。
2.8.2. 短所
・特にないように思われる。
2.8.3. 開発時の課題
・ struts-config.xmlでアクションフォームBean自動生成を定義している部分で、「」のような定義をするとエラーになる。(現段階ではString以外の利用方法が不明)
2.8.4. サンプルプログラム
 /sample/SimpleStrutsTemplate.zip
開発関連の覚書メニューへ