◆カスタムタグとは? JSPで自分で作ったタグの動作を定義できる機能です。 ◆ボディがある場合とない場合の2種類のタグがあります ボディありのタグとは下のようにタグの中になんらかの記述がある場合です。 ここがボディの記述 ボディなしのタグとは下のようなタグのことです。 タグハンドラ(ボディが無い場合)の作成 タグハンドラを作成します。タグハンドラとはタグを処理するクラスのことです。 タグハンドラはTagインターフェースまたはBodyTagインターフェースを実装(implements)しなければなりません。ボディを処理しない場合またはボディがない場合はTagインターフェース、ボディを処理する場合はBodyTagインターフェースを実装(implements)します。実際にはタグハンドラはTagインターフェースを実装(implements)したTagSupportクラス、またはBodyTagインターフェースを実装(implements)したBodyTagSupportクラスを継承(extends)すればいいようになっています。 ボディの有無 インターフェース クラス 無し Tag TagSupport 有り BodyTag BodyTagSupport ◆ここで使用するファイル HelloWorldTag.java タグハンドラ (タグ名:helloworld) helloworld.tld タグライブラリディスクリプタ hellowroldtag.jsp JSPファイル ◆タグハンドラ(ボディが無い場合)のコード HelloWorldTag.java(ここからダウンロード) package javahello; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class HelloWorldTag extends TagSupport { public int doStartTag() throws JspException { try { // Hello Worldと出力 pageContext.getOut().print("Hello World"); } catch (Exception e) { throw new JspException(e.getMessage()); } return SKIP_BODY; } public int doEndTag() { return EVAL_PAGE; } } ■メソッドの説明 メソッド 説明 doStartTag() 開始タグを処理するメソッド doEndTag() 終了タグを処理するメソッド ■メソッドの戻り値の説明 メソッド 戻り値 説明 doStartTag() SKIP_BODY ボディをJSPとして評価しない場合 EVAL_BODY_INCLUDE ボディをJSPとして評価する場合 doEndTag() SKIP_PAGE 終了タグ以降のJSPを評価しない EVAL_PAGE 終了タグ以降のJSPを評価する ◆タグハンドラのコンパイル タグハンドラをコンパイルするにはservlet.jarをクラスパスに追加する必要があります。servlet.jarはTomcatのフォルダの下のcommon\libの下に入っています。(CLASSPATHへの追加方法はアプリケーション編を参考にしてください。 コマンドプロンプト C:\作業フォルダ\JavaHello>javac HelloWorldTag.java C:\作業フォルダ\JavaHello> ◆タグディスクリプタライブラリファイルの作成 タグディスクリプタライブラリファイルを作成します。タグディスクリプタライブラリファイルとはタグに関する情報を記述してあるXML形式のファイルです。 helloworld.tld(ここからダウンロード) 1.0 1.1 javahello JavaでHello World タグライブラリ helloworld javahello.HelloWorldTag empty Hello Worldと出力 ■タグディスクリプタのタグの説明 このタグライブラリに関する情報 タグ 説明 tlibversion このタグライブラリのバージョン jspversion 使用するJSPのバージョン(optional) shortname このタグライブラリの短縮名 uri このタグライブラリのURIを指定(optional) info このタグライブラリの説明(optional) tag タグに関する情報。1つ以上記述。(下記 タグに関する情報を参照) タグに関する情報 タグ 説明 name タグ名 tagclass このタグを処理するタグハンドラクラスの完全修飾パッケージ名を指定。 teiclass TEIクラスの完全修飾パッケージ名を指定。(optional) bodycontent ボディの内容のタイプを指定 以下の3つを指定可能 tagdependent・・・ボディがSQL文などのJSP以外の記述である場合。 JSP・・・ボディがJSPの構文を含んでいる場合。 empty・・・ボディが無い場合 info このタグの説明(optional) attribute タグが属性を持つ場合、その属性情報を指定(下記 タグの属性に関する情報を参照) タグの属性に関する情報 タグ 説明 name タグの属性名 required この属性が必ず必要か、任意かを指定。この要素を指定しない場合はfalseを指定したと同じになる。(optional) true,false,yes,noを指定可能 rtexprvalue 属性の値の指定がJSPのスクリプトであるかないかを指定。この要素を指定しない場合はfalseを指定したと同じになる。(optional) true,false,yes,noを指定可能 例) trueまたはyesの場合 上記のように属性の値を指定可能。 optional・・・省略可能 ◆JSPコード helloworldtag.jsp(ここからダウンロード) <%@ page contentType="text/html; charset=Shift_JIS" %> <%@ page import="javahello.HelloWorldTag" %> <%@ taglib uri="/jsp/helloworld.tld" prefix="hw" %> Hello World Jsp Custom Tag ◆TomcatへのファイルのコピーとTomcatの再起動 これで必要なファイルが全て整いました。Tomcatで見れるようにするためにファイルをコピーします。Tomcatのフォルダ\webapps\examples\WEB-INF\classes\javahelloフォルダを作成してください。 HelloWorldTag.class → Tomcatのフォルダ\webapps\examples\WEB-INF\classes\javahello helloworld.tld → Tomcatのフォルダ\webapps\examples\jsp helloworldtag.jsp → Tomcatのフォルダ\webapps\examples\jsp コピーできましたらTomcatを再起動しましょう。 ◆ブラウザーで見てみよう! 以下のURLを指定してブラウザで見てみましょう。 http://localhost:8080/examples/jsp/helloworldtag.jsp ------------------------ タグハンドラ(ボディが有る場合)の作成 次にボディがある場合に挑戦してみましょう。ここではJDBCでデータベースに接続して結果を表示するタグを作ります。 ◆ここで使用するファイル HelloWorldQueryTag.java データベースに接続して結果セットを得るタグハンドラ (タグ名:query) HelloWorldBodyTag.java 検索結果を表示するタグハンドラ (タグ名:foreach) HelloWorldBodyTEI.java foreachタグのTEIクラス helloworld.tld タグライブラリディスクリプタ hellowroldbodytag.jsp JSPファイル ◆タグハンドラ(ボディが有る場合)のコード ■データベースに接続して結果セットを得るタグハンドラ(タグ名:query) HelloWorldQueryTag.java(ここからダウンロード) package javahello; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.sql.*; public class HelloWorldQueryTag extends BodyTagSupport { String url; String jdbcClass; String userName; String passwd; Connection con; Statement stmt; public void setUrl(String url) { this.url = url; } public String getUrl() { return url; } public void setJdbcClass(String jdbcClass) { this.jdbcClass = jdbcClass; } public String getJdbcClass() { return jdbcClass; } public void setUserName(String userName) { this.userName = userName; } public String getUserName() { return userName; } public void setPasswd(String passwd) { this.passwd = passwd; } public String getPasswd() { return passwd; } public int doAfterBody() throws JspTagException { BodyContent bc = getBodyContent(); String query = bc.getString(); bc.clearBody(); try { // ドライバクラスをロード Class.forName(jdbcClass); // データベースへ接続 con = DriverManager.getConnection(url, userName, passwd); // ステートメントオブジェクトを生成 stmt = con.createStatement(); // 結果セットを取得 ResultSet result = stmt.executeQuery(query); // 属性をセット pageContext.setAttribute(id,result); } catch (Exception e) { throw new JspTagException(e.getMessage()); } return SKIP_BODY; } public void release() { try { stmt.close(); con.close(); } catch (Exception e) { e.printStackTrace(); } } } ■検索結果を表示するタグハンドラ(タグ名:foreach) HelloWorldBodyTag.java(ここからダウンロード) package javahello; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.sql.*; import java.io.*; public class HelloWorldBodyTag extends BodyTagSupport { private ResultSet result; public HelloWorldBodyTag() { super(); } public ResultSet getResult() { return result; } public void setResult(ResultSet result) { this.result = result; } public int doStartTag() throws JspTagException { result = (ResultSet) pageContext.getAttribute(id); try { if (result.next()) { pageContext.setAttribute(id, result); // 結果が存在する場合はボディを評価する return EVAL_BODY_AGAIN; } else { return SKIP_BODY; } } catch (Exception e) { throw new JspTagException(e.getMessage()); } } public int doAfterBody() throws JspTagException { // ボディの内容を取得 BodyContent body = getBodyContent(); try { // ボディを出力 body.writeOut(getPreviousOut()); } catch (IOException e) { throw new JspTagException(e.getMessage()); } body.clearBody(); try { if (result.next()) { // まだ行が残っている場合はボディの評価を繰り返す return EVAL_BODY_AGAIN; } else { return SKIP_BODY; } } catch (SQLException e) { throw new JspTagException(e.getMessage()); } } public int doEndTag() { return EVAL_PAGE; } public void release() { result = null; } } ■メソッドの説明 メソッド 説明 doStartTag() 開始タグを処理するメソッド doAfterBody() ボディ評価後の処理をするメソッド doEndTag() 終了タグを処理するメソッド release() リソースの開放を行うメソッド ■メソッドの戻り値の説明 メソッド 戻り値 説明 doStartTag() SKIP_BODY ボディをJSPとして評価しない場合 EVAL_BODY_AGAIN ボディをJSPとして評価する場合 doAfterBody() SKIP_BODY ボディをJSPとして評価しない場合 EVAL_BODY_AGAIN 再びボディをJSPとして評価する場合 doEndTag() SKIP_PAGE 終了タグ以降のJSPを評価しない EVAL_PAGE 終了タグ以降のJSPを評価する ◆TEIクラスの作成 TEI(Tag extra infomation)クラスを使用すればタグの中の属性に設定されている値を変数として使用することができます。この変数のことをスクリプト変数といいます。TEIクラスはTagExtraInfoクラスを継承します。 例) <%=helloResult.getInt("NO") %> ◆TEIクラスのコード HelloWorldBodyTEI.java(ここからダウンロード) import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.io.IOException; public class HelloWorldBodyTEI extends TagExtraInfo { public VariableInfo[] getVariableInfo(TagData tagData) { VariableInfo[] vars = new VariableInfo[1]; vars[0] = new VariableInfo(tagData.getId(), "java.sql.ResultSet", true, VariableInfo.NESTED); return vars; } } ■説明 getVariableInfoメソッドで使用するスクリプト変数の情報を返すようにします。戻り値はVariableInfoクラスの使用するスクリプト変数の数の長さの配列になります。VariableInfoクラスについてはJ2EEのJava APIドキュメントを参照してください。 ◆タグディスクリプタライブラリファイルの編集 タグディスクリプタライブラリファイルを以下のように編集します。 helloworld.tld(ここからダウンロード) 1.0 1.1 javahello JavaでHello World タグライブラリ helloworld javahello.HelloWorldTag empty Hello Worldと出力 query javahello.HelloWorldQueryTag tagdependent 結果セットを取得 url true jdbcClass true userName true passwd true id true foreach javahello.HelloWorldBodyTag javahello.HelloWorldBodyTEI JSP 結果セットを表示 id true ◆JSPコード (helloworldbodytag.jsp) <%@ page contentType="text/html; charset=Shift_JIS" %> <%@ page import="javahello.*" %> <%@ taglib uri="/jsp/helloworld.tld" prefix="hw" %> Hello World Jsp Custom Tag SELECT * FROM HELLO_WORLD_TABLE
NO 言語 メッセージ
<%=helloResult.getInt("NO") %> <%=helloResult.getString("LANGUAGE") %> <%=helloResult.getString("MESSAGE") %>
◆TomcatへのファイルのコピーとTomcatの再起動 Tomcatで見れるようにするためにファイルをコピーします。 HelloWorldQueryTag.class → Tomcatのフォルダ\webapps\examples\WEB-INF\classes\javahello HelloWorldBodyTag.class → Tomcatのフォルダ\webapps\examples\WEB-INF\classes\javahello HelloWorldBodyTEI.class → Tomcatのフォルダ\webapps\examples\WEB-INF\classes\javahello helloworld.tld → Tomcatのフォルダ\webapps\examples\jsp helloworldbodytag.jsp → Tomcatのフォルダ\webapps\examples\jsp ---------------------------------- ---------------------------------- ◆データベースの用意 ◆MySQLとは? MySQLは無料で使えるオープンソースのデータベースです。使いやすく軽快に動作することが特徴のRDBMS(リレーショナルデータベース管理システム)です。 ◆ここでの環境 OS Windows XP J2SE SDK 1.4.0 データベース MySQL (バージョン3.23.49) ◆MySQLのダウンロードとインストール MySQLはwww.mysql.comからダウンロードできます。ここではバージョン3.23.49のWindows版をダウンロードしました。 MySQLのダウンロード → http://www.mysql.com/downloads/ ダウンロードしたファイルを解凍したフォルダに入っているSETUP.EXEを実行することでインストールできます。 ◆環境変数PATHの設定 環境変数PATHの値の一番最後にセミコロンを入れてC:\mysql\binを追加してください。環境変数の設定方法はアプリケーション編を参考にしてください。これでMySQLのコマンドが使えるようになります。 ◆MySQLの起動 MySQLの起動はmysqldコマンドでできます。--default-character-set=sjisを引数で指定して使用する文字セットを設定します。 コマンドプロンプト C:\>mysqld --default-character-set=sjis ◆データベースの表示 存在するデータベースをみるにはmysqlshowコマンドでできます。最初から「mysql」と「test」という名前のデータベースが用意されています。新しいコマンドプロンプトを立ち上げてmysqlshowコマンドを実行してみましょう。 コマンドプロンプト C:\>mysqlshow +-----------+ | Databases | +-----------+ | mysql | | test | +-----------+ C:\> ◆データベースの作成 自分のデータベースを作ってみましょう。データベースの作成はmysqladminコマンドでできます。ここでは「hellodb」という名前のデータベースを作ることにします。 コマンドプロンプト C:\>mysqladmin -u root create hellodb C:\> 作成されたかどうか見てみましょう。 コマンドプロンプト C:\>mysqlshow +-----------+ | Databases | +-----------+ | hellodb | | mysql | | test | +-----------+ C:\> 作成されていますね。 ◆対話型MySQLクライアントの起動 MySQLにはmysqlというコマンドで起動できる対話型ツールが利用できます。これを使用することによってデータベースに接続してSQL文を実行することができます。それでは実際にhellodbデータベースに接続してみましょう。 コマンドプロンプト C:\>mysql -u root hellodb Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 23 to server version: 3.23.49-nt Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> これでデータベースに接続できました。 ◆テーブルの作成 SQL文を実行してテーブルを作成してみることにします。以下がここで実行するSQL文です。 テーブルを作成するSQL文 CREATE TABLE HELLO_WORLD_TABLE ( NO INTEGER NOT NULL, LANGUAGE VARCHAR(50), MESSAGE VARCHAR(100), PRIMARY KEY(NO) ); それではSQL文を入力してみましょう。(上のSQL文をコピーしてコマンドラインに貼り付けてもOKです) コマンドプロンプト mysql> CREATE TABLE HELLO_WORLD_TABLE ( -> NO INTEGER NOT NULL, -> LANGUAGE VARCHAR(50), -> MESSAGE VARCHAR(100), -> PRIMARY KEY(NO) -> ); Query OK, 0 rows affected (0.01 sec) mysql> これでテーブルが作成されました。ほんとに作成されているかテーブル一覧を表示していましょう。テーブル一覧を表示するにはshow tablesというコマンドでできます。 コマンドプロンプト mysql> show tables; +-------------------+ | Tables_in_hellodb | +-------------------+ | hello_world_table | +-------------------+ 1 row in set (0.00 sec) mysql> できていますね。 ◆テーブルにデータの追加 それではテーブルにデータを作ってみましょう。ここで作るデータは以下のようなデータです。 NO LANGUAGE MESSAGE 1 日本語 こんにちわ 世界 2 英語 Hello World 上記のデータを追加するには以下のような2つのSQL文を実行します。 テーブルにデータを追加するSQL文 INSERT INTO HELLO_WORLD_TABLE VALUES ( 1 , '日本語' , 'こんにちわ 世界'); INSERT INTO HELLO_WORLD_TABLE VALUES ( 2 , '英語' , 'Hello World'); SQL文を入力して実行してみましょう。(上のSQL文をコピーしてコマンドラインに貼り付けてもOKです) コマンドプロンプト mysql> INSERT INTO HELLO_WORLD_TABLE -> VALUES ( 1 , '日本語' , 'こんにちわ @世界'); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO HELLO_WORLD_TABLE -> VALUES ( 2 , '英語' , 'Hello World');; Query OK, 1 row affected (0.00 sec) mysql> 正常に追加されているか見てみることにしましょう。テーブルのデータを見るには以下のSQL文を実行します。 テーブルのデータを表示するSQL文 SELECT * FROM HELLO_WORLD_TABLE; SQL文を入力して実行してみましょう。(上のSQL文をコピーしてコマンドラインに貼り付けてもOKです) コマンドプロンプト mysql> SELECT * FROM HELLO_WORLD_TABLE; +----+----------+------------------+ | NO | LANGUAGE | MESSAGE | +----+----------+------------------+ | 1 | 日本語 | こんにちわ 世界 | | 2 | 英語 | Hello World | +----+----------+------------------+ 2 rows in set (0.00 sec) mysql> データが正常に追加されていますね。これでここでの対話型ツールでの作業は一通り終わったので対話型ツールを終了させましょう。終了するにはquitというコマンドを実行します。 コマンドプロンプト mysql> quit Bye C:\> ◆JDBCドライバのダウンロードとCLASSPATHへの追加 JavaのアプリケーションからMySQLのデータベースへ接続するにはJDBCドライバが必要です。ODBC経由でAccessに接続する場合はJ2SE SDKに最初からドライバが入っているので必要ありませんでしたが、MySQLの場合はドライバをダウンロードしてCLASSPATHへ追加しなければなりません。ドライバって言っていますが普通のJavaのライブラリです。 JDBCドライバのダウンロード → http://www.mysql.com/downloads/api-jdbc.html ここではMySQL Connector/J 2 をダウンロードしました。 (ファイル名:mysql-connector-java-2.0.14.zip) ダウンロードしたらそのファイルを解凍しなければいけません。解凍するにはjarコマンドを使用します。 (参考) ダウンロードしたzipファイルを解凍するには コマンドプロンプト C:\作業フォルダ\MySQL>jar -xf mysql-connector-java-2.0.14.zip C:\作業フォルダ\MySQL> 解凍してできたmysql-connector-java-2.0.14という名前のフォルダに入っているmysql-connector-java-2.0.14-bin.jarをCLASSSPATHに追加してください。(追加方法はアプリケーション編を参考) ◆検索した結果を表示するコードの作成 ■Javaソースコード JDBC編でODBC経由でAccessに接続した場合との違いは 1.ドライバクラスの違い 2.データベースのURLの違い だけです。 わかりやすいようにODBCの場合のコードをコメントアウトして残してあります。 HelloWorldJDBCMySQL.java(ここからダウンロード) import java.sql.*; public class HelloWorldJDBCMySQL { public static void main(String[] args) { try { // ドライバクラスをロード // Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); // ODBCの場合 Class.forName("org.gjt.mm.mysql.Driver"); // MySQLの場合 // データベースへ接続 // Connection con = // DriverManager.getConnection("jdbc:odbc:helloworld"); // ODBCの場合 // MySQLの場合 String url = "jdbc:mysql:///hellodb?useUnicode=true&characterEncoding=SJIS"; Connection con = DriverManager.getConnection(url); // ステートメントオブジェクトを生成 Statement stmt = con.createStatement(); String sql = "SELECT * FROM HELLO_WORLD_TABLE"; // クエリーを実行して結果セットを取得 ResultSet rs = stmt.executeQuery(sql); // 検索された行数分ループ while(rs.next()){ // NOを取得 int no = rs.getInt("NO"); // 言語を取得 String lang = rs.getString("LANGUAGE"); // メッセージを取得 String msg = rs.getString("MESSAGE"); // 表示 System.out.println(no + " " + lang + " " + msg); } // データベースから切断 stmt.close(); con.close(); } catch (Exception e) { e.printStackTrace(); } } } ■コンパイルと実行 コマンドプロンプト C:\作業フォルダ\JavaHello>javac HelloWorldJDBCMySQL.java C:\作業フォルダ\JavaHello>java HelloWorldJDBCMySQL 1 日本語 こんにちわ 世界 2 英語 Hello World C:\作業フォルダ\JavaHello> おおおおお!表示されましたね! ◆行の削除、更新、追加をするコードの作成 次に行の削除、更新、追加を行うコードを作成します。行の削除、更新、追加を行うにはStatementインターフェースのexecuteUpdateメソッドを使用します。executeUpdateメソッドの戻り値は削除、更新、追加した行数になります。また、検索の場合はexecuteQueryメソッドを使用します。 HelloWorldJDBCMySQLUpdate.java(ここからダウンロード) import java.sql.*; public class HelloWorldJDBCMySQLUpdate { public static void main(String[] args) { try { // ドライバクラスをロード Class.forName("org.gjt.mm.mysql.Driver"); // データベースへ接続 String url = "jdbc:mysql:///hellodb?useUnicode=true&characterEncoding=SJIS"; Connection con = DriverManager.getConnection(url); // ステートメントオブジェクトを生成 Statement stmt = con.createStatement(); // NOが3の行を削除するSQL文を作成します String sql = "DELETE FROM HELLO_WORLD_TABLE " + "WHERE HELLO_WORLD_TABLE.NO=3"; // クエリーを実行します int result = stmt.executeUpdate(sql); System.out.println(result + "行削除しました"); // NOが3の行を新しく追加するSQL文を作成します sql = "INSERT INTO HELLO_WORLD_TABLE (NO,LANGUAGE,MESSAGE) " + "VALUES(3 ,'ドイツ語','Hallo Welt')"; // クエリーを実行します result = stmt.executeUpdate(sql); System.out.println(result + "行追加しました"); // NOが1の行を新しい値で更新するSQL文を作成します sql = "UPDATE HELLO_WORLD_TABLE "+ "SET LANGUAGE='スペイン語',MESSAGE='Hola Mundo' " + "WHERE HELLO_WORLD_TABLE.NO=1"; // クエリーを実行します result = stmt.executeUpdate(sql); System.out.println(result + "行更新しました"); // 全ての行を検索するSQL文を作成 sql = "SELECT * FROM HELLO_WORLD_TABLE"; // クエリーを実行して結果セットを取得 ResultSet rs = stmt.executeQuery(sql); // 検索された行数分ループ while(rs.next()){ // NOを取得 int no = rs.getInt("NO"); // 言語を取得 String lang = rs.getString("LANGUAGE"); // メッセージを取得 String msg = rs.getString("MESSAGE"); // 表示 System.out.println(no + " " + lang + " " + msg); } // データベースから切断 stmt.close(); con.close(); } catch (Exception e) { e.printStackTrace(); } } } ■コンパイルと実行 コマンドプロンプト C:\JavaHello\MySQL>javac HelloWorldJDBCMySQLUpdate.java C:\JavaHello\MySQL>java HelloWorldJDBCMySQLUpdate 0行削除しました 1行追加しました 1行更新しました 1 スペイン語 Hola Mundo 2 英語 Hello World 3 ドイツ語 Hallo Welt C:\JavaHello\MySQL> 追加されて更新できました。 もう一度実行するとNOが3の行が存在するため1行削除してから1行追加するようになります。 コマンドプロンプト C:\JavaHello\MySQL>java HelloWorldJDBCMySQLUpdate 1行削除しました 1行追加しました 1行更新しました 1 スペイン語 Hola Mundo 2 英語 Hello World 3 ドイツ語 Hallo Welt C:\JavaHello\MySQL> 削除してから追加できました。 ◆MySQLの停止 最後にMySQLを停止させましょう。以下のコマンドで停止できます。 コマンドプロンプト C:\>mysqladmin -u root shutdown C:\> --------------- 以上MySQL設定方法 ---------------------------------- ◆MySQLのドライバをTomcatで使用可能にする mysql-connector-java-○.○-bin.jarファイルを[Tomcatのフォルダ]\shared\lib または、[WEBアプリケーションのフォルダ]\WEB-INF\libの下にコピーしてください。コピーしたらTomcatを再起動してください。 コピーしましたらTomcatを再起動してください。 ◆ブラウザで見てみよう! http://localhost:8080/examples/jsp/helloworldbodytag.jsp ------------------------------------------