このページでは, JavaServer Faces (JSF) を使って,リレーショナルデータベースと連携する簡単なWeb アプリケーション・プログラムを開発する手順を, 見本となるプログラムと図解で説明する.
見本となるプログラムは, ユーザ名とメールアドレスと登録種別をデータベースに登録するとともに, 固有のユーザIDを自動で割り当てる,というものです.
⇒ そのために,AccountDso という名前のクラスを定義します.
⇒ SQL とは,リレーショナルデータベースを扱うためのプログラミング言語です. Java と SQL を組み合わせて動かすために,JDBCを使う. このとき,Java のプログラムが,SQL のプログラムをリレーショナルデータベースに送りつけて,結果を待つ,という振る舞いになる. 変数を使って、Java と SQL との間のデータのやり取りを行う.
⇒ SpringJDBC を使うと簡単です. SpringJDBC とは,JDBC 抽象化フレームワークの機能を持ったソフトウェアで,Spring 2 の構成要素になっています.
そのために,AccountDao という名前のクラスを定義します. つまり,データベースの操作は,必ず AccountDao を経由する.SpringJDBC の流儀に従って書くのは,CommodityDao クラスだけということになりあmす.
⇒ そのために,Tomcat を使う.
tomcat と連携した Java サーブレットのプログラムを開発しますが, JSF の機能を使い,素の tomcat を使う場合と比べて,簡単に開発ができるよ うにします.JSF (JSF) を使った理由については,いずれ,別ペー ジで詳しく解説したいと考えています.
この Web ページに書いたプログラムは,PostgreSQL の利用で 動く.ごく簡単な設定の変更で、や MySQL の利用 や Java DB 他のリレーショナルデータベースソフトウェアでも動く.
【補足説明】
下記の 2つのサーバは別物です. 2つを同時に動かすことはできません(ポートを奪い合うことができないので).一方を動かすときは,もう一方を止めることになる.
Eclipse では,Eclipse 内部の tomcat サーバが動き, Java サーブレットの動作テストなどに使う.
Eclipse とは無関係の tomcat サーバ(C:\tomcat55\bin\tomcat5w.exe 等で起動する Tomcat サーバのこと).当然, 公開 tomcat サーバが管理するディレクトリも Eclipse とは独立している.
なお,「Eclipse 内部の tomcat サーバ」を使えるようには, Eclipse で「新規サーバの定義」を行う必要がある.これは,1回行うだけで十分です.
JSF を使ってプログラムを作成するときの作業項目は,次のようになっています.
フォーム・ビーンと言っているのは,フォームデータ(フォーム部品に,ユーザ からの記入したデータの中身)が格納される Java のマネージド・ビーン (Managed Bean) のことです.
フォーム・ビーンのクラス定義は自前で行う必要がある. フォーム・ビーンは,フォームデータを格納するための属性と,属性ごとのセッ ターとゲッターを持ちます.
入力フォームは,Web ブラウザで表示される部分のことです. テキスト,テキストエリア,チェックボックス,セレクトメニュー,ラジオボタンなどのフォーム部品と,サブミット用のボタンを配置(レイアウト)する. 今回は,プログラミングとしては,JSP と JSF の組み合わせですので, 入力フォームは,
それぞれのフォーム部品ごとに,記入内容を格納すべきフォーム・ビーンの属性名を割り当てます. 割り当ての結果,フォーム部品への入力内容が,自動的にフォーム・ビーンの属性に格納されるとともに, フォーム・ビーンの属性の値が,フォーム部品に表示(テキスト,テキストエリアなど値が表示されるフォーム部品)されます. そのために, フォーム部品ごとに,value 属性として,フォーム・ビーンのマネージド・ビーン (Managed Bean) 名 と属性名を記述することになる.
ボタンについては,それぞれのボタンごとに,アクション・コントローラ・オブジェクトのメソッド名を割り当てます. そのためには,タグの action 属性として「 action="%{hogeClass.hogeMethod}"」 のように,メソッド名(とそのメソッドに関係するマネージド・ビーン (Managed Bean) 名)を記述します. ボタンを押すと,割り当てられたアクション・コントローラ・メソッドが自動的に呼び出されるようになる. なお,JSFでは,それぞれのボタンごとに,異なるアクション・コントローラ・メソッドを割り当てるという流儀になっています.
faces-config.xml では, マネージド・ビーン (Managed Bean) 名と,Java クラスの対応を書く. さらには,faces-config.xml では, フォーム・ビーンごとに,スコープの設定,初期値の設定を行うことができる. スコープの指定は,例えば,「<managed-bean-scope>session</managed-bean-scope>」のよう に書く. このように書くと,指定されたマネージド・ビーン (Managed Bean) オブジェクトを,セッション開始時に 自動生成するようになる.
ボタンが押されると,対応するアクション・コントローラ・メソッドが自動的 に呼び出されます. このとき, フォームデータが,自動的に, Java サーブレット側にを送信され,自動生成されたフォーム・ビーンに格納されます. 詳しくは次の通りです.
まず,faces-config.xml に,アクション・コントローラ・メソッドを持つク ラス名と,マネージド・ビーン (Managed Bean) 名の対応関係を書いておきます.JSF で記述する入 力フォームのボタンの部分には,クラス名では無く,このマネージド・ビーン (Managed Bean) 名を 書く. また, faces-config.xml では, マネージド・ビーン (Managed Bean) 名と,Java クラスの対応を書くと同時に, 「<managed-bean-scope>session</managed-bean-scope>」のよう スコープの指定を書く.これは, アクション・コントローラ・メソッドを持つクラスのオブジェクトを,セッショ ン開始時に自動生成させるための記述です.
アクション・コントローラ・メソッドの戻り値は文字列(String)にす る,という決まりがあります. アクション・コントローラ・メソッドの戻り値である文字列の値によって,新しく表示すべきページが選択されます. faces-config.xml 内のナビゲーション・ルール (navigation rule) に記述された from-outcome に一致する文字列になっている場合,faces-config.xml 内のナビゲーション・ルール (navigation rule) の to-view-id に記述されたページが表示されます. これが画面遷移に関する記述です.
実際の処理を行うビジネスロジックは,上記で説明したフォーム・ビーン・オブ ジェクトや,アクション・コントローラ・メソッドを持つオブジェクト)とは分けるというのが一般の流儀です. つまり,アクション・コントローラ・メソッドが,ビジネスロジックを呼び出すことになる.
ビジネスロジックのオブジェクトを自動生成する処理は,faces-config.xml に書く.
上記のことを,実際のプログラム実行を通して理解しよう,というのがこの Web ページの目的です.
インストールしていないときは,下記の Web ページを参考に,インストールを済ませておくこと.
前もって,Tomcat インストールディレクトリと, Spring 2 インストールディレクトリを調べておいてください.このページでは,次のように書く.
データベースシステムに関する項目
データベースシステムに関するいくつかの設定内容があります. このページでは,設定内容を下記のように書くので, 違う設定にする場合には, この Web ページの説明を読み替えてください.
データベース名と, PostgreSQL にログインするために使うデータベース・一般ユーザのアカウント(ユーザ名とパスワード)を決めておくこと. このページでは,次のように書く.
使用するデータベースの名前のことを,「データベース名」と呼ぶことにする. データベース名は,自由に決めてよいが,半角文字(つまり英字と英記号)を使い,スペースを含まないこと, すでに存在するデータベースを使ってもいい(つまり,既存のデータベースのデータベース名を使う)し,新しいデータベースを作ることにしてもいいです.
データベース名 testdb の権限を持ったユーザにして下さい.(そうで無いとエラーが出ます).
この Web ページの手順を試すために,新しいデータベースと,新しい一般ユーザのアカウントを作りたいという場合は, phpPgAdmin などを使ってください.
psql のようなコマンドライン・クライアントを使う場合には,次のようになります(エンコーディングについて調べきっていません.まだ不完全です.参考情報ということでご理解下さい).
CREATE ROLE testuser LOGIN PASSWORD 'hoge$#34hoge5' NOINHERIT VALID UNTIL 'infinity'; CREATE DATABASE testdb WITH ENCODING='UTF8' OWNER=testuser;
パスワードは,説明を簡単にするために hoge$#34hoge5 と書いているが,実際には,これとは違うものを,必ず適切に設定してください.
PostgreSQL の利用 を使うために,次の設定を行うことになるので,確認しておく.
PostgreSQL 用 JDBC の Java ファイルが存在するディレクトリ C:\Program Files\psqlJDBC を探すとすぐに見つかります.
データベース名と,MySQL にログインするために使うデータベース・一般ユーザのアカウント(ユーザ名とパスワード)を, このページでは,次のように書く.
使用するデータベースの名前のことを,「データベース名」と呼ぶことにする. データベース名は,自由に決めてよいが,半角文字(つまり英字と英記号)を使い,スペースを含まないこと, すでに存在するデータベースを使ってもいい(つまり,既存のデータベースのデータベース名を使う)し,新しいデータベースを作ることにしてもいいです.
データベース名 testdb の権限を持ったユーザにして下さい.(そうで無いとエラーが出ます).
この Web ページの手順を試すために,新しいデータベースと,新しい一般ユーザのアカウントを作りたいという場合は, MySQL コマンドライン・クライアントの主な機能 や MySQL GUI Tools などを使い,次のコマンドを実行してください.
※ それぞれのツールの操作法(起動法,ログインの方法など)は,MySQL コマンドライン・クライアントの主な機能 や MySQL GUI Tools の Web ページを見てください.
create database 'testdb' default character set cp932 collate cp932_japanese_ci; create user testuser identified by 'hoge$#34hoge5'; grant all on testdb.* to 'testuser';
パスワードは,説明を簡単にするために hoge$#34hoge5 と書いているが,実際には,これとは違うものを,必ず適切に設定してください.
MySQL の利用 を使うために,次の設定を行うことになるので,確認しておく.
JDBC で MySQL を使うために必要になるので、 https://dev.mysql.com/downloads/connector/ から Connector/J をダウンロードして、解凍しておく(展開(解凍)するディレクトリは何でもよい。この資料では上記のディレクトリにあるものとして説明する)。
ダウンロードの手順は, 「MySQL コネクタ (Connector) Java のダウンロード」の Web ページで説明している.
次の設定を確認しておく.
Java DB のデータベースファイルが置かれるディレクトリのことです. これは自由に決めてよいが,半角文字(つまり英字と英記号)を使い,スペースを含まないこと, データベース名と Java DB データベースディレクトリとは別ものです.混同しないこと.
なお,Java DB データベースディレクトリは,「dbdir」 のように,相対パス形式で書く場合と,「C:\hoge\dbdir」のように,絶対パス形式で書く場合があります. 今回は,相対パス形式で書く.
データベース・ロケーションとは, データベースファイルが置かれる実際のディレクトリのことです.
Java DB データベースディレクトリを,「dbdir」のような相対パス形式にする場合, データベース・ロケーションは,Eclipse インストールディレクトリである C:\Program Files\eclipse3.5\eclipse のサブディレクトリになる. (一方で,絶対パス形式の場合は,データベース・ロケーションは,Eclipse インストールディレクトリと無関係になります). このデータベース・ロケーションは, Eclipse インストールディレクトリと,Java DB データベースディレクトリ(相対)を連結したものになる.
Java DB (Derby) インストールのときに,Eclipse プラグインもインストールしますが,その中に Java DB 用 JDBC の jar ファイルが含まれています.
テスト用データベースとして,下記の SQL コマンドで,テーブル Account が作られていること.
create table Account ( ユーザ名 VARCHAR(100) not null, メールアドレス VARCHAR(100) not null, 登録種類 VARCHAR(20) not null, ユーザID INTEGER primary key not null );
以下,Eclipse を使う. 動的 Web プロジェクトの作成,Apache MyFaces のインポートとJava サーブレットの作成とテスト実行という一連の操作を,図解で説明する.
Eclipse のプロジェクト等を作る. このページでは,Eclipse のプロジェクト名,Java パッケージ名は次のように記述します. (すでに同じ名前のプロジェクトがある,といったときは,プロジェクト名を変えてください).
ファイル構成は次のようになる.
├MYFACES ├ : ├Javaリソース; src │└hoge.hoge.com │ ├AccountDao.java │ ├AccountDso.java │ ├DataSourceFactory.java │ ├アクション.java │ ├システム内部状態.java │ ├登録ビジネスロジック.java │ └登録フォーム.java : ├WebContent ← Webアプリケーションのルート ├WEB-INF │ : │ ├faces-config.xml │ : │ ├web.xml │ : │ ├failure.jsp ├index.jsp ├success.jsp └登録画面.jsp ← 入力フォームプログラム
下記の手順で,動的 Web プロジェクトを新規に作成する.
「ウインドウ (Window)」→「ビューの表示 (Show View)」→「プロジェクト・エクスプローラ (Project Explorer)」 と操作する.
「ファイル」→「新規 (New)」→「プロジェクト (Project)」
または,プロジェクト・エクスプローラ内で,右クリック→「新規 (New)」→「プロジェクト (Project)」
新規プロジェクトのウインドウが開くので, 「Web」を展開する.
展開した「Web」の下にある 「動的 Webプロジェクト (Dynamic Web Project)」を選び, 「次へ」をクリック.
設定用のウインドウが開くので,下記の設定を行う. 設定が終わったら,「次へ」をクリック.
プロジェクト名は,好きな名前でよいが,スペースや全角文字は避けること. ここでは,プロジェクト名を,「MYFACES」と付けることにする.
「デフォルトの使用 (Use default)」にチェックを入れたままで良い.
他のもの(例えば「なし」)になっていたら,「Apache Tomcat v5.5」に変更しておく
※ 変更のとき,「なし」だけしか無くて,「Apache Tomcat v5.5」が候補として表示されない場合は, 「Eclipse を使用しての Java サーブレット・プログラムの開発」の Web ページに記載の「新規サーバの定義」を行うこと.
「次へ」をクリック.
※ このウインドウが開かないことがある.気にしなくてよい.
「終了」をクリック.
プロジェクト・エクスプローラで,いま作成した動的 Web プロジェクト MYFACES が表示されていることを確認する.
Apache MyFaces の動作確認のため, 公開されている jsf-blank プログラム (jsf-blank-myfaces-with-extensions-app.zip) を実行してみる.
https://www.tutorialspoint.com/jsf/index.htm をクリック.
今開いている Web ページの「Section 1: Introducing JSF」のところにある jsf-blank-myfaces-with-extensions-app.zip をダウンロード.
展開(解凍)してできたファイルのうち,WEB-INF/web.xml, WEB-INF/struts-config.xml, WEB-INF/lib, css/styles.css, index.jsp, welcome.jsp を使う (要するに全部を使う).
プロジェクト・エクスプローラで, プロジェクト名 MYFACES の下の「WebContent」を右クリックし,「インポート」を選ぶ.
「一般」→「ファイルシステム」と操作した後, 「次へ」をクリック.
WebContent\css, WebContent\WEB-ING\lib, WebContent\index.jsp, , WebContent\welcome.jsp が増えていることがみてとれる.web.xml などは上書きされる.
さきほど作成したプロジェクト MYFACES の lib を展開すると, MyFaces Core と MyFaces Tomahawk のバージョンが分かります. 1.1.3 のように古いバージョンになっているでしょう. バージョンアップしたいときの手順は次の通りです.
Apache MyFaces Project の ダウンロード用 Web ページで,zip 形式ファイル myfaces-core-1.1.6-bin.zip をクリック.
※ MyFaces Core 1.1 系列と,MyFacesTomahawk 1.1 系列を組み合わせて使うルールなので, MyFaces Core 1.2.4 をダウンロードしない.
一番上の URL をクリック.
どこに解凍しても良いが,後で分かりやすいように C:\Program Files\Java の下に解凍しておく. 解凍の結果,新しいディレクトリ C:\Program Files\Java\myfaces-core-1.1.6 ができる.
Apache MyFaces Project の ダウンロード用 Web ページで,zip 形式ファイル tomahawk-1.1.7-bin.zip をクリック.
一番上の URL をクリック.
どこに解凍しても良いが,後で分かりやすいように C:\Program Files\Java の下に解凍しておく. 解凍の結果,新しいディレクトリ C:\Program Files\Java\tomahawk-1.1.7 ができる.
先ほど作ったプロジェクト MYFACES に,MyFaces Core をインポートします.
プロジェクト・エクスプローラで,WebContent\Web-INF\lib を右クリックし,「インポート」を選ぶ.
「一般」→「ファイルシステム」と操作した後, 「次へ」をクリック.
上記と同様の手順で,MyFaces Tomahawk をインポートします.
プロジェクト・エクスプローラで,WebContent\Web-INF\lib を右クリックし,「インポート」を選ぶ
「一般」→「ファイルシステム」と操作した後, 「次へ」をクリック.
次のファイルを削除する.削除するには, 「lib」を展開した後,削除したいファイルを右クリックして, 「削除」を選ぶ.
Java DB (Derby) を使うときに限り,プロジェクトへのApache Derby ネーチャーの追加 と,Java DB (Derby) サーバの開始を行う. これは, Java DB (Derby) を使うための追加的な設定です.
「Apache Derby」が候補として現れないときは, Java DB (Derby) インストール の手順に従って,インストールと設定を行う.
「Derby ネットワーク・サーバの開始」が選べない状態になっているときは, すでに開始済みなので,この手順は不要.
リレーショナルデータベース・ソフトウェアとして,Java DB (Derby) 以外を使う場合は,上記は不要です.
今度は,Spring JDBC を使うための設定です.
プロジェクトへの Spring プロジェクト・ネーチャーの追加を,次の操作で行う.
「Spring ツール (Spring Tools)」が候補として現れないときは, Eclipse の SpringIDE プラグイン の手順に従って,インストールを行う.
プロジェクト名 MYFACES の左横の 「+」をクリックして展開すると, 「Spring Elements」が増えている. (Spring プロジェクト・ネーチャーの追加ができたことが分かる).
次の2種類の jar ファイルを,今度は,WebContent\WEB-INF\lib にインポートします. (先ほど,外部 jar ファイルとして追加したものと同じファイル).
Spring 2 を Java サーブレット・プログラムから使えるようにするために, Spring 2 に関する 2 つの jar ファイルをインポートします. 次の 2 つです.
C:\Program Files\Java\spring-framework-2.5\dist\spring.jar C:\Program Files\Java\spring-framework-2.5\lib\jakarta-commons\commons-logging.jar
JDBC を使いリレーショナルデータベース・ソフトウェアと接続できるようにするため,リレーショナルデータベース・ソフトウェアに付属の JDBC ファイルをインポートする必要がある. (JDBC ファイルは,使用するリレーショナルデータベース・ソフトウェアごとに違う,ということ).
プロジェクトの WebContent\WEB-INF\lib へのインポートを行う手順を下記に示す.
プロジェクト・エクスプローラで, プロジェクト名 MYFACES の左横の「+」をクリックして展開すると,「Java リソース; src」などが現れる(その他,いろいろ,プロジェクトの構成物が現れる).
※ すでに展開済みのときは,この手順は不要.
WebContent の左横の「+」をクリックして展開する.
※ すでに展開済みのときは,この手順は不要.
WEB-INF の左横の「+」をクリックして展開する.
※ すでに展開済みのときは,この手順は不要.
「一般」→「ファイルシステム」と操作した後, 「次へ」をクリック.
インポートの手順は下記の通りである.
インポートするファイルが複数あるので, lib を右クリックし,「インポート」を選ぶという手順に戻って,やり直す必要がある. (つまり,ファイルの数だけ,インポートの操作を繰り返す). 上にも書きましたが,インポートすべきファイルは,次の2種類です.
C:\Program Files\Java\spring-framework-2.5\dist\spring.jar C:\Program Files\Java\spring-framework-2.5\lib\jakarta-commons\commons-logging.jar
上記のファイルが現れないときは,Spring 2 インストール の手順に従ってインストールを行う.
C:\Program Files\psqlJDBC\postgresql-8.3-603.jdbc4.jar をインポート
C:\Program Files\Java\mysql-connector-java-5.1.6\mysql-connector-java-5.1.6-bin.jar をインポート
JDBC の jar ファイルが無い,というときは,MySQL Connector Java のダウンロードの Web ページを見てください.
C:Program Files\eclipse3.5\eclipse\plugins\org.apache.derby.core_10.5.1\derby.jar をインポート
インポートの結果,ファイルが増えたことを確認したいときは,プロジェクト・エクスプローラで,「lib」を展開する.
Eclipse のプロジェクト・エクスプローラを使って, Java パッケージを作成します. Java パッケージ名には hoge.hoge.com のようなドメイン名を付ける習慣があることに注意してください. このページでは,作成するJava パッケージ名は,hoge.hoge.com と書く. (Java パッケージ名を変えるときは,読み替えてください).
「ウインドウ」→「ビューの表示」→「プロジェクト・エクスプローラ」 と操作する.
Java パッケージの作成,クラスの作成などの作業は,プロジェクト・エクスプローラで行う.
プロジェクト・エクスプローラに,プロジェクト一覧が表示されているはずです. Java パッケージを新規作成したいプロジェクト名 MYFACES を右クリックして, 「新規」→「パッケージ」と操作する.
「Java パッケージ (Java package)」の名前として,Java パッケージ名 hoge.hoge.comを記入する.
その後,「終了」をクリック.
プロジェクト・エクスプローラにおいて, Java パッケージ hoge.hoge.com が増えていることを確認する.
※ プロジェクト・エクスプローラで, Java パッケージ名 hoge.hoge.comが表示されていないときは, プロジェクト MYFACES の左横の「+」をクリックして展開した後, 下の 「Java リソース; src」の左横の「+」をクリックして展開して下さい.
----------------------ここから---------------------- package hoge.hoge.com; import java.sql.*; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.jdbc.core.simple.ParameterizedRowMapper; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; // テーブル Person に関わる操作 public class AccountDao { // 使用するテーブル名 final private static String TABLE = "Account"; // private で SimpleJdbcTemplate オブジェクトを定義して,他のメソッドで使う,というのが決まり文句(詳しくは Spring のマニュアル) private SimpleJdbcTemplate jdbcTemplate; public void setDataSource(org.springframework.jdbc.datasource.DriverManagerDataSource dataSource) { this.jdbcTemplate = new SimpleJdbcTemplate(dataSource); } // // ステートメント実行の例 (テーブル定義) // public void initializeTable() { // executing statements; this.jdbcTemplate.update("drop table " + TABLE); // create table Account (ユーザ名 VARCHAR(100), メールアドレス VARCHAR(100), 登録種類 VARCHAR(20), ユーザID integer) this.jdbcTemplate.update("create table " + TABLE + " (ユーザ名 VARCHAR(100), メールアドレス VARCHAR(100), 登録種類 VARCHAR(20), ユーザID integer)"); } // // 更新の例(1行挿入.値の更新) // public void insertTuple(AccountDso account) { this.jdbcTemplate.update("insert into " + TABLE + " values ( '" + account.getユーザ名() + "', '" + account.getメールアドレス() + "', '" + account.get登録種類() + "', " + account.getユーザID() + " )"); } // // 問い合わせ // // タップル数 public int getCount() { return this.jdbcTemplate.queryForInt("select count(*) from " + TABLE); } public int getMaxUserID() { return this.jdbcTemplate.queryForInt("select MAX(ユーザID) from " + TABLE); } // 結果が,AccountDso オブジェクトのリスト (つまり,結果が Java の PersonDso オブジェクトに格納されている) public List<AccountDso>getAllAccount() { return this.jdbcTemplate.query( "select * from " + TABLE, new org.springframework.jdbc.core.simple.ParameterizedRowMapper<AccountDso>() { public AccountDso mapRow(ResultSet rs, int rowNum) throws SQLException { AccountDso p = new AccountDso(); p.setユーザ名(rs.getString("ユーザ名")); p.setメールアドレス(rs.getString("メールアドレス")); p.set登録種類(rs.getString("登録種類")); p.setユーザID(rs.getInt("ユーザID")); return p; } } ); } // 選択条件あり.name で選択して,PersonDso オブジェクトを出力 (name が主キーならば PersonDso オブジェクトは1つ) public AccountDso selectNameById( String name ) { return this.jdbcTemplate.queryForObject( "select * from " + TABLE + " where name = ?", new org.springframework.jdbc.core.simple.ParameterizedRowMapper<AccountDso>() { public AccountDso mapRow(ResultSet rs, int rowNum) throws SQLException { AccountDso p = new AccountDso(); p.setユーザ名(rs.getString("ユーザ名")); p.setメールアドレス(rs.getString("メールアドレス")); p.set登録種類(rs.getString("登録種類")); p.setユーザID(rs.getInt("ユーザID")); return p; } }, name ); } }; ----------------------ここまで----------------------
----------------------ここから---------------------- package hoge.hoge.com; //テーブル Account の1タップル(行)を格納するためのオブジェクト public class AccountDso { private String ユーザ名 = null; private String メールアドレス = null; private String 登録種類 = null; private int ユーザID = 0; public String getユーザ名() { return ユーザ名; } public void setユーザ名(String ユーザ名) { this.ユーザ名 = ユーザ名; } public String getメールアドレス() { return メールアドレス; } public void setメールアドレス(String メールアドレス) { this.メールアドレス = メールアドレス; } public String get登録種類() { return 登録種類; } public void set登録種類(String 登録種類) { this.登録種類 = 登録種類; } public int getユーザID() { return ユーザID; } public void setユーザID(int ユーザid) { ユーザID = ユーザid; } } ----------------------ここまで----------------------
JDBC ドライバ名,データベース名などの定義を行うクラスです. DataSourceFactory.java は,PostgreSQL 用になっているので,他のリレーショ ナルデータベースシステムを使うときは,先頭部分を書き換えることを忘れないこと.
なお,インポートすべき JDBC ファイルの jar のファイル名は,参考のため,下記のプログラム DataSourceFactory.java に記載している.
Eclipse で DataSourceFactory クラスを新規作成したら,下記のプログラムをカット&ペースト.
JDBC プログラムで,データベースシステムと接続するとき, 新しいデータベースを作るには,「;create=true」を付ける.
----------------------ここから---------------------- package hoge.hoge.com; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class DataSourceFactory { // 決まり文句 (ドライバクラス) final private static String PostgresJDBCDriver = "org.postgresql.Driver"; final private static String MySQLJDBCDriver = "org.gjt.mm.mysql.Driver"; final private static String JavaDBJDBCDriver = "org.apache.derby.jdbc.EmbeddedDriver"; final private static String HiRDBDriver = "JP.co.Hitachi.soft.HiRDB.JDBC.PrdbDriver"; // 下記の変数を正しく設定する // DBNAME, DBDIR, USER, PASS, JDBCDriver, DBURL // PostgreSQL 用デフォルト // Eclipse で PostgreSQL を使いたいときは,次の手順で,WebContent\WEB-INF\lib にインポートしておく. // WebContent\WEB-INF\lib を右クリック.「一般」→「ファイルシステム」 // その後インポートすべきファイルとして,次のファイルを指定 // C:\Program Files\psqlJDBC\postgresql-8.3-603.jdbc4.jar final private static String DBNAME = "testdb"; // Database Name final private static String USER = "testuser"; // user name for DB. final private static String PASS = "hoge$#34hoge5"; // password for DB. final private static String JDBCDriver = PostgresJDBCDriver; final private static String DBURL = "jdbc:postgresql://localhost/" + DBNAME; // MySQL 用デフォルト // Eclipse で MySQL を使いたいときは,次の手順で,WebContent\WEB-INF\lib にインポートしておく. // https://dev.mysql.com/downloads/connector/ から,Connector/J をダウンロード // c:\Program Files\Java\mysql-connector-java-5.1.6\ に置く. // WebContent\WEB-INF\lib を右クリック.「一般」→「ファイルシステム」 // その後インポートすべきファイルとして,次のファイルを指定 // c:\Program Files\Java\mysql-connector-java-5.1.6\mysql-connector-java-5.1.6-bin.jar を追加 // final private static String DBNAME = "testdb"; // Database Name // final private static String USER = "testuser"; // user name for DB. // final private static String PASS = "hoge$#34hoge5"; // password for DB. // final private static String JDBCDriver = MySQLJDBCDriver; // final private static String DBURL = "jdbc:mysql://localhost/" + DBNAME; // JavaDB用デフォルト // final private static String DBNAME = "dbdir;create=true"; // Java DB の場合は,Java DB データベースディレクトリ(相対) // final private static String DBDIR = "C:\\Program Files\\eclipse3.5\\eclipse\\"; // データベースが存在するディレクトリ // DTP, DBViewer などを使ってデータベースを生成した場合は Eclipse インストールディレクトリ // ij などを使ってデータベースを生成した場合は,c:\\<ワークスペース>\\<プロジェクト名> // final private static String USER = ""; // user name for DB. Java DB (Derby) の場合は空 // final private static String PASS = ""; // password for DB. Java DB (Derby) の場合は空 // final private static String JDBCDriver = JavaDBJDBCDriver; // final private static String DBURL = "jdbc:derby:" + DBDIR + DBNAME; // HiRDB用デフォルト // Eclipse で HiRDB を使いたいときは,次の手順で,WebContent\WEB-INF\lib にインポートしておく. // WebContent\WEB-INF\lib を右クリック.「一般」→「ファイルシステム」 // その後インポートすべきファイルとして,次のファイルを指定 // C:\win32app\hitachi\hirdb_s\CLIENT\UTL\pdjdbc.jar // ユーザ名,パスワード: C:/windows/HiRDB.iniのPDUSER の値を調べておく // final private static String USER = "ユーザ名"; // user name for HiRDB. see C:/windows/HiRDB.ini // final private static String PASS = "パスワード"; // password for HiRDB. see C:/windows/HiRDB.ini // final private static String JDBCDriver = HiRDBDriver; // final private static String HiRDBServerName = "hitachi-664320D"; // HiRDB サーバのコンピュータ名 // final private static String DBURL = "jdbc:hitachi:PrdbDrive://DBID=22200,DBHOST=" + HiRDBServerName + ",ENCODELANG=MS932"; // 'DBID=22200' is in "conf\pdsys"; DriverManagerDataSource connect() { org.springframework.jdbc.datasource.DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName((String)JDBCDriver); dataSource.setUrl(DBURL); dataSource.setUsername(USER); dataSource.setPassword(PASS); return dataSource; } } ----------------------ここまで----------------------
----------------------ここから---------------------- package hoge.hoge.com; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class アクション { private 登録ビジネスロジック logic; private 登録フォーム regform; // 以下のうち,2つのセッターはJSFが呼び出す. // ※ JSFコンテナのほうで,登録ビジネスロジックと,登録フォームという // 2つのアプリケーションオブジェクトを保持する. public 登録ビジネスロジック getLogic() { return logic; } public void setLogic(登録ビジネスロジック logic) { this.logic = logic; } public 登録フォーム getRegform() { return regform; } public void setRegform(登録フォーム regform) { this.regform = regform; } // アクション・コントロール・メソッド public String doRegistration() { // JFS で HttpServletRequest, HttpSession を取得するときの決まり文句 ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); HttpServletRequest request = (HttpServletRequest)context.getRequest(); HttpSession session = request.getSession(); // セッション変数に入っていれば,ビジネスロジックにも設定済みなので,何もしない. システム内部状態 state = (システム内部状態)session.getAttribute("systemState"); if ( state == null ) { state = new システム内部状態(); state.reset(); session.setAttribute("systemState", state); logic.setSystemState(state); } AccountDao accountDao = (AccountDao)session.getAttribute("accountDao"); if ( accountDao == null ) { DataSourceFactory dataSourceFactory = new DataSourceFactory(); DriverManagerDataSource dataSource = dataSourceFactory.connect(); accountDao = new AccountDao(); accountDao.setDataSource(dataSource); session.setAttribute("accountDao", accountDao); logic.setAccountDao(accountDao); } //登録処理 logic.registration(this.regform); // いつも成功 return "success"; // return "failure"; } } ----------------------ここから----------------------
----------------------ここから---------------------- package hoge.hoge.com; public class システム内部状態 { // システムの内部状態の保持. private int ユーザID = 0; private boolean 初期済か = false; // true ならば,ユーザIDに正しい値が入っているという意味 private String 最終アクセスページID = null; // JSP 内の hiddenInput // 「<h:inputHidden value="index" binding="#{regform.hiddenInput}"/>」でバインディング // などで送られてくる「"index"」を入れる public int getユーザID() { return ユーザID; } public void setユーザID(int ユーザid) { ユーザID = ユーザid; } public boolean is初期済か() { return 初期済か; } public void set初期済か(boolean 初期済か) { this.初期済か = 初期済か; } public String get最終アクセスページID() { return 最終アクセスページID; } public void set最終アクセスページID(String 最終アクセスページid) { 最終アクセスページID = 最終アクセスページid; } public void reset() { this.ユーザID = 0; this.初期済か = false; this.最終アクセスページID = null; } } ----------------------ここまで----------------------
package hoge.hoge.com; import java.util.Date; public class 登録ビジネスロジック { // システムの内部状態の保持. private システム内部状態 state = null; public void setSystemState(システム内部状態 data) { this.state = data; } public システム内部状態 getSystemState() { return this.state; } // データアクセスオブジェクト (Dao) の保持. private AccountDao accountDao = null; public void setAccountDao(AccountDao DAO) { this.accountDao = DAO; } public AccountDao getAccountDao() { return this.accountDao; } private void createNewId(){ System.out.println("ユーザID設定開始"); if ( !this.state.is初期済か() ) { System.out.println("ユーザID取得"); // データベースが空の場合,ユーザIDを1にセットし, // 空で無い場合,データベース内のユーザIDの最大値に1足した値にセットする if ( this.accountDao.getCount() == 0 ) { this.state.setユーザID(1); } else { this.state.setユーザID( this.accountDao.getMaxUserID() + 1 ); } this.state.set初期済か(true); } else { // システム内部状態が初期済みなら,その「ユーザID」属性の値に1足すだけの処理 int id = this.state.getユーザID(); this.state.setユーザID( id + 1 ); } } /** * 登録ビジネスロジックの実装 * 初期登録(Registration)の場合,DBにデータを登録 * 登録フォームオブジェクトを与えて呼び出すこと. */ public void registration( 登録フォーム regform ){ // ユーザIDの生成 this.createNewId(); // システム内部状態の「最終アクセスページID」の更新 this.state.set最終アクセスページID(regform. getHiddenInput().getValue().toString()); // タップル挿入 AccountDso a = new AccountDso(); a.setユーザ名(regform.getユーザ名_必須()); a.setメールアドレス(regform.getメールアドレス_必須()); a.set登録種類(regform.get登録種類_必須()); a.setユーザID(this.state.getユーザID()); // this.accountDao.initializeTable(); this.accountDao.insertTuple(a); // 確認表示 System.out.println("--システム内部状態--"); System.out.println("PAGEID:"+this.state.get最終アクセスページID()); System.out.println("--DBに登録--"); System.out.println("ユーザ名:"+a.getユーザ名()); System.out.println("メールアドレス:"+a.getメールアドレス()); System.out.println("登録種類:"+a.get登録種類()); System.out.println("ユーザID:"+a.getユーザID()); System.out.println("以上のデータでDBにINSERTしました"); System.out.println("DATE:"+(new Date())); } } ----------------------ここまで----------------------
----------------------ここから---------------------- package hoge.hoge.com; import java.util.List; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; // アクションフォーム・クラス // 入力フォームデータの格納を行うとともに,アクション・コントロール・メソッドも持つ public class 登録フォーム { private String ユーザ名_必須 = null; private String メールアドレス_必須 = null; private String 登録種類_必須 = null; // JSP 内の「<h:inputHidden value="index" binding="#{regform.hiddenInput}"/>」でバインディング public javax.faces.component.html.HtmlInputHidden hiddenInput = null; public String getユーザ名_必須() { return ユーザ名_必須; } public void setユーザ名_必須(String ユーザ名_必須) { this.ユーザ名_必須 = ユーザ名_必須; } public String getメールアドレス_必須() { return メールアドレス_必須; } public void setメールアドレス_必須(String メールアドレス_必須) { this.メールアドレス_必須 = メールアドレス_必須; } public String get登録種類_必須() { return 登録種類_必須; } public void set登録種類_必須(String 登録種類_必須) { this.登録種類_必須 = 登録種類_必須; } public javax.faces.component.html.HtmlInputHidden getHiddenInput() { return hiddenInput; } public void setHiddenInput( javax.faces.component.html.HtmlInputHidden hiddenInput) { this.hiddenInput = hiddenInput; } public void reset(){ this.ユーザ名_必須 = null; this.メールアドレス_必須 = null; this.登録種類_必須 = null; } } ----------------------ここまで----------------------
4つのJSPファイル index.jsp, success.jsp, failure.jsp, 登録画面.jsp を作成する.
----------------------ここから---------------------- <%@ page contentType="text/html; charset=utf-8" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="https://myfaces.apache.org/tomahawk" prefix="t" %> <f:view> <html> <head> <!-- タイトルを適切に付ける--> <title> 登録画面 </title> </head> <body> <h:form id="form1"> <!-- inputHidden の value="ほにゃらら" の部分は,value="index" のように,ページIDを付ける --> <h:inputHidden value="index" binding="#{regform.hiddenInput}"/> <H1> <center>登録画面</center> </H1> <f:subview id="table"> <!-- インクルードするJSPファイル名は,画面ごとに異なる.書き換えて下さい--> <%@ include file="登録画面.jsp"%> </f:subview> </h:form> </body> </html> </f:view> ----------------------ここまで----------------------
ラジオボタンは2段組にしている(tomahawk の機能)
----------------------ここから---------------------- <%@ page contentType="text/html; charset=utf-8" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="https://myfaces.apache.org/tomahawk" prefix="t" %> <center> <!-- panelGrid は,複数の列があるような表 --> <h:panelGrid columns="2"> <h:outputLabel for="text1" value="ユーザ名" /> <h:inputText id="text1" value="#{regform.ユーザ名_必須}"/> <h:outputLabel for="text2" value="メールアドレス" /> <h:inputText id="text2" value="#{regform.メールアドレス_必須}"/> <!-- 入れ子表 (ラジオボタンを2列にしたいときは columns="2", 1列にしたいときは columns="1"--> <h:panelGrid columns="2"> <h:outputLabel value="登録種類" /> <!-- layout="spread" にしているので,ラジオボタンを作るが表示はされない(2カラム表示を可能にするための工夫) --> <t:selectOneRadio id="radio1" value="#{regform.登録種類_必須}" layout="spread" styleClass="selectOneRadio"> <f:selectItem itemValue="学生" itemLabel="学生"/> <f:selectItem itemValue="登録会員" itemLabel="登録会員"/> <f:selectItem itemValue="その他の会員" itemLabel="その他の会員"/> <f:selectItem itemValue="非会員" itemLabel="非会員"/> </t:selectOneRadio> <!-- 作ったラジオボタンの表示.for="???" 部分は一致させること.index は 0 から始まる --> <t:radio for="radio1" index="0" /> <t:radio for="radio1" index="1" /> <t:radio for="radio1" index="2" /> <t:radio for="radio1" index="3" /> </h:panelGrid> <h:outputLabel value="" /> <h:commandButton id="button1" value="登録" action="#{action.doRegistration}"/> </h:panelGrid> </center> ----------------------ここまで----------------------
----------------------ここから---------------------- <%@ page contentType="text/html; charset=utf-8" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="https://myfaces.apache.org/tomahawk" prefix="t" %> <f:view> <html> <head> <!-- タイトルを適切に付ける--> <title> 登録成功 </title> </head> <body> <h:form id="form1"> <H1> <center>登録成功</center> </H1> <p> ユーザ名: <h:outputText value="#{regform.ユーザ名_必須}" /> </p> <p> メールアドレス: <h:outputText value="#{regform.メールアドレス_必須}" /> </p> <p> 登録種類: <h:outputText value="#{regform.登録種類_必須}" /> </p> <p> 登録に成功しました </p> <p> <h:commandButton value="初めに戻る" action="returnToStart"/> </p> </h:form> </body> </html> </f:view> ----------------------ここまで----------------------
----------------------ここから---------------------- <%@ page contentType="text/html; charset=utf-8" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="https://myfaces.apache.org/tomahawk" prefix="t" %> <f:view> <html> <head> <!-- タイトルを適切に付ける--> <title> 登録失敗 </title> </head> <body> <h:form id="form1"> <H1> <center>登録失敗</center> </H1> <p> ユーザ名: <h:outputText value="#{regform.ユーザ名_必須}" /> </p> <p> メールアドレス: <h:outputText value="#{regform.メールアドレス_必須}" /> </p> <p> 登録種類: <h:outputText value="#{regform.登録種類_必須}" /> </p> <p> 登録に失敗しました </p> </h:form> </body> </html> </f:view> ----------------------ここまで----------------------
WEB-INF/lib/web.xml を,以下の手順で書き換える.
web.xml は下記のようにする.これは,JSF を使うときの決まり文句なので,悩まないこと.
編集が終わったら,プロジェクト・エクスプローラで,web.xml を右クリックして,「リフレッシュ」(または「更新)を選ぶ.
extensionFilter の部分は、Apahce MyFaces の tomahawk コンポーネントと、sandbox コンポーネントを使うときに必要になる。
(特記事項) web.xml の書き方は、tomahawk のバージョンに依存する。 下記に書いた web.xml は、tomahawk のバージョン 1.1.6 で確認済み。
----------------------ここから---------------------- <?xml version="1.0" encoding="UTF-8"?> <!-- * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. --> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>MyFaces Application</display-name> <!-- Extensions Filter --> <filter> <filter-name>MyFacesExtensionsFilter</filter-name> <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class> <init-param> <param-name>maxFileSize</param-name> <param-value>20m</param-value> </init-param> </filter> <filter-mapping> <filter-name>MyFacesExtensionsFilter</filter-name> <!-- servlet-name must match the name of your javax.faces.webapp.FacesServlet entry --> <servlet-name>Faces Servlet</servlet-name> </filter-mapping> <!-- extension mapping for serving page-independent resources (javascript, stylesheets, images, etc.) --> <filter-mapping> <filter-name>MyFacesExtensionsFilter</filter-name> <url-pattern>/faces/myFacesExtensionResource/*</url-pattern> </filter-mapping> <!-- servlet --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- servlet-mapping --> <!-- <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <!-- The Usual Welcome File List --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app> ----------------------ここまで----------------------
faces-config.xml は、ビーン名とクラス名のマッピングを取るなどのためのファイル。 ここでの設定の要点は下記の通りです.このことを頭に入れて理解してください.
マネージド・ビーン (Managed Bean)
----------------------ここから---------------------- <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"> <faces-config> <managed-bean> <managed-bean-name>regform</managed-bean-name> <managed-bean-class>hoge.hoge.com.登録フォーム</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>logic</managed-bean-name> <managed-bean-class>hoge.hoge.com.登録ビジネスロジック</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>action</managed-bean-name> <managed-bean-class>hoge.hoge.com.アクション</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>logic</property-name> <property-class>hoge.hoge.com.登録ビジネスロジック</property-class> <value>#{logic}</value> </managed-property> <managed-property> <property-name>regform</property-name> <property-class>hoge.hoge.com.登録フォーム</property-class> <value>#{regform}</value> </managed-property> </managed-bean> <navigation-rule> <from-view-id>*</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/success.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/failure.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>returnToStart</from-outcome> <to-view-id>/index.jsp</to-view-id> </navigation-case> </navigation-rule> </faces-config> ----------------------ここまで----------------------
ウインドウが開くので, 「ローカルホストの Tomcat v5.5 サーバ」が選択されていることを確認の後,「終了」をクリック.
コンソール・ビューの表示を確認する.
Eclipse の 組み込み Web ブラウザ (Internal Web ブラウザ)が開き,そこに実行結果が出る.
うまく動作しないときの確認項目