ヘッダーをスキップ

Oracle Application Server Containers for J2EE JavaServer Pages 開発者ガイド
10gリリース2(10.1.2)
B15632-02
目次
目次
索引
索引

戻る 次へ

6
プログラミングに関するその他の考慮事項

この章では、JSPアプリケーションの開発に使用する、様々なプログラミングの方針とヒントについて説明します。次の項目について説明します。

一般的なJSPプログラミングの方針

この項では、特定のターゲット環境に関係なく、JSPページのプログラミング時に考慮する必要がある事項について説明します。次の項目について説明します。

JavaBeansとスクリプトレットの比較

「ビジネス・ロジックとページ・プレゼンテーションの分離: JavaBeansのコール」では、JavaServer Pagesテクノロジの主なメリットについて説明しています。つまり、ビジネス・ロジックを含み、動的なコンテンツを決定するJavaコードは、リクエスト処理、プレゼンテーション・ロジックおよび静的なコンテンツを含むHTMLコードから分離できます。この分離によって、HTMLのエキスパートはプレゼンテーションに集中でき、Javaのエキスパートは、JSPページからコールされるJavaBeansのビジネス・ロジックに集中できます。

標準のJSPページに含まれるのは、通常、リクエスト処理やプレゼンテーション用のJava機能に関する簡単なJavaコードのみです。「JDBCを使用したJSPデータ・アクセスのサンプル」に示したサンプル・ページは説明に役立つ例ですが、理想的な設計ではありません。たとえば、このサンプルのrunQuery()メソッドでのデータ・アクセスは、JavaBeanで実行する方が適切です。ただし、出力をフォーマットするformatResult()メソッドは、JSPぺージの方が適切です。

静的なインクルードと動的なインクルードの比較

includeディレクティブ(「ディレクティブ」を参照)は、変換時にインクルード・ページのコピーを作成し、それをJSPページ(インクルード先ページ)にコピーします。この機能は、静的なインクルード(または変換時インクルード)と呼ばれ、次の構文を使用します。

<%@ include file="/jsp/userinfopage.jsp" %>

jsp:includeタグ(「標準アクション: JSPタグ」を参照)は、実行時に、インクルード・ページの出力を、インクルード先ページの出力に動的に挿入します。この機能は、動的なインクルード(または実行時インクルード)と呼ばれ、次の構文を使用します。

<jsp:include page="/jsp/userinfopage.jsp" flush="true" />

C構文の知識がある方にとって、静的なインクルードは#include文に相当します。動的なインクルードは、ファンクション・コールと同じです。いずれのインクルードも便利ですが、異なる目的で使用されます。


注意: 静的なインクルードと動的なインクルードは、同じサーブレット・コンテキスト内のページ間でのみ使用できます。 

静的なインクルードのロジック手法

静的なインクルードの場合は、インクルード先のJSPページで生成されるコードのサイズが大きくなります。これは、変換時にincludeディレクティブの時点で、インクルード・ページのテキストが、インクルード先ページに物理的にコピーされるためです。1つのページが複数回、インクルード先ページにインクルードされると、複数のコピーが作成されます。

静的にインクルードされたJSPページは、独立した変換可能なエンティティである必要はありません。このページは、インクルード先ページにコピーされるテキストのみで構成されます。インクルード・テキストがコピーされたインクルード先ページは、変換可能であることが必要です。インクルード先ページは、インクルード・ページがコピーされる前に変換可能である必要はありません。静的にインクルードされた一連のページは、それ自体では独立できないフラグメントとなる可能性があります。

動的なインクルードのロジック手法

動的なインクルードでは、リクエスト・ディスパッチャなどへのメソッド・コールが増加しますが、インクルード先ページで生成されたコードのサイズが大幅に増加することはありません。動的なインクルードによって、実行時の処理は、インクルード先ページからインクルード・ページに切り替えられます。これは、インクルード・ページのテキストをインクルード先ページに物理的にコピーする処理とは逆になります。

動的なインクルードの場合は、リクエスト・ディスパッチャへのコールを追加する必要があるため、処理のオーバーヘッドが増加します。

動的にインクルードされたページは、それ自体で変換および実行できる独立したエンティティであることが必要です。インクルード先ページも同様に、動的なインクルードなしに変換および実行できる独立したエンティティであることが必要です。

動的なインクルードと静的なインクルードのメリット、デメリットおよび代表的な使用例

静的なインクルードはページのサイズに影響を与え、動的なインクルードは処理のオーバーヘッドに影響を与えます。静的なインクルードの場合は、動的なインクルードに必要なリクエスト・ディスパッチャのオーバーヘッドを回避できますが、大規模なファイルの場合に問題が生じる可能性があります(生成されたページ実装クラスのサービス・メソッドのサイズは、64KBに制限されています。詳細は、「大量の静的なコンテンツまたは重要なタグ・ライブラリの使用に対する対処」を参照してください)。

また、静的なインクルードの過度の使用は、JSPページのデバッグを困難にする可能性があるため、プログラムの実行をトレースすることがさらに困難になります。静的にインクルードしたページ間でのわかりにくい相互依存は避けてください。

静的なインクルードは通常、そのコンテンツが複数のJSPページで繰り返し使用される、小規模なファイルをインクルードするために使用します。例:

動的なインクルードは、モジュール方式のプログラミングに役立ちます。1つのページを、独立して実行したり、別のページの出力の一部を生成するために使用できます。動的にインクルードされたページは、インクルード先ページのサイズを増やさずに、複数のインクルード先ページで再利用できます。


注意: OC4Jには、1つのファイルを複数のページに静的にインクルードする便利な方法として、グローバル・インクルードが用意されています。「Oracle JSPのグローバル・インクルード」を参照してください。 

JSPタグ・ライブラリの作成と使用を考慮する時期

開発チームがカスタム・タグの作成と使用を検討することが必要な場合があります。特に、次の場合には必要です。

Java構文の置換

JSP開発者にJavaプログラミングの経験がない場合、ページでJavaロジック(たとえば、JSP出力のプレゼンテーションとフォーマットを指示するロジック)をコーディングするのは困難な場合があります。

このような場合に、JSPタグ・ライブラリが役立ちます。出力を生成するこのようなロジックが多数のJSPページで必要な場合、Javaロジックを置換するタグ・ライブラリは、JSP開発者にとって非常に便利です。

このようなタグ・ライブラリの例として、OC4JでサポートされているJavaServer Pages標準タグ・ライブラリ(JSTL)があります。このライブラリの詳細は、『Oracle Application Server Containers for J2EE JSPタグ・ライブラリおよびユーティリティ・リファレンス』を参照してください。

API機能に対する便利なJSPプログラミング・アクセスの提供

タグ・ライブラリの提供によって、Webアプリケーションのプログラマは、サーブレットまたはJSPスクリプトレットから製品の機能や拡張機能を使用するために、Java APIに依存する必要がなくなります。タグ・ライブラリを使用すると、プログラマのタスクが大幅に軽減され、タグ・ハンドラによって適切なAPIコールが自動的に処理されます。

たとえば、OC4Jでは、電子メールとファイル・アクセス機能用に、タグとJavaBeansが提供されています。また、OC4JのWeb Object Cacheには、タグ・ライブラリとJava APIが提供されています。

JSP出力の操作またはリダイレクト

カスタム・タグを使用するもう1つの状況は、レスポンス出力に関する特殊な実行時処理が必要な場合です。必要な機能を使用するには、処理手順を追加したり、出力をブラウザ以外の場所にリダイレクトする必要が生じる場合があります。

たとえば、ブラウザではなくログ・ファイルにリダイレクトする出力テキストの周囲に配置するカスタム・タグを作成する場合、コードは次のようになります。この例のcustはタグ・ライブラリの接頭辞で、logはライブラリのタグの1つです。

<cust:log>
   Today is <%= new java.util.Date() %>
   Text to log.
   More text to log.
   Still more text to log.
</cust:log>

JSPプログラミングのその他のヒント

前述した一般的なプログラミングの方針以外に、次の項で説明するように、プログラミングに関して考慮する必要がある様々なヒントがあります。

直接起動からJSPページを除外する方法

一部のJSPページをアプリケーションからのみアクセス可能にし、ユーザーが直接起動できないようにする場合があります。特に、Model-View-Controller(MVC)などのアーキテクチャで必要になる場合があります。

たとえば、フロントエンドまたは表示ページがindex.jspであるとします。ユーザーは、このページに直接アクセスするURLリクエストを介してアプリケーションを起動します。ここで、index.jspには、2番目のページのincluded.jspが含まれ、3番目のページのforwarded.jspに転送されるとします。さらに、ユーザーがURLリクエストを介してこれらのページを直接起動できないようにする必要があるとします。

これを行うには、included.jspforwarded.jspをアプリケーションの/WEB-INFディレクトリに格納します。これらのページをこのディレクトリに格納すると、URLリクエストを介して直接起動できなくなります。直接起動しようとすると、ブラウザでエラー・レポートが生成されます。

index.jspページの文は次のようになります。

<jsp:include page="WEB-INF/included.jsp"/>
...
<jsp:forward page="WEB-INF/forwarded.jsp"/>

アプリケーション構造は次のようになります。構造には、サーブレット、JavaBeansまたは他のクラス用の標準のclassesディレクトリ、およびJARファイル用の標準のlibディレクトリが含まれます。

index.jsp
WEB-INF/
   web.xml
   included.jsp
   forwarded.jsp
   classes/
   lib/

集中チェッカ・ページの使用

JSPアプリケーションの全般的な管理や監視に、アプリケーションの各ページからインクルードする集中チェッカ・ページを使用すると便利です。集中チェッカ・ページは、各ページの実行中に次のタスクを実行できます。

この他にも多くの使用方法があります。

たとえば、HttpSessionBindingListenerインタフェースを実装したセッション・チェッカ・クラスのMySessionCheckerがあります(「標準セッションのリソース管理: HttpSessionBindingListener」を参照)。

public class MySessionChecker implements HttpSessionBindingListener
{
   ...

   valueBound(HttpSessionBindingEvent event)
   {...}

   valueUnbound(HttpSessionBindingEvent event)
   {...}

   ...
}

たとえば、次のような内容を含むチェッカ・ページ、centralcheck.jspを作成できます。

<jsp:useBean id="sessioncheck" class="MySessionChecker" scope="session" />

centralcheck.jspが含まれるページでは、セッション終了時にsessioncheckがスコープ外になると同時に、サーブレット・コンテナが、MySessionCheckerクラスに実装されているvalueUnbound()メソッドをコールします。これは、セッション・リソースを管理するために実行されます。centralcheck.jspは、アプリケーションの各JSPページの最後に含めることができます。


注意:
  • OC4Jには、1つのファイルを複数のページに静的にインクルードする便利な方法として、グローバル・インクルードが用意されています。「Oracle JSPのグローバル・インクルード」を参照してください。

  • この種の機能について、サーブレット・フィルタの使用を検討することもできます。サーブレット・フィルタの詳細は、『Oracle Application Server Containers for J2EEサーブレット開発者ガイド』を参照してください。

 

大量の静的なコンテンツまたは重要なタグ・ライブラリの使用に対する対処

JSPページに大量の静的なコンテンツ(実行時に変更されるコンテンツのない大量のHTMLコード)が含まれると、変換と実行の速度が低下する場合があります。

2つの対処方法があり、いずれの対処方法でも変換速度は向上します。

大量の静的なコンテンツを含むJSPページ、または大量のタグ・ライブラリを使用するJSPページで起こりうるもう1つの問題は、ほとんど(全部ではない場合)のJVMでは、単一のメソッド内のコード・サイズが64 KBに制限されていることです。javacによるコンパイルは可能ですが、JVMでは実行できません。実質的にJSPページのソース・ファイル全体から生成されたJavaコードは、ページ実装クラスのサービス・メソッドに追加されるため、この問題は、JSPトランスレータの実装によっては、JSPページに関する問題になる可能性があります。Javaコードは静的なHTMLをブラウザに出力するために生成され、スクリプトレットからのJavaコードは直接コピーされます。

同様に、JSPページのJavaスクリプトレットのサイズが大きいため、サービス・メソッドでサイズ制限の問題が発生する場合があります。ページ内のJavaコードが問題の原因の場合は、コードをJavaBeansに移動する必要があります。

大量のタグ・ライブラリの使用によってJSPページのサイズが制限される場合、ページを複数のページに分割し、必要に応じてjsp:includeタグを使用するという解決策が一般的です。

メソッド変数宣言とメンバー変数宣言の比較

「スクリプト要素」で、メンバー変数の宣言にはJSPの<%! ... %>宣言を使用し、メソッド変数は<% ... %>スクリプトレットで宣言する必要があることを説明しました。

変数の使用方法に応じて、適切な機能を使用して宣言するように注意してください。

次にdecltest.jspの例を示します。

<HTML>
<BODY>
<% double f2=0.0; %>
<%! double f1=0.0; %>
Variable declaration test.
</BODY>
</HTML>

この場合、ページ実装クラスのコードは次のようになります。

package ...;
import ...;

public class decltest extends ... {
   ...

   // ** Begin Declarations
   double f1=0.0;                  // *** f1 declaration is generated here ***
   // ** End Declarations

   public void _jspService
                (HttpServletRequest request, HttpServletResponse response)
                throws IOException, ServletException {
      ...

      try {
         out.println( "<HTML>");
         out.println( "<BODY>");
         double f2=0.0;      // *** f2 declaration is generated here ***
         out.println( "");
         out.println( "");
         out.println( "Variable declaration test.");
         out.println( "</BODY>");
         out.println( "</HTML>");
         out.flush();
      }
      catch( Exception e) {
         try {
            if (out != null) out.clear();
         }
         catch( Exception clearException) {
         }
      finally {
         if (out != null) out.close();
      }
   }
}


注意: これは、概念を説明するためのコードです。クラスの大部分は簡素化のために削除されているため、JSPトランスレータで生成されるページ実装クラスの実際のコードとは異なります。 

pageディレクティブの特性

この項では、次のpageディレクティブの特性について説明します。

静的なpageディレクティブ

pageディレクティブは静的で、変換時に解析されます。動的な設定を実行時に解析するようには指定できません。次に例を示します。

例1

次のpageディレクティブは有効です。

<%@ page contentType="text/html; charset=EUCJIS" %>
例2

次のpageディレクティブは無効で、エラーが発生します(この例ではEUCJISがハードコードされていますが、実行時に動的に決定されるすべてのキャラクタ・セットに当てはまります)。

<% String s="EUCJIS"; %>
<%@ page contentType="text/html; charset=<%=s%>" %>

一部のpageディレクティブ設定には、代替策があります。例2の場合は、コンテンツ・タイプを動的に設定できるsetContentType()メソッドを使用できます(「コンテンツ・タイプの動的な設定」を参照)。

pageディレクティブ属性の重複設定の禁止

JSP仕様では、複数のディレクティブ属性(pageディレクティブのimport属性を除く)が単一のJSP変換単位(JSPページおよびincludeディレクティブを使用してインクルードされたページ)内で2回以上設定されていないことを、JSPコンテナが確認する必要があることを指示しています。JSP 1.2の場合、これはpageディレクティブのみに適用されますが、将来のJSPバージョンでは、他の関連ディレクティブが追加される可能性があります。

ディレクティブ属性の重複設定が許可されているJSP 1.1標準に対する下位互換性のために、OC4Jではforgive_dup_dir_attr構成パラメータが提供されています。このパラメータの詳細は、「JSP構成パラメータの説明」を参照してください。たとえば、以前にコーディングしたページには、pageディレクティブのlanguage属性がすべてjavaに設定されているセグメントが複数含まれている可能性があります。

属性の重複設定については、次の点に注意してください。

累積されるpageディレクティブのimport設定

pageディレクティブのimport属性には、JSP 1.2のディレクティブ属性の重複に関する制限は当てはまりません。JSPページまたは変換単位(JSPページおよびincludeディレクティブを使用してインクルードされたページ)では、pageディレクティブのJava import設定が累積されます。

1つのJSPページまたは変換単位内では、次の2つの例は等価です。

<%@ page language="java" %>
<%@ page import="java.io.*, java.sql.*" %>

または

<%@ page language="java" %>
<%@ page import="java.io.*" %>
<%@ page import="java.sql.*" %>

最初のpageディレクティブのimport設定の後は、2番目のpageディレクティブのimport設定が、インポートするクラスまたはパッケージのセットに追加されます。インポートするクラスまたはパッケージは置換されません。

JSPでの空白の保持とバイナリ・データの使用

JSPコンテナは通常、ソース・コードの空白(改行を含む)をブラウザへの出力内に保持します。開発者が意図しない空白が挿入される場合があるため、一般的に、JSPテクノロジは、バイナリ・データの生成には適していません。

空白の例

次の2つのJSPページでは、ソース・コード内での改行の使用に応じて、異なるHTML出力が作成されます。

例1: 改行なし

次のJSPページでは、Date()コールとgetParameter()コールの後に改行がありません。(Date()コールで始まる3行目と4行目は、実際には1行のコードが折り返されています。)

nowhitsp.jsp:

<HTML>
<BODY>
<%= new java.util.Date() %> <% String user=request.getParameter("user"); %> <%= 
(user==null) ? "" : user %>
<B>Enter name:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="user" SIZE=15>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>

このコードによるブラウザへのHTML出力は、次のとおりです。日付の後に空白行はありません。

<HTML>
<BODY>
Tue May 30 20:07:04 PDT 2000
<B>Enter name:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="user" SIZE=15>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>
例2: 改行あり

次のJSPページでは、Date()コールとgetParameter()コールの後に改行があります。

nowhitsp.jsp:

<HTML>
<BODY>
<%= new java.util.Date() %>
<% String user=request.getParameter("user"); %>
<%= (user==null) ? "" : user %>
<B>Enter name:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="user" SIZE=15>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>

このコードによるブラウザへのHTML出力は、次のとおりです。

<HTML>
<BODY>
Tue May 30 20:19:20 PDT 2000


<B>Enter name:</B>
<FORM METHOD=get>
<INPUT TYPE="text" NAME="user" SIZE=15>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>

日付と「Enter name:」行との間に、2行の空白行があることに注意してください。この2つの例では、図6-1に示すように、ブラウザに同じ表示を作成するため、その違いは大きくありません。ただし、この例は、空白の保持に関する一般的な問題点を示しています。

図6-1    空白の例のブラウザ出力のサンプル


画像の説明

JSPページでバイナリ・データを回避する理由

次の理由から、JSPページはバイナリ・データの生成には適していません。通常は、かわりにサーブレットを使用します。

JSPテクノロジは、動的なテキスト・コンテンツのプログラミングの簡素化を目的としているため、JSPページでバイナリ・データの生成を試行すると、JSPテクノロジの特性を失うことになります。

JSPのベスト・プラクティスのサマリー

この項では、ベスト・プラクティスおよび考慮事項を要約し、この章またはこのマニュアルの詳細が説明されている箇所への相互参照を示します。

ベスト・プラクティス: JSPコーディング

JSPコードの推奨事項は次のとおりです。

ベスト・プラクティス: 変換とコンパイル

JSPページの変換時とコンパイル時における推奨事項は次のとおりです。

ベスト・プラクティス: JSP構成

JSP構成の推奨事項は次のとおりです。これらのパラメータの詳細は、「JSP構成パラメータ」を参照してください。


戻る 次へ
Oracle
Copyright © 2000, 2005 Oracle.

All Rights Reserved.
目次
目次
索引
索引