前回はWebプログラミングの概要について説明しました。今回は、実際にJSPでプログラミングを行うときに必要となる、プログラムの再利用方法について説明します。プログラムの再利用を行うことで、コーディング量を減らすことができるだけでなく、メンテナンス性を高めることができます。
JSPでのプログラムの再利用方法には、主に次のようなものがあります。
クラスの作成やBeanの使用は一般的なJavaアプリケーションでも用いる手法ですが、インクルードアクションとインクルードディレクティブの使用はJSP固有の手法です。今回は、この2つのインクルードの方法について説明します。
JSPプログラムやHTML文が記されたファイルを別のファイルに読み込む(インクルードする)ことで、一度作成したプログラムを再利用することができます。JSPでは、ファイルのインクルードを行う方法に、静的なインクルードを行う「インクルードディレクティブ」、動的なインクルードを行う「インクルードアクション」の2通りの方法があります。
例えば、include.jspという既存のファイルをインクルードする場合、それぞれ次のように記述します。
<%@ include file="include.jsp"%>
<jsp:include page="include.jsp" flush="true" />
インクルードアクションのflush属性はインクルードされるページを読み込む前に、ページの出力バッファをフラッシュするかどうかを制御します。現バージョンのJSPでは、必ずtrueに設定することになっているので、インクルードアクションを使用する場合は、flush=”"true"を必ず記述するようにします。
特定のJSPにファイルをインクルードする、という意味ではどちらも共通していますが、実際にはファイルがインクルードされる方法が異なります。この違いを理解するために、まずは、次の3つのファイルを見てみましょう。どれも1、2行のとても短いプログラムです。
<% out.print("World!"); %>
<% out.print("Hello, "); %> <%@ include file="include.jsp"%>
<% out.print("Hello, "); %> <jsp:include page="include.jsp" flush="true" />
5-1.jspと5-2.jspでは、どちらもinclude.jspの内容をインクルードしているため、出力結果は同じで、次のように「Hello, World!」という文字列が表示されます。
それでは、インクルードディレクティブとインクルードアクションでは、どこに違いがあるのでしょう。一度、5-1.jspと5-2.jspを実行した後で、include.jspを次のように変更してみます。
<% out.print("JSP!"); %>
この後、再度5-1.jspと5-2.jspを両方実行してみると、次のようになります。
5-2.jspの方は変更が反映されましたが、5-1.jspは変化しませんでした。これがインクルードディレクティブ(静的なインクルード)とインクルードアクション(動的なインクルード)の大きな違いです。
インクルードディレクティブは、コンパイル前に読み込み処理を行い、インクルードアクションは実行時に読み込み処理を行います。この様子を図に示すと、次のようになります。
それでは、JSPプログラムがサーバ側でJavaコードに翻訳されるときにはどのような処理がなされるのでしょう。本連載の第4回で“Hello, World!”の文字列を表示するJSPプログラムがJavaコードに翻訳された結果を見たように、今回も5-1.jsp、5-2.jspがJavaコードに翻訳された結果を見てみましょう。Javaコードは非常に長いので、実際にHTMLを出力する部分だけに注目してみます。
// begin [file="/home/mitani/jsp/5-1.jsp";from=(0,2);to=(0,25)] out.print("Hello, "); // end // HTML // begin [file="/home/mitani/jsp/5-1.jsp";from=(0,27);to=(1,0)] out.write("\r\n"); // end // begin [file="/home/mitani/jsp/include.jsp";from=(0,2);to=(0,24)] out.print("World!"); // end // HTML // begin [file="/home/mitani/jsp/5-1.jsp";from=(1,32);to=(2,0)] out.write("\r\n"); // end
翻訳後のJavaファイルの出力部分に“World!”という文字が直接入っているので、このJavaファイルのコンパイル後にinclude.jspを変更しても5-1.jspの出力が変わらないことが分かります。
このinclude.jspの変更を反映するには、5-1.jsp自身を変更するか、次のようにtouchコマンドを使用して、5-1.jspの更新時刻を変更する必要があります。
> touch 5-1.jsp
// begin [file="/home/mitani/jsp/5-2.jsp";from=(0,2);to=(0,25)] out.print("Hello, "); // end // HTML // begin [file="/home/mitani/jsp/5-2.jsp";from=(0,27);to=(1,0)] out.write("\r\n"); // end // begin [file="/home/mitani/jsp/5-2.jsp";from=(1,0);to=(1,47)] { String _jspx_qStr = ""; pageContext.include("include.jsp" + _jspx_qStr); } // end // HTML // begin [file="/home/mitani/jsp/5-2.jsp";from=(1,47);to=(2,0)] out.write("\r\n"); // end
こちらは、直接“World!”という文字列を出力するのではなく、pageContextオブジェクトのincludeメソッドを使用しています(pageContextは、outやrequest同様、暗黙オブジェクトの1つです)。include.jspが変更されれば、5-2.jspを更新しなくとも、表示内容が変わることが分かります。ところで、ここでは何も意味を成していないように見えるString型の変数、_jspx_qStrとは何でしょう?もう少しインクルードアクションの例を見てみましょう。
さて、インクルードアクションでは、次のような記述で、インクルードするページにパラメータを渡すことができます。
<jsp:include page="インクルードファイル名" flush="true"> <jsp:param name="パラメータ名" value="パラメータ値" /> </jsp:include>
今度は、引数名が“name”、引数の値が“@IT”であるパラメータを渡すプログラム5-3.jspと、渡されたパラメータを受け取るinclude2.jspを次のように作成してみます。
<% out.print("Hello, "); %> <jsp:include page="include2.jsp" flush="true"> <jsp:param name="name" value="@IT" /> </jsp:include>
<%= request.getParameter("name") %>.
この実行結果は次のようになります。5-3.jspから渡されたパラメータがinclude2.jspで受け取られているのが分かります。
5-3.jspが翻訳された結果は次のようになっています。String _jspx_qStrがパラメータの設定に使用されているのが分かります。
// begin [file="/home/mitani/jsp/5-3.jsp";from=(1,0);to=(3,14)] { String _jspx_qStr = ""; _jspx_qStr = _jspx_qStr + "?name=" + "@IT"; pageContext.include("include2.jsp" + _jspx_qStr); } // end
このように、パラメータを渡して特定のページをインクルードすることで、例えばメッセージを特定のテーブルで表示するプログラムを再利用したり、特定のフォーマットでCopyrightを表示するプログラムを再利用するなど、有効な活用が可能です。
インクルードするファイル名は、JSPファイルからの相対パスで指定することも、絶対パスで指定することもできます。ただし、インクルードするファイルは、Context pathで指定した同一のWebアプリケーションに属する必要があります。また、絶対パスで指定するときのルートパスは、Context path指定したdocBaseになることに注意しましょう。
例えば、Context pathを次のように設定し、
<Context path="/jsp" docBase="/home/username/jsp" crossContext="false" debug="0" reloadable="true" > </Context>
実際のディレクトリ構成が次のようになっていたとします。
この場合、test.jspからinclude.jspをインクルードするには、次のように記述します。
<jsp:include page="../include.jsp" flush="true" />
<jsp:include page="/include.jsp" flush="true" />
次の記述はどちらも誤りですので注意しましょう。
<jsp:include page="/home/username/jsp/include.jsp" flush="true" />
<jsp:include page="http://localhost/jsp/include.jsp" flush="true" />
なお、インクルードで指定するファイルは、JSPファイルであっても、単なるHTMLファイルであっても構いません。
今回は、特定のファイルをインクルードしてプログラムを再利用する方法を説明しました。次回は、オリジナルクラスとBeanを作成して、プログラムを再利用する方法を解説します。
Copyright © ITmedia, Inc. All Rights Reserved.