2003年
掲示板に投稿した内容を保存したり、読み出したりするクラスを作成します。
J2EEパターンでは、データソース(DBやファイル等)へアクセスするコードを
ビジネスロジックの中に直接書くべきではないと言われています。
データソースへのアクセスをカプセル化するパターンと
してDAO(Data Access Object)パターンというものがあります。
[DAOパターンの例]
public class DAOFactory {
public static OrderDAO getOrderDAO() {
return new OrderDAOImpl1();
}
}
//DAOのインターフェース
public interface OrderDAO {
public void updateOrderData(OrderVO data);
public void insertOrderData(OrderVO data);
}
//DAO本体
public class OrderDAOImpl1 implements OrderDAO {
public void updateOrderData(OrderVO data) {
//注文テーブルを更新するコード
}
public void insertOrderData(OrderVO data) {
//注文テーブルを更新するコード
}
}
//DAOを使う側のクラス
public class Main {
public static void main(String[] args) {
OrderDAO dao = DAOFactory.getOrderDAO();
dao.updateOrderData(data);
}
}
みたいな感じです。DAOを使う側のクラスの中にOrderDAOImpl1が
出てきません。使う側からはDAO本体が何であるかがわからなく
しています。使う側からはインターフェース経由でDAOを操作しているからです。
これにより、DAO本体をOrderDAOImpl1からOrderDAOImpl2
に変更したくなった時にDAOFactoryのみ変更すれば良いことになります。
つまり、DAOパターンには以下のメリットがあります。
1.具象クラス(DAO本体)をDAOの利用者から隠蔽し、DAO本体の変更による影響を
利用者に与えない。例えば、利用するDBを変更する場合にDAO本体のみ
変更で済む。
2.複雑なデータアクセスを局所化 & 隠蔽してソースコードをわかりやすくする。
今回作成する掲示板アプリケーションは、ファイルにデータを記録します。将来的に
ファイルからDBに変更する予定はありませんので、2番のメリットのみ
享受出来れば良いので、DAOを生成するクラスとDAOのインターフェースは作りません。
今いるプロジェクトでも作りませんでした。後になってDBをOracleからDB2
に変更しますとかいうことってほとんどないのではないでしょうか?
なので1番のメリットはあまり意味をなさない気がします。クラスが増えて
めんどくさくなるだけです。
それじゃ、ソース行ってみよう!
import java.io.*;
import java.util.ArrayList;
import java.net.URL;
import jp.gr.java_conf.yamarou.io.FileUtil;
/**
* 掲示板メッセージの読み込み、書き込みを行うData Access Object。
* @author yamarou
*/
public class ForumDAO {
/** 改行文字をシステムプロパティから取得 */
private static final String LINE_SEPARATOR = System.getProperty(
"line.separator");
/** 掲示板メッセージファイル */
private static final String FILE_NAME = "/message.txt";
/**
* ファイルから掲示板メッセージを取得し返す。
* @return 掲示板メッセージ
*/
public ForumMessageVO[] getForumMessages() {
try {
//ファイルを読み込む。
String file = getFilePath(); //(1)
String[] lines = FileUtil.getLines(file); //(*)
ArrayList nameList = new ArrayList();
ArrayList messageList = new ArrayList();
if (lines.length != 0) {
nameList.add(lines[0].substring(9));
}
//ファイルの中身を解析する。
StringBuffer buf = new StringBuffer(1000);
for (int i = 1; i < lines.length; i++) {
String line = lines[i];
if (line.indexOf("[[name]]=") == 0) {
nameList.add(line.substring(9));
} else if (line.indexOf("[[end]]") == 0) {
messageList.add(buf.toString());
buf.delete(0, 1000);
} else {
buf.append(line);
buf.append(LINE_SEPARATOR);
}
}
//逆順で、リストから配列に移す。
ForumMessageVO[] results = new ForumMessageVO[nameList.size()];
int decIndex = results.length - 1;
for (int i = 0; i < results.length; i++) {
results[i] = new ForumMessageVO();
results[i].setName((String)nameList.get(decIndex));
results[i].setMessage((String)messageList.get(decIndex));
decIndex--;
}
return results;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* 掲示板メッセージをファイルに保存する。
* @param name
* @param message
*/
public void save(String name, String message) {
try {
//出力データ編集
StringBuffer buf = new StringBuffer(1000);
buf.append("[[name]]=");
buf.append(name);
buf.append(LINE_SEPARATOR);
buf.append(message);
buf.append(LINE_SEPARATOR);
buf.append("[[end]]");
buf.append(LINE_SEPARATOR);
//ファイルに書き込む。
String file = getFilePath();
PrintWriter writer = new PrintWriter(new FileWriter(file, true));
writer.print(buf.toString());
writer.close();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* クラスパス上にある掲示板メッセージファイルのパスを返す。
* @return ファイルパス
*/
private String getFilePath() {
URL url = getClass().getResource(FILE_NAME); //(2)
String file = url.getFile(); //(3)
return file;
}
}
ファイルを読んだり、書いたりしています。少し物珍しいのは(1)で
getFilePath()を呼び出している所です。getFilePathでは(2)で、
クラスパス上にあるリソース(ファイル)をURLオブジェクトとして
取得しています。(3)で、URLオブジェクトからファイルパスを取得ます。
そっからは普通のファイル入出力と同じです。
それと(*)でFileUtilというクラスを使っています。FileUtil.getLines(file);で
fileのファイルを読み込んでString配列に格納して返します。このクラスは
僕が作ったライブラリのjp.gr.java_conf.yamarou.ioパッケージに
含まれています。これらもいずれ公開したいと思います。ぜひ使ってね(ハート)
ところで、
「jp.gr.java_confって何だぁ?」
パッケージ名はドメインを逆にしたものを付けるルールになっています。
そうすることによって、名前がぶつかる事を避けているわけですが、
個人でドメインを持っていない人の為にパッケージ名を貸してくれる
サイトがあります。検索エンジンで”パッケージ名登録”と入力してみて
下さい。yamarouパッケージもそのサイトに登録されています。
皆さんも個人でライブラリ等を作りたい方は利用することをお薦めします。
ちなみに掲示板メッセージのファイル形式は以下のフォーマットです。
[[end]]
この形式でファイルに追記書き込みして、読み出したら逆順で画面に表示してる
というわけです。
次回はJSPに入ろうと思います。その中でStruts TagLibの使い方や、
国際化対応を取り上げます。
んじゃ
やまろう