データベースへの接続・操作を担当するのは、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アプリケーションからデータベースにアクセスするための方法を学習しました。今回学習したのは最も基本的な内容にすぎませんが、逆にいうと、多くの状況で応用可能な「定石」でもあります。ただ記事を読み流すだけではなく、自分の手を動かしつつ、自分の目で動作を確認してみてください。きっとそこには「読む」だけでは得られなかった新たな発見があるはずです。