データベースへの接続・操作を担当するのは、JavaBeansクラスBookInfoの役割です。BookInfoクラスのgetBookInfosメソッドでは、書籍情報テーブル(bok_inf_tbl)の内容を配本日(publishedフィールド)降順で抽出し、取得した結果セットを後続のビュー(BookView.jsp)に引き渡します。
 ただし、取得した結果セットをそのまま「.jsp」ファイルに引き継いでも、「.jsp」ファイルではこれを扱うことができません(もちろん、スクリプトレットなどを利用すれば可能です)。後続の「.jsp」ファイル内において、「Strutsタグライブラリ」だけで結果セットの内容を処理するには、結果セットからJavaBeansクラスの配列を作成しておく必要があるのです。Strutsでは標準的に結果セット(ResultSetオブジェクト)を処理するための機能(タグライブラリ)は用意していませんが、データをJavaBeans配列の形式に加工しておくことでデータを容易に処理することができるようになります(処理方法については後述)。
 BookInfoクラスでは、bok_inf_tblテーブルから抽出した結果セットの1行を1つのオブジェクトで表現します。getBookInfosメソッドでは、データソースから抽出した結果セットの内容を1行ずつ取り出し、BookInfoクラスの各プロパティ(フィールド)に格納していきます。出来上がったBookInfoクラスは、ArrayList(可変配列)に順に追加していくことで、最終的にループ処理がすべて完了したときには、BookInfoクラスの配列ができているというわけです。
 なお、ここではデータベース操作の基本的な手法については割愛しますので、詳細は「基礎から学ぶサーブレット/JSP 第10回」「JNDI活用でデータソース管理を一元化する」を参考にしてください。
         
          | BookInfo.java(コンパイル結果は「/WEB-INF/classes/struts」に保存) | 
        
         
          package struts; 
             
            import java.io.*; 
            import java.sql.*; 
            import java.util.*; 
            import javax.sql.*; 
            import javax.naming.*; 
             
            public final class BookInfo implements Serializable { 
               // 各レコードのフィールド値を格納するためのプライベート変数 
              private String isbn; 
              private String title; 
              private String author; 
              private String price; 
              private String publish; 
              private String published; 
               // コンストラクタ 
              public BookInfo() { 
                isbn=null;   title=null; 
                author=null; price=null; 
                publish=null;published=null; 
              } 
               // プロパティ参照用のgetterメソッド 
              public String getIsbn()     {return isbn;} 
              public String getTitle()    {return title;} 
              public String getAuthor()   {return author;} 
              public String getPrice()    {return price;} 
              public String getPublish()  {return publish;} 
              public String getPublished(){return published;} 
               // プロパティ設定用のsetterメソッド 
              public void setIsbn(String isbn)        {this.isbn=isbn;} 
              public void setTitle(String title)      {this.title=title;} 
              public void setAuthor(String author)    {this.author=author;} 
              public void setPrice(String price)      {this.price=price;} 
              public void setPublish(String publish)  {this.publish=publish;} 
              public void setPublished(String published){this.published=published;} 
               // データベースからの出力結果をArrayListオブジェクトに格納 
              public static ArrayList getBookInfos() { 
                ArrayList objAry=new ArrayList(); 
                Connection db=null; 
                PreparedStatement objPs=null; 
                ResultSet rs=null; 
                try { 
                   // データベースへの接続を確立 
                  Context ctx=new InitialContext(); 
                  DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/Struts"); 
                  db=ds.getConnection(); 
                  objPs=db.prepareStatement("SELECT * FROM bok_inf_tbl ORDER BY published DESC"); 
                  rs=objPs.executeQuery(); 
                   // 取得した結果セットをもとに、BookInfo配列を生成 
                  while(rs.next()){ 
                    BookInfo objBok=new BookInfo(); 
                    objBok.setIsbn(rs.getString("isbn")); 
                    objBok.setTitle(rs.getString("title")); 
                    objBok.setAuthor(rs.getString("author")); 
                    objBok.setPrice(rs.getString("price")); 
                    objBok.setPublish(rs.getString("publish")); 
                    objBok.setPublished(rs.getString("published")); 
                    objAry.add(objBok); 
                  } 
                } catch(Exception e) { 
                  e.printStackTrace(); 
                } finally { 
                  try { 
                    if(rs!=null)   {rs.close();} 
                    if(objPs!=null){objPs.close();} 
                    if(db!=null)   {db.close();} 
                  } catch(Exception e){ 
                    e.printStackTrace(); 
                  } 
                } 
                return objAry; 
              } 
            }  | 
        
      
      
 完成したArrayListオブジェクトは、HttpServletRequest#setAttributeメソッドを介してリクエスト属性“book.view.info”として格納します。
 これで、データを表示するための準備ができましたので、いよいよビュー(「.jsp」ファイル)の構築です。上で用意されたBookInfoクラスの配列を、「.jsp」ファイル上でグリッド表に展開してみましょう。
         
          | BookView.jsp(「/chap03」に保存) | 
        
         
          <%@ page contentType="text/html;charset=Shift_JIS" %> 
            <%@ taglib uri="/tags/struts-html"  prefix="html" %> 
            <%@ taglib uri="/tags/struts-bean"  prefix="bean" %> 
            <%@ taglib uri="/tags/struts-logic" prefix="logic" %> 
            <html:html> 
            <head> 
            <title>書籍情報更新・削除</title> 
            </head> 
            <body> 
            <h1 style="color:white;background-color:#525D76;">書籍情報更新・削除</h1> 
            [<html:link action="/BookWriteViewAction">新規登録</html:link>] 
            <table border="1"> 
              <tr bgcolor="#eeeeee"> 
                <th>タイトル</th><th>著者名</th><th>価格</th><th>出版社</th><th>配本日</th> 
              </tr> 
              <logic:iterate id="bookInfo" name="book.view.info" scope="request"> 
                <tr> 
                  <td nowrap> 
                    <html:link action="/BookWriteViewAction" 
                      paramId="isbn" paramName="bookInfo" paramProperty="isbn"> 
                      <bean:write name="bookInfo" property="title" /> 
                    </html:link> 
                  </td> 
                  <td nowrap><bean:write name="bookInfo" property="author" /></td> 
                  <td nowrap><bean:write name="bookInfo" property="price" /></td> 
                  <td nowrap><bean:write name="bookInfo" property="publish" /></td> 
                  <td nowrap><bean:write name="bookInfo" property="published" /></td> 
                </tr> 
              </logic:iterate> 
            </table> 
            </body> 
            </html:html>  | 
        
      
      
 配列から順番に要素を取り出し、出力するのは、<logic:iterate>要素の役割です。name属性で指定された「属性」値を、scope属性で指定されたスコープから検出します。id属性は、<logic:iterate>要素の配下で、取り出された要素(個々のJavaBeansクラス)にアクセスする場合の変数名となります。
 <logic:iterate>要素配下では、<bean:write>要素を使用することで、JavaBeansクラスの個々のプロパティにアクセスすることができます。<bean:write>要素のname属性は、<logic:iterate>要素のid属性に対応している必要があります。property属性には、取得したいプロパティ名を、それぞれ指定してください。
 なお、タイトル列には、詳細画面(次回紹介)にジャンプするためのハイパーリンクを作成することにします。ハイパーリンクの作成には、<html:link>要素を使用します。以下に、<html:link>要素で利用可能な主な属性を挙げておくことにしましょう。
<html:link>要素の主な属性
 | 
属性 | 
概要 | 
 | 
action | 
リンク先のアクション名 | 
| paramId | 
クエリ情報のキー名 | 
| paramName | 
クエリ情報の値(JavaBeansクラス) | 
| paramProperty | 
クエリ情報の値(プロパティ名) | 
 | 
 配下には、リンク文字列として使用される文字列を指定します。つまり、<html:link>要素によって、(例えば)以下のような<a>タグが生成されます。
         
          <a href="/struts/BookWriteViewAction.do?isbn=4-7980-0522-3"> 
            プチリファレンスJSP&サーブレット</a>  | 
        
      
      
 <logic:iterate>要素と併用することで、一覧表に個別画面へのリンクを生成するこの手法は、比較的よく利用する定石的な方法でもありますので、きちんと押さえておいてください。
 最後に、これまで作成したアクションクラス、アクションフォームBeans、「.jsp」ファイルを、コンフィグレーションファイル上でマッピング(関連付け)して、完了です。struts-config.xmlに、以下のリストの赤字部分を追記してください。
         
          | struts-config.xml | 
        
         
           <?xml version="1.0" encoding="Shift_JIS" ?> 
            <!DOCTYPE struts-config PUBLIC 
                      "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" 
                      "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> 
            <struts-config> 
              <data-sources> 
                <data-source type="org.apache.commons.dbcp.BasicDataSource"> 
                  <set-property property="driverClassName" 
                    value="org.gjt.mm.mysql.Driver" /> 
                  <set-property property="url" value="jdbc:mysql://localhost/wings?useUnicode= 
            true&characterEncoding=Shift_JIS" /> 
                  <set-property property="username" value="root" /> 
                  <set-property property="password" value="root" /> 
                </data-source> 
              </data-sources> 
              <form-beans> 
                <form-bean name="BeginForm" type="struts.BeginForm" /> 
                <form-bean name="BookUpdateViewForm" 
                  type="org.apache.struts.action.DynaActionForm"> 
                  <form-property name="isbn" type="java.lang.String" /> 
                </form-bean> 
                <form-bean name="BookUpdateForm" type="struts.BookUpdateForm" /> 
              </form-beans> 
              <global-exceptions> 
              </global-exceptions> 
              <global-forwards> 
              </global-forwards> 
              <action-mappings> 
                <action path="/BeginAction" type="struts.BeginProcess" 
                  name="BeginForm" scope="request"> 
                  <forward name="success" path="/output.jsp" /> 
                </action> 
                <action path="/BookViewAction" type="struts.BookViewProcess"> 
                  <forward name="success" path="/chap03/BookView.jsp" /> 
                </action> 
                <action path="/BookWriteViewAction" type="struts.BookUpdateViewProcess" 
                  name="BookUpdateViewForm" scope="request"> 
                  <forward name="success" path="/chap04/BookUpdate.jsp" /> 
                </action> 
                <action path="/BookWriteAction" type="struts.BookUpdateProcess" 
                  name="BookUpdateForm" scope="request" 
                  input="/chap04/BookUpdate.jsp" validate="false"> 
                  <forward name="success" path="/BookViewAction.do" /> 
                </action> 
              </action-mappings> 
              <message-resources parameter="ApplicationResources" /> 
              <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>  | 
        
      
      
 <action>要素の設定については、すでに「第2回 Strutsフレームワークの「枠組み」を学ぶ」でもご紹介したので、さらに加えるべき点はありません。復習も兼ねて、第2回の解説と照らし合わせながら、自分なりに解釈してみてください。
 なお、このようにコンフィグレーションファイルを設定した場合、アプリケーションは以下のURLで呼び出すことができます。
         
          |  
             http://localhost:8080/struts/BookViewAction.do  
           | 
        
      
      
 末尾の見慣れない拡張子「.do」を、あるいは不思議に思われた方がいらっしゃるかもしれません。しかし、これはれっきとしたStrutsの標準的な拡張子です。第1回で作成したweb.xmlをもう一度ご覧いただくと、アクションサーブレット(action)に対して、拡張子「.do」が関連付けされていることがお分かりになるはずです。
 つまり、Strutsでは拡張子「.do」でURLを指定することで、必ず一度アクションサーブレットを呼び出しているというわけです。アクションサーブレットは、URLからアクション名(ここでは「BookViewAction」)を取得し、これをキーとして関連するアクションフォームBeansやアクションクラスをコールします。
 第2回のサンプル(input.jsp)で、拡張子「.do」を意識する必要がなかったのは、ただ単に<html:form>要素がaction属性の指定値に対して、内部的に拡張子「.do」を付加していたからにすぎません。このように、ブラウザから直接にStrutsアプリケーションを呼び出す場合には、「.do」を明示的に指定する必要があります。
 以上、今回はStrutsアプリケーションからデータベースにアクセスするための方法を学習しました。今回学習したのは最も基本的な内容にすぎませんが、逆にいうと、多くの状況で応用可能な「定石」でもあります。ただ記事を読み流すだけではなく、自分の手を動かしつつ、自分の目で動作を確認してみてください。きっとそこには「読む」だけでは得られなかった新たな発見があるはずです。