インクルードによるコードの再利用で効率化をはかるTomcatを使う「JSPプログラミング」(5)

» 2001年07月31日 00時00分 公開
[三谷純タイムインターメディア]

前回はWebプログラミングの概要について説明しました。今回は、実際にJSPでプログラミングを行うときに必要となる、プログラムの再利用方法について説明します。プログラムの再利用を行うことで、コーディング量を減らすことができるだけでなく、メンテナンス性を高めることができます。


 JSPでのプログラムの再利用方法には、主に次のようなものがあります。

  • インクルードディレクティブを使用した静的インクルード
  • インクルードアクションを使用した動的インクルード
  • オリジナルクラスの作成とその使用
  • オリジナルBeanの作成とその使用

 クラスの作成やBeanの使用は一般的なJavaアプリケーションでも用いる手法ですが、インクルードアクションとインクルードディレクティブの使用はJSP固有の手法です。今回は、この2つのインクルードの方法について説明します。

■インクルードには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行のとても短いプログラムです。

●include.jsp(インクルードされるファイル)
<% out.print("World!"); %>
●5-1.jsp(インクルードディレクティブを用いた例)
<% out.print("Hello, "); %>
<%@ include file="include.jsp"%>
●5-2.jsp(インクルードアクションを用いた例)
<% out.print("Hello, "); %>
<jsp:include page="include.jsp" flush="true" />

 5-1.jsp5-2.jspでは、どちらもinclude.jspの内容をインクルードしているため、出力結果は同じで、次のように「Hello, World!」という文字列が表示されます。

5-1.jspの実行結果 5-1.jspの実行結果
5-2.jspの実行結果 5-2.jspの実行結果

■インクルードディレクティブとインクルードアクションの違い

 それでは、インクルードディレクティブとインクルードアクションでは、どこに違いがあるのでしょう。一度、5-1.jsp5-2.jspを実行した後で、include.jspを次のように変更してみます。

・include.jsp (インクルードされるファイル:変更後)
<% out.print("JSP!"); %>

 この後、再度5-1.jsp5-2.jspを両方実行してみると、次のようになります。

5-1.jspの実行結果 5-1.jspの実行結果
5-2.jspの実行結果 5-2.jspの実行結果

 5-2.jspの方は変更が反映されましたが、5-1.jspは変化しませんでした。これがインクルードディレクティブ(静的なインクルード)とインクルードアクション(動的なインクルード)の大きな違いです。

 インクルードディレクティブは、コンパイル前に読み込み処理を行い、インクルードアクションは実行時に読み込み処理を行います。この様子を図に示すと、次のようになります。

インクルードディレクティブの流れ(5-1.jspの場合) インクルードディレクティブの流れ(5-1.jspの場合)

インクルードアクションの流れ(5-2.jspの場合) インクルードアクションの流れ(5-2.jspの場合)

■Javaコードの比較

 それでは、JSPプログラムがサーバ側でJavaコードに翻訳されるときにはどのような処理がなされるのでしょう。本連載の第4回で“Hello, World!”の文字列を表示するJSPプログラムがJavaコードに翻訳された結果を見たように、今回も5-1.jsp5-2.jspがJavaコードに翻訳された結果を見てみましょう。Javaコードは非常に長いので、実際にHTMLを出力する部分だけに注目してみます。

・Javaコードに翻訳された5-1.jsp (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

・Javaコードに翻訳された5-2.jsp (HTML出力部分の抜粋)
// 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を次のように作成してみます。

・5-3.jsp
<% out.print("Hello, "); %>
<jsp:include page="include2.jsp" flush="true">
  <jsp:param name="name" value="@IT" />
</jsp:include>
・include2.jsp
<%= request.getParameter("name") %>.

 この実行結果は次のようになります。5-3.jspから渡されたパラメータがinclude2.jspで受け取られているのが分かります。

5-3.jspの実行結果 5-3.jspの実行結果

 5-3.jspが翻訳された結果は次のようになっています。String _jspx_qStrがパラメータの設定に使用されているのが分かります。

・Javaコードに翻訳された5-3.jsp (インクルード部分の抜粋)
// 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.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。