Oracle Application Server Containers for J2EE JavaServer Pages 開発者ガイド 10gリリース2(10.1.2) B15632-02 |
|
この章では、JSPアプリケーションの開発に使用する、様々なプログラミングの方針とヒントについて説明します。次の項目について説明します。
この項では、特定のターゲット環境に関係なく、JSPページのプログラミング時に考慮する必要がある事項について説明します。次の項目について説明します。
「ビジネス・ロジックとページ・プレゼンテーションの分離: 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プログラミングの経験がない場合、ページでJavaロジック(たとえば、JSP出力のプレゼンテーションとフォーマットを指示するロジック)をコーディングするのは困難な場合があります。
このような場合に、JSPタグ・ライブラリが役立ちます。出力を生成するこのようなロジックが多数のJSPページで必要な場合、Javaロジックを置換するタグ・ライブラリは、JSP開発者にとって非常に便利です。
このようなタグ・ライブラリの例として、OC4JでサポートされているJavaServer Pages標準タグ・ライブラリ(JSTL)があります。このライブラリの詳細は、『Oracle Application Server Containers for J2EE JSPタグ・ライブラリおよびユーティリティ・リファレンス』を参照してください。
タグ・ライブラリの提供によって、Webアプリケーションのプログラマは、サーブレットまたはJSPスクリプトレットから製品の機能や拡張機能を使用するために、Java APIに依存する必要がなくなります。タグ・ライブラリを使用すると、プログラマのタスクが大幅に軽減され、タグ・ハンドラによって適切なAPIコールが自動的に処理されます。
たとえば、OC4Jでは、電子メールとファイル・アクセス機能用に、タグとJavaBeansが提供されています。また、OC4JのWeb Object Cacheには、タグ・ライブラリとJava APIが提供されています。
カスタム・タグを使用するもう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ページをアプリケーションからのみアクセス可能にし、ユーザーが直接起動できないようにする場合があります。特に、Model-View-Controller(MVC)などのアーキテクチャで必要になる場合があります。
たとえば、フロントエンドまたは表示ページがindex.jsp
であるとします。ユーザーは、このページに直接アクセスするURLリクエストを介してアプリケーションを起動します。ここで、index.jsp
には、2番目のページのincluded.jsp
が含まれ、3番目のページのforwarded.jsp
に転送されるとします。さらに、ユーザーがURLリクエストを介してこれらのページを直接起動できないようにする必要があるとします。
これを行うには、included.jsp
とforwarded.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ページの最後に含めることができます。
注意:
|
JSPページに大量の静的なコンテンツ(実行時に変更されるコンテンツのない大量のHTMLコード)が含まれると、変換と実行の速度が低下する場合があります。
2つの対処方法があり、いずれの対処方法でも変換速度は向上します。
jsp:include
タグを使用して、実行時にその出力をJSPページ出力にインクルードします。jsp:include
タグの詳細は、「標準アクション: JSPタグ」を参照してください。external_resource
構成パラメータを有効にすると、JSPトランスレータがこの操作を実行します。このパラメータの詳細は、「JSP構成パラメータの説明」を参照してください。
事前に変換する場合は、ojspc
ツールの-extres
オプションが同じ機能を提供します。
大量の静的なコンテンツを含むJSPページ、または大量のタグ・ライブラリを使用するJSPページで起こりうるもう1つの問題は、ほとんど(全部ではない場合)のJVMでは、単一のメソッド内のコード・サイズが64 KBに制限されていることです。javac
によるコンパイルは可能ですが、JVMでは実行できません。実質的にJSPページのソース・ファイル全体から生成されたJavaコードは、ページ実装クラスのサービス・メソッドに追加されるため、この問題は、JSPトランスレータの実装によっては、JSPページに関する問題になる可能性があります。Javaコードは静的なHTMLをブラウザに出力するために生成され、スクリプトレットからのJavaコードは直接コピーされます。
同様に、JSPページのJavaスクリプトレットのサイズが大きいため、サービス・メソッドでサイズ制限の問題が発生する場合があります。ページ内のJavaコードが問題の原因の場合は、コードをJavaBeansに移動する必要があります。
大量のタグ・ライブラリの使用によってJSPページのサイズが制限される場合、ページを複数のページに分割し、必要に応じてjsp:include
タグを使用するという解決策が一般的です。
「スクリプト要素」で、メンバー変数の宣言にはJSPの<%! ... %>
宣言を使用し、メソッド変数は<% ... %>
スクリプトレットで宣言する必要があることを説明しました。
変数の使用方法に応じて、適切な機能を使用して宣言するように注意してください。
<%! ... %>
JSP宣言構文内で宣言される変数は、JSPトランスレータが生成したページ実装クラス内のクラス・レベルで宣言されます。この場合、オブジェクト・インスタンスを宣言すると、そのオブジェクトは複数のリクエストから同時にアクセスできます。したがって、page
ディレクティブ内でisThreadSafe="false"
が宣言されていないかぎり、オブジェクトはスレッド・セーフであることが必要です。
<% ... %>
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(); } } }
この項では、次のpage
ディレクティブの特性について説明します。
page
ディレクティブは静的で、変換時に効果があります。パラメータ設定が実行時に評価されるようには指定できません。
page
ディレクティブに特に関係していますが、page
ディレクティブのimport
属性にはこの制限は当てはまりません。
page
ディレクティブのJava import
設定は、JSPページまたは変換単位内に累積されます。
page
ディレクティブは静的で、変換時に解析されます。動的な設定を実行時に解析するようには指定できません。次に例を示します。
次のpage
ディレクティブは有効です。
<%@ page contentType="text/html; charset=EUCJIS" %>
次のpage
ディレクティブは無効で、エラーが発生します(この例ではEUCJIS
がハードコードされていますが、実行時に動的に決定されるすべてのキャラクタ・セットに当てはまります)。
<% String s="EUCJIS"; %> <%@ page contentType="text/html; charset=<%=s%>" %>
一部のpage
ディレクティブ設定には、代替策があります。例2の場合は、コンテンツ・タイプを動的に設定できるsetContentType()
メソッドを使用できます(「コンテンツ・タイプの動的な設定」を参照)。
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
ディレクティブが許可されます。次の場合は許可されます。
<%@ page buffer="none" %> <%@ page session="true" %>
または
------------------------------ <%@ page buffer="10kb" %> <%@ include file="b.jsp" %> ------------------------------ ------------------------------ b.jsp <%@ page session="false" %> ------------------------------
次の場合は許可されません。
<%@ page buffer="none" %> <%@ page buffer="10kb" %>
または
<%@ page buffer="none" buffer="10kb" %>
または
------------------------------ <%@ page buffer="10kb" %> <%@ include file="b.jsp" %> ------------------------------ ------------------------------ b.jsp <%@ page buffer="3kb" %> ------------------------------
include
ディレクティブを使用してインクルードされたページで構成されていますが、jsp:include
タグを使用してインクルードされたページは含まれていません。jsp:include
タグを使用してインクルードされたページは、変換時に静的にインクルードされるのではなく、実行時に動的にインクルードされます。詳細は、「静的なインクルードと動的なインクルードの比較」を参照してください。したがって、次の場合は許可されます。
------------------------------ <%@ page buffer="10kb" %> <jsp:include page="b.jsp" /> ------------------------------ ------------------------------ b.jsp <%@ page buffer="3kb" %> ------------------------------
page
ディレクティブのimport
属性には、属性の重複設定に対する制限は当てはまりません。次項の「累積される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テクノロジは、バイナリ・データの生成には適していません。
次の2つのJSPページでは、ソース・コード内での改行の使用に応じて、異なるHTML出力が作成されます。
次の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>
次の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に示すように、ブラウザに同じ表示を作成するため、その違いは大きくありません。ただし、この例は、空白の保持に関する一般的な問題点を示しています。
次の理由から、JSPページはバイナリ・データの生成には適していません。通常は、かわりにサーブレットを使用します。
JspWriter
クラスには実際のバイトを書き込むためのメソッドがありません。
.gif
ファイルなど)の生成など、空白が重要な場合には適していません。次に一般的な例を示します。
... <% response.getOutputStream().write(...binary data...) %> <% response.getOutputStream().write(...more binary data...) %>
この場合、ブラウザは、出力バッファのバッファリングに応じて、バイナリ・データの途中または最後にある不要な改行文字を受け取ります。コードの行間で改行を使用しないことによってこの問題は回避できますが、この方法は望ましいプログラミング・スタイルではありません。
JSPテクノロジは、動的なテキスト・コンテンツのプログラミングの簡素化を目的としているため、JSPページでバイナリ・データの生成を試行すると、JSPテクノロジの特性を失うことになります。
この項では、ベスト・プラクティスおよび考慮事項を要約し、この章またはこのマニュアルの詳細が説明されている箇所への相互参照を示します。
JSPコードの推奨事項は次のとおりです。
JSPページの変換時とコンパイル時における推奨事項は次のとおりです。
JSP構成の推奨事項は次のとおりです。これらのパラメータの詳細は、「JSP構成パラメータ」を参照してください。
|
![]() Copyright © 2000, 2005 Oracle. All Rights Reserved. |
|