ヘッダーをスキップ

Oracle Containers for J2EE JavaServer Pages開発者ガイド
10g(10.1.3.1.0)

B31860-01
目次
目次
索引
索引

戻る 次へ

6 JSPでの作業

この章では、JSPページのプログラミングに関する基本的な考慮事項について、例を示して説明します。JSPとサーブレット間の相互作用およびデータベース・アクセスについても説明します。

次の項目について説明します。

開始前の考慮点

次の各項では、OC4J環境でJSPページのコーディングまたは使用を開始する前に考慮しておく必要がある事項について説明します。

アプリケーション・ルート機能について

サーブレット仕様(サーブレット2.2以降)に従って、各Webアプリケーションには独自のサーブレット・コンテキストがあります。各サーブレット・コンテキストは、サーバーのファイル・システム内でディレクトリ・パスに関連付けられています。このディレクトリ・パスは、Webアプリケーションのモジュール用のベース・パスです。このベース・パスがアプリケーション・ルートです。

各Webアプリケーションには、独自のアプリケーション・ルートがあります。標準のサーブレット環境のWebアプリケーションの場合、サーブレット、JSPページ、およびHTMLファイルなどの静的なファイルは、すべてこのアプリケーション・ルートに基づいています。(これに対して、サーブレット2.0環境では、サーブレットとJSPページのアプリケーション・ルートと、静的なファイルのドキュメント・ルートは異なります。)

サーブレットURLには、次の汎用的なフォームがあります。

http://host:port/contextpath/servletpath

サーブレット・コンテキストが作成されると、アプリケーション・ルートと、URLのコンテキスト・パス部分との間にマッピングが指定されます。サーブレット・パスは、アプリケーションのweb.xmlファイルに定義されます。web.xml内の<servlet>要素によって、サーブレット・クラスがサーブレット名に関連付けられます。web.xml内の<servlet-mapping>要素によって、URLパターンが指定のサーブレットに関連付けられます。サーブレットが実行されると、サーブレット・コンテナは、指定されたURLパターンを既知のサーブレット・パスと比較し、一致したサーブレット・パスを選択します。詳細は、『Oracle Containers for J2EEサーブレット開発者ガイド』を参照してください。

たとえば、アプリケーション・ルートが/home/dir/mybankapp/mybankwebappのアプリケーションが、コンテキスト・パス/mybankにマッピングされると仮定します。さらに、このアプリケーションには、サーブレット・パスがloginservletのサーブレットが含まれると仮定します。このサーブレットは、次のように起動できます。

http://host:port/mybank/loginservlet

アプリケーション・ルートのディレクトリ名はユーザーには表示されません。

このアプリケーションのHTMLページについてこの例を使用すると、次のURLによって、/home/dir/mybankapp/mybankwebapp/dir/abc.htmlファイルがポイントされます。

http://host:port/mybank/dir/abc.html

各サーブレット環境には、デフォルトのサーブレット・コンテキストもあります。このコンテキストのコンテキスト・パスは、デフォルトのサーブレット・コンテキストのアプリケーション・ルートにマッピングされている「/」のみです。たとえば、デフォルトのコンテキストのアプリケーション・ルートが/home/dir/defaultapp/defaultwebappで、サーブレット・パスがmyservletのサーブレットでデフォルトのコンテキストを使用すると仮定します。その場合のURLは、次のとおりです。

http://host:port/myservlet

デフォルトのコンテキストは、URLに指定されているコンテキスト・パスと一致しない場合にも使用されます。

HTMLファイルについてこの例を使用すると、次のURLによって/home/dir/defaultapp/defaultwebapp/dir2/def.htmlファイルがポイントされます。

http://host:port/dir2/def.html

OC4Jのクラスパス機能について

OC4JのWebコンテナは、Webサーバー上の標準の場所を使用して、変換済JSPページおよび必須クラス(JavaBeansなど)用の.classファイルと.jarファイルを検索します。コンテナは、Webサーバーのクラスパス構成を使用せずに標準の場所でファイルを検索します。

従属クラスの場所は次のとおりです。これらの場所はアプリケーション・ルートと相対的な関係があります。

/WEB-INF/classes/...
/WEB-INF/lib 

JSPページ実装クラス(変換済ページ)の場所は、次のとおりです。

.../_pages/...

/WEB-INF/classesディレクトリは、Javaの各.classファイル用です。これらのクラスは、Javaパッケージのネーミング規則に従って、classesディレクトリ下のサブディレクトリに格納する必要があります。たとえば、oracle.jsp.sample.lotteryパッケージに含まれるように定義した、LottoBeanと呼ばれるJavaBeanがあると仮定します。Webコンテナは、アプリケーション・ルートに対して相対的な次の場所で、LottoBean.classを検索します。

/WEB-INF/classes/oracle/jsp/sample/lottery/LottoBean.class

libディレクトリは、JAR(.jar)ファイル用です。Javaパッケージ構造はJARファイル構造に指定されているため、すべてのJARファイルは、サブディレクトリ内ではなく、libディレクトリ内に直接格納されます。たとえば、LottoBean.classは、アプリケーション・ルートに対して相対的な次の場所にあるlottery.jarに格納されます。

/WEB-INF/lib/lottery.jar

_pagesディレクトリは、OC4JのJ2EEホーム・ディレクトリの下にあり、jsp-cache-directory構成パラメータの値によって決まります。詳細は、「生成されるファイルとその格納場所」を参照してください。


重要

_pagesディレクトリのデフォルトの場所など、実装に関する詳細は、今後のリリースで変更される場合があります。 


OC4Jでデフォルトでインポートされるパッケージ

OC4JのWebコンテナは、JSP仕様に基づいて次のパッケージをJSPページにデフォルトでインポートします。JSPでこれらのパッケージを使用する場合、pageディレクティブのimport設定は不要です。

javax.servlet.*
javax.servlet.http.*
javax.servlet.jsp.*

以前のリリースでは、次のパッケージもデフォルトでインポートされました。

java.io.*
java.util.*
java.lang.reflect.*
java.beans.*

使用する未修飾のクラス名と、インポートしたパッケージ内の同じ名前のクラスとの間で発生する競合を最小化するために、インポートするデフォルトのパッケージ・リストが縮小されました。

ただし、このために、以前のバージョンのOC4Jで使用していたアプリケーションで移行上の問題が発生する可能性があります。このようなアプリケーションは、正常にコンパイルされない場合があります。デフォルト・リストのパッケージより多くのパッケージをインポートする必要がある場合は、次の2つの方法があります。

JDK 1.4に関する問題: パッケージに含まれないクラスを起動できない

OC4Jには、Sun社のJDK1.4およびJDK 1.5が同梱されています。したがって、以前のバージョンのJDKから移行する場合、次の点を考慮する必要があります。

Sun社が述べているように、コンパイラでは、不特定の名前空間から型をインポートするインポート文は拒否されます。これは、JDKの以前のバージョンに関するセキュリティ上の問題とあいまい性に対処するための措置でした。基本的に、これはパッケージに含まれていないクラス(クラスのメソッド)を起動できないことを示します。パッケージに含まれていないクラスを起動しようとすると、コンパイル時に致命的エラーが発生します。

これは特に、JSPページからJavaBeansを起動するJSP開発者に影響します。このようなBeanは、パッケージの外部にあることが多いためです(JSP仕様2.0では、新しいコンパイラの要件を満たすために、Beanはパッケージ内に存在することが必要です)。


注意

  • javac -sourceコンパイラ・オプションは、JDK1.4コンパイラによってJDK1.3コードが透過的に処理されることを目的としていますが、このオプションは、パッケージに含まれないクラスの問題には対処していません。

  • OC4Jでは、JDK1.4とJDK1.5コンパイラのみがサポートおよび認証されています。server.xmlファイルに<java-compiler>要素を追加することで、別のコンパイラを指定できます。これがパッケージに含まれないクラスの問題の対処方法になることもありますが、OC4Jとともに使用する場合、Oracleでは他のコンパイラは認証またはサポートされていません。(また、Oracle Application Server環境でserver.xmlファイルを直接更新しないでください。Oracle Enterprise Manager 10gを使用してください。)

 

JDK1.4の互換性の問題の詳細は、次のWebサイトを参照してください。

http://java.sun.com/j2se/1.4/compatibility.html

特に、「Incompatibilities Between Java 2 Platform, Standard Edition, v1.4.0 and v1.3」のリンクをクリックしてください。

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

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

従来型JSPとスクリプトレスJSPの作成の比較

JSP開発の主眼は、スクリプトレスなJSP、つまりスクリプトレットや実行時の式などの埋込みJavaスクリプト要素を含まないページの作成となっています。スクリプトレスなJSPは、従来のスクリプト・ベースのJSP開発と比べ、いくつかの利点があります。

JSPコードのサンプルは、スクリプトレスなJSPの例です。

JSP 1.1以来、ページの作成者は、JavaBeansおよびタグ・ハンドラ・インスタンスによって提供されるJava機能にアクセスするために、標準アクション・タグおよびカスタム・タグを活用することにより、ほとんどJavaを使用しないページを作成することが可能でした。ただし、完全にスクリプトレスなページを作成するには多くの課題がありました。たとえば、データ・アクセスの制限や、カスタム・タグ・ハンドラ・クラスを作成する際の複雑さなどです。

JSP 2.0リリースでは、いくつかの主要な改善点により、スクリプトレスなページの作成が大幅に容易になっています。たとえば、式言語(EL)機能をJSP仕様に完全に統合したことにより、ELからすべてのJSPページのコンテキスト・オブジェクト、変数およびリクエスト・パラメータ、さらにJavaBeansのプロパティとコレクション要素にアクセスできるようになりました。ELを使用すると、Javaスクリプトレットや式を使用せずに、アプリケーション・データにアクセスし、データを操作できます。式言語の詳細は、「式言語の使用によるJSP作成の単純化」を参照してください。

また、カスタム・タグを作成し、JSPページで使用する方法も容易になりました。JavaServer Pages標準タグ・ライブラリ(JSTL)では、JSP作成者が最も必要とする機能の大部分がカプセル化されているタグ・ライブラリを多数提供しています。新しいSimpleTagインタフェースにより、カスタム・タグ・ハンドラの作成が著しく単純化されました。実際、JSP作成者は、完全にJSP構文で作成されているタグ・ファイルを使用して、まったくJavaを使用しないタグ・ライブラリを作成できるようになりました。

JSP 2.0はJSP 1.xとの下位互換性を維持しています。つまり、JSP 2.0構文で作成されたページでも、Javaスクリプト要素を使用できます。

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

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

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

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

JSPページ内にJSPページをインクルードする方法は、2つあります。

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つのページを、独立して実行したり、別のページの出力の一部を生成するために使用できます。動的にインクルードされたページは、インクルード先ページのサイズを増やさずに、複数のインクルード先ページで再利用できます。

JSPタグ・ライブラリでのサービスおよびリソース参照の注釈の使用

リリース10.1.3.1より、OC4Jでは、J2EE 5.0およびJSP 2.1の仕様で定義されているJSPタグ・ライブラリでの注釈のサポートを開始しました。

J2SE 5.0以上では、構成データおよび依存性を、Javaコードの外部リソースにメタデータとして指定できます。これを、注釈とも言います。このようなデータを、構成ファイル、またはサービス(EJBやWebサービスなど)およびリソース参照(データソースやJMS宛先など)の注釈で定義できます。

次の制約に注意してください。

前述の例を除き、JavaServer Pagesでサポートされている注釈は、サーブレットでサポートされているものと同じです。これは『Oracle Containers for J2EEサーブレット開発者ガイド』の第7章「サービスおよびリソース参照の注釈の使用」に記載されています。

JSPアプリケーションの監視

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

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

たとえば、HttpSessionBindingListenerインタフェースを実装したセッション・チェッカ・クラスのMySessionCheckerがあります。

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ページ、または大量のタグ・ライブラリを使用する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 f=0.0; %>
Variable declaration test.
</BODY>
</HTML>

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

package ...;
import ...;

public class decltest extends ... {
   ...

   // ** Begin Declarations
   double f=0.0;                  // *** f 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ディレクティブを使用してインクルードされたページ)内で異なる値で再設定されていないことを、Webコンテナが確認する必要があることが記載されています。

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


注意

forgive_dup_dir_attrパラメータは、Oracle Containers for J2EE 10g(10.1.3.1.0)では推奨されていません。 


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

生成したメソッドの64Kのサイズ制限に対する対処方法

Java仮想マシン(JVM)では、Javaメソッド当たりのコード量を64K(65536バイト)に制限しています。アプリケーションで大きなJSPを使用すると、実行時にこの制限を超える可能性があります。一般的に、JSPのファイル・サイズは最小限にとどめる必要があります。

JSPで大量のタグ・ライブラリを使用する場合、「アプリケーション」→「JSPコンテナのプロパティ」→「カスタム・タグのコード・サイズの削減」プロパティ(またはglobal-web-application.xmlreduce_tag_code構成パラメータ)を有効にして、カスタム・タグから生成されるコードのサイズを削減します。ただし、これにより、JSPコンパイルのパフォーマンスが影響を受ける可能性があります。

JSPファイルのネーミング規則の順守

サーブレット仕様では、JSPページのファイル名に拡張子.jspが必要です。ただし、サーブレット仕様2.3では、個別に変換可能な完全なページと、個別に変換できないページ・セグメント(includeディレクティブを介して移入したファイルなど)の違いは識別されません。

JSP仕様2.0では、次のことをお薦めします。

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

Webコンテナは通常、ソース・コードの空白(改行を含む)をブラウザへの出力内に保持します。開発者が意図しない空白が挿入される場合があるため、一般的に、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=5>
<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=5>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>
例2: 改行あり

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

whitesp.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=5>
<INPUT TYPE="submit" VALUE="Submit name">
</FORM>
</BODY>
</HTML>

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

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


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

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

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

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

JSPのベスト・プラクティス

次の各項では、OC4JにデプロイするJSPページを開発する際、考慮すべきベスト・プラクティスについて説明します。

HTTPセッションに関する注意

HTTPセッションは、メモリーの使用量により、Webアプリケーションにパフォーマンス面でのオーバーヘッドを追加します。セッションは、JSPではデフォルトで有効になっています。

不要な場合のHTTPセッションの不使用

HTTPセッション・オブジェクトが不要な場合は、使用しないでください。JSPページでHTTPセッションが不要な場合(基本的に、セッション属性の格納または取得が不要な場合)は、セッションを使用しないように指定できます。pageディレクティブで、次のように指定します。

<%@ page session="false" %>

これによって、セッションの作成または取得のオーバーヘッドが減少するため、ページのパフォーマンスが改善されます。

デフォルトでは、サーブレットはセッションを使用しませんが、JSPページはセッションを使用します。

使用していないセッションの無効化

JSPでHTTPセッションを使用しない場合、必ずjavax.servlet.http.HttpSession.invalidate()メソッドを使用して明示的に各セッションを取り消し、占有されているメモリーを解放します。

OC4Jでのデフォルトのセッション・タイムアウトは30分です。アプリケーションのweb.xmlファイルで、<session-config>要素の<session-timeout>パラメータを設定することにより、特定のアプリケーションでこの値を変更できます。

ojspcユーティリティを使用したJSPページの事前変換

ojspcユーティリティを使用した、デプロイ前のJSPページの事前変換を検討してください。JSPページにはユーザーが最初にアクセスするため、このユーティリティを使用すると、ページを変換するときのパフォーマンスの損失が発生しません。このユーティリティの詳細な使用方法は、第4章「ojspcによるJSPページのプリコンパイル」を参照してください。

HTTPセッションにおける更新オブジェクトの再設定の確認

分散可能なWebアプリケーションのJSPを作成している場合、HTTPセッションで変更されたオブジェクトを再設定するようページをコーディングし、セッション・オブジェクトの更新がクラスタ環境でレプリケートされることを確認してください。

OC4Jでは、セッションで保存されたセッション・オブジェクトをシリアライズ化しますが、オブジェクトのデータ・メンバーが変更されてもセッション・オブジェクトは再シリアライズ化されません。したがって、更新されたセッション状態はレプリケートされません。この問題はJSP特有のものではなく、サーブレットなどでも、セッションで変更されたオブジェクトを再設定する必要があります。

JSPでは、変更可能なセッション属性ごとに、HttpSessionに対してsetAttribute()をコールするスクリプトレットを含めることにより、セッション状態を確実にレプリケートする必要があります。

<jsp:useBean>タグを使用してsessionスコープBeanを作成する場合、setAttribute()をコールしてセッションの更新されたBeanを再設定します。Beanの作成時にBeanに設定されたプロパティはセッションに対して設定されますが、Beanのプロパティ値の更新は設定されません。

JSPページのバッファの無効化

JSPページのバッファを無効にします。デフォルトでは、JSPページはページ・バッファと呼ばれるメモリー領域を使用します。このバッファ(デフォルトは8 KB)は、動的なグローバリゼーション・サポートのコンテンツ・タイプの設定、転送またはエラー・ページをページで使用する場合に必要です。このような機能をページで使用しない場合は、pageディレクティブのバッファを無効にできます。

<%@ page buffer="none" %>

これによって、メモリーの使用量が減少し、バッファをコピーする出力手順が不要になるため、パフォーマンスが改善されます。

JSPページへのリダイレクトを使用しない転送

1つのJSPページから別のページに制御を渡す方法は2つあります。<jsp:forward>標準アクションタグを使用する方法と、スクリプトレットでリダイレクトURLをresponse.sendRedirect()に渡す方法です。

<jsp:forward>オプションの方が速く、効率的です。この標準アクションを使用すると、転送されたターゲット・ページはJSPランタイムによって内部的に起動され、継続してリクエストが処理されます。転送が実行されたことはブラウザに認識されず、ユーザーからは処理全体がシームレスに感じられます。

sendRedirect()を使用すると、ブラウザはリダイレクトされたページに新しいリクエストを送信する必要があります。ブラウザに表示されるURLは、リダイレクトされたページのURLに変更されます。さらに、リダイレクトには新しいリクエストが含まれるため、すべてのrequestスコープのオブジェクトが、リダイレクトされたページで使用できなくなります。

ユーザーがページを再ロードする場合に、実行されている実際のページがURLに反映されるようにする場合のみ、リダイレクトを使用してください。

アクセスを制限するために直接起動から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タイムアウトの利用

<orion-web-app>要素のjsp-timeout属性に、整数値(秒単位)を指定します。この値が経過した後にリクエストされなかった場合、そのJSPページはメモリーから削除されます。これによって、コール頻度の低いページに割り当てられているリソースが解放されます。デフォルト値は0(ゼロ)で、タイムアウトはありません。 <orion-web-app>属性は、OC4Jのglobal-web-application.xmlファイルおよびorion-web.xmlファイル内にあります。OC4Jインスタンス内のすべてのアプリケーションにタイムアウトを適用する場合、global-web-application.xmlファイルを変更します。特定のアプリケーションの構成値を設定する場合、アプリケーション固有のorion-web.xmlファイル内のファイルを変更します。

デプロイ用のEARファイル内のJSPファイルのパッケージ化

OC4Jでは、ファイルを直接適切な場所にコピーすることによるJSPページのデプロイをサポートしています。ページの開発やテストの際、この機能は大変便利です。

ただし、JSPベースのアプリケーションを本番用にリリースする場合、この方法はお薦めしません。必ずJSPファイルをEnterprise Archive(EAR)ファイルにパッケージ化して、標準的なデプロイおよび複数のアプリケーション・サーバーに渡るデプロイを可能にしてください。

パフォーマンス改善のための動的キャラクタ・セットのチェックの無効化

デフォルトでは、JspWriterが出力/書込みのたびに動的なキャラクタ・セットをチェックします。パフォーマンス改善のため、OC4J全体のシステム・プロパティを-Dcheck.dynamic.charset="false"に設定して、このチェックを無効にします。

これにより、キャラクタ・セットのチェックは、JspWriterでの出力/書込みごとではなく、リクエストごとに1回実行されます。

JSPファイルでの引用符の正しい使用

次の例には、JSPファイル内での誤った引用符の使用例が含まれています。

    <td width="100%" 
style="border-left: 1px solid #000; border-right: 1px solid #000; <dhv:evaluate if="<%= 
!i.hasNext() %>">border-bottom: 1px solid 
#000;</dhv:evaluate>">

問題はstyle属性の2つ目の引用符(if=の後)です。

    style="border-left: 1px solid #000; border-right: 1px solid #000; 
<dhv:evaluate if="<%= !i.hasNext() %>">border-bottom: 1px solid 
#000;</dhv:evaluate>">

Tomcatはこの正しくないコードを受け入れ、処理を続行します。

OC4JはJSPおよびサーブレットの仕様に従い、正しくないコードを受け入れず、エラーを発行します。

この問題を解決するには次を実行する必要があります。

他にも引用符に関する問題があります。

プログラマがページの動的コンテンツに依存する外観を作成する場合があります。たとえば、個別に表の最終行を表示するとします。一部のライブラリはこれが可能であり、ライブラリをタグの属性内に含めて、周囲のタグがコールされる前に評価することができます。

Tomcatでは次のシーケンスを使用できます。

    attribute="text"another text"text"

Tomcatでは、属性値が行の最初の引用符から最後の引用符までの単一の値として解析されます。

一方、OC4Jでは、属性値が最初の引用符と2つ目の引用符の間にある文字列textとして解析されます。後続の文字列another text"text"はエラーとみなされます。

正しくない使用方法:

<td width="100%"
   height="<dhv:evaluate if="<%= !i.hasNext() %>">20</dhv:evaluate>">

パーサーでの表示:

<td width="100%"
   height="<dhv:evaluate if=" <<-- ERROR Tag not closed!!
   <%= !i.hasNext() %>">20</dhv:evaluate>">

正しい使用方法:

<td width="100%"
   height="<dhv:evaluate if='<%= !i.hasNext() %>'>20</dhv:evaluate>"> 

サーブレットの使用

JSPページのコーディングは多くの点で便利ですが、サーブレットのコールが必要な場合があります。その一例は、バイナリ・データを出力する場合です。

このため、サーブレットとJSPページ間での往復が、1つのアプリケーション内で必要になる場合があります。次の各項で、その方法を説明します。

JSPページからのサーブレットの起動

あるJSPページから別のJSPページを起動する場合と同様に、jsp:include操作タグとjsp:forward操作タグを使用して、JSPページからサーブレットを起動できます。(「標準のJSPアクション・タグ」を参照。)次に例を示します。

<jsp:include page="/servlet/MyServlet" flush="true" />

ページの実行中にこの文が出現すると、ページ・バッファがブラウザに出力され、サーブレットが実行されます。サーブレットの実行が終了すると、制御がJSPページに戻されて、ページの実行が続行されます。この機能は、JSPページ間におけるjsp:include操作タグと同じ機能です。

また、JSPページ間におけるjsp:forward操作タグと同様に、次の文は、ページ・バッファをクリアし、JSPページの実行を終了して、サーブレットを実行します。

<jsp:forward page="/servlet/MyServlet" />

JSPページから起動したサーブレットへのデータの受渡し

JSPページからサーブレットに動的にインクルードまたは転送を行う場合は、jsp:paramタグを使用して、サーブレットにデータを渡すことができます(別のJSPページへのインクルードまたは転送でも同様です)。

jsp:paramタグは、jsp:includeタグまたはjsp:forwardタグ内で使用できます。次に例を示します。

<jsp:include page="/servlet/MyServlet" flush="true" >
   <jsp:param name="username" value="Smith" />
   <jsp:param name="userempno" value="9876" />
</jsp:include>

jsp:paramタグの詳細は、「標準のJSPアクション・タグ」を参照してください。

適切なスコープのJavaBean、またはHTTPリクエスト・オブジェクトの属性を使用して、JSPページとサーブレットとの間でデータの受渡しを行うこともできます。リクエスト・オブジェクトの属性の使用方法は、「JSPページとサーブレット間でのデータの受渡し」で説明します。

サーブレットからのJSPページの起動

標準のjavax.servlet.RequestDispatcherインタフェースの機能を使用すると、サーブレットからJSPページを起動できます。この機能を使用するには、次の手順に従ってコードを作成します。

  1. サーブレット・インスタンスからサーブレット・コンテキスト・インスタンスを取得します。

    ServletContext sc = this.getServletContext();
    
  2. サーブレット・コンテキスト・インスタンスからリクエスト・ディスパッチャを取得し、ターゲットのJSPページのページ相対パスまたはアプリケーション相対パスをgetRequestDispatcher()メソッドへの入力として指定します。

    RequestDispatcher rd = sc.getRequestDispatcher("/jsp/mypage.jsp");
    

    この手順の実行前か実行中に、HTTPリクエスト・オブジェクトの属性を必要に応じて使用して、JSPページにデータを受け渡すことができます。詳細は、次項の「JSPページとサーブレット間でのデータの受渡し」を参照してください。

  3. リクエスト・ディスパッチャのinclude()メソッドまたはforward()メソッドを起動し、HTTPリクエスト・オブジェクトとレスポンス・オブジェクトを引数として指定します。次に例を示します。

    rd.include(request, response);
    

    または

    rd.forward(request, response);
    

    これらのメソッドの機能は、jsp:includeタグおよびjsp:forwardタグの機能と同じです。include()メソッドは一時的に制御を移すのみで、後で、起動したサーブレットに実行の制御が戻されます。

    forward()メソッドは、出力バッファをクリアすることに注意してください。


    注意

    リクエスト・オブジェクトとレスポンス・オブジェクトは、標準のサーブレット機能(javax.servlet.http.HttpServletクラスに指定されているdoGet()メソッドなど)を使用して、事前に取得されています。 


JSPページとサーブレット間でのデータの受渡し

前の項の「サーブレットからのJSPページの起動」で説明したように、リクエスト・ディスパッチャを使用してサーブレットからJSPページを起動するとき、HTTPリクエスト・オブジェクトを必要に応じて使用して、データを受け渡すことができます。この操作は、次のいずれかの方法で実行できます。

JSPとサーブレット間の相互作用のサンプル

この項では、前の各項で説明した機能を使用したJSPページとサーブレットのサンプルを示します。JSPページのJsp2Servlet.jspには、サーブレットのMyServletがインクルードされ、このサーブレットには別のJSPページのwelcome.jspがインクルードされます。

Jsp2Servlet.jspのコード

<HTML>
<HEAD> <TITLE> JSP Calling Servlet Demo </TITLE> </HEAD>
<BODY>

<!-- Forward processing to a servlet -->
<% request.setAttribute("empid", "234"); %>
<jsp:include page="/servlet/MyServlet?user=Smith" flush="true"/>

</BODY>
</HTML>

MyServlet.javaのコード

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.PrintWriter;
import java.io.IOException;

public class MyServlet extends HttpServlet {

    public void doGet (HttpServletRequest request,
                       HttpServletResponse response) 
      throws IOException, ServletException {
      PrintWriter out= response.getWriter(); 
      out.println("<B><BR>User:" + request.getParameter("user"));
      out.println
          (", Employee number:" + request.getAttribute("empid") + "</B>");
      this.getServletContext().getRequestDispatcher
                       ("/jsp/welcome.jsp").include(request, response);
    }
}

welcome.jspのコード

<HTML>
<HEAD> <TITLE> The Welcome JSP  </TITLE> </HEAD>
<BODY>

<H3> Welcome! </H3>
<P><B> Today is <%= new java.util.Date() %>.  Have a nice day! </B></P>
</BODY>
</HTML>

Apache TomcatからOC4JへのJSPページの移行

この項では、JavaServer Pagesを含むアプリケーションをTomcatからOracle Application Server(OC4J)に移行する場合に使用するJSP固有のポインタを示します。TomcatからOC4Jへの移行に関する主な説明は、『Oracle Containers for J2EEサーブレット開発者ガイド』の第6章のアプリケーションのApache TomcatからOC4Jへの移行に関する項に記載されています。これには、TomcatからOC4JへのJSPコンパイルの問題に関する項も含まれています。

概要

JSPページはTomcatからOracle Application Serverへ簡単に移行でき、Tomcat環境で選択した内容に応じて、コードの変更はほとんど必要ないか、あるいはまったく必要ありません。

Oracle Application Server 10gリリース3(10.1.3.1)は、Sun社のJavaServer Page仕様バージョン2.0に準拠しています。Tomcat 5.5も、バージョン2.0と互換性があります。TomcatとOracle Application Server Containers for J2EE(OC4J)の両方に同じバージョンのJava Server Pages仕様が実装されているため、コアJSP仕様の領域でこの2つに違いはありません。

また、Oracle Application Server 10gリリース3(10.1.3.1)は、バージョン1.2との下位互換性があります。そのため、標準のバージョン1.2仕様で作成されたJSPページは、Oracle Application Serverで正常に作動し、移行の手間は最小限で済みます。

JSPページを新しい環境に移行する場合の主なタスクは、構成とデプロイです。独自の拡張子を使用すると、追加のタスクが必要になり、移行が複雑になります。

JSPページの移行に関係するタスクは、JSPページのパッケージとデプロイの方法によっても異なります。JSPページは、単純なJSPページとして、標準ディレクトリ構造内でその他のリソースとともにパッケージされるWebアプリケーションとして(WARファイル)、またはEnterprise Application Archive(EAR)ファイルとしてデプロイできます。

移行手順

TomcatからOC4JへのJSPページの移行は簡単で、移行タスクには構成、(WARファイルへの)パッケージおよび(適切なデプロイ・ディレクトリへの)デプロイが含まれます。これらのタスクは、手動あるいはOracle JDeveloperを使用して実行できます。

単純なJSPページの移行

JSPページには、HTTPサーブレットのような特定のマッピングは必要ありません。単純なJSPページは、JSPページおよびJSPページに必要なすべてのファイルを適切なディレクトリにコピーすることでデプロイできます。その他の登録は必要ありません。


注意

JSPを含むすべてのタイプのアプリケーションのデプロイには、Application Server Controlコンソールを使用することをお薦めします。ただし、説明のため、次の例ではJSPページをApplication Server Controlコンソールを使用せずに手動で移行する方法を示します。 


OC4Jのデプロイ・プロセスは、J2EE Webアプリケーションと様々な構成ファイルをデフォルトで提供することで簡略化されています。

単純なJSPページをTomcatからOC4Jへ移行する一般的な手順は、次のとおりです。

  1. OC4Jのインスタンスが実行されていない場合は、起動します。

    Oracle Enterprise Manager 10g Application Server Controlコンソールの「管理」Webページを使用するか、次のopmnctlコマンド(ローカルで実行)を使用します。

    opmnctl @instance startproc ias-component=OC4J 
    
  2. TomcatのディレクトリからOC4Jの適切なディレクトリにJSPページをコピーします。

  3. URLを使用し、WebブラウザからJSPページをリクエストします。次に例を示します。

     http://<hostname>:7777/j2ee/MyJspPage.jsp 
    

    <hostname>は、JSPファイルをコピーしたOracle Application Serverのホストです。

JSPページの構成とデプロイの詳細は、『Oracle Containers for J2EE構成および管理ガイド』を参照してください。

JSPページのプリコンパイル

JSPページはJSPコンパイラによって自動的にコンパイルされます。ただし、JSPページのテストおよびデバッグを行う場合は、直接JSPコンパイラにアクセスします。

JSPコンパイラは.jspファイルを解析して.javaファイルにします。次に、標準のJavaコンパイラを使用して.javaファイルを.classファイルにコンパイルします。

次のツールのいずれかを使用して、JSPページをプリコンパイルできます。

実行時エラーの処理

JSPページを実行してクライアント・リクエストを処理している間に、ページの内側または外側(コールされたJavaBean内など)で実行時エラーが発生する場合があります。この項ではエラー処理機能について説明し、基本的な例を示します。

サーブレットとJSPの実行時エラー処理機能

この項では、実行時例外の処理機能について説明します。JSPエラー・ページを使用する場合についても説明します。

一般的なサーブレット実行時エラー処理機能

JSPページの実行中に発生した実行時エラーは、標準のJava例外処理機能によって、次のいずれかの方法で処理されます。

エラー・リソースのURLは、元のJSPページでpageディレクティブのerrorPage属性を設定すると指定できます。(pageディレクティブなどのJSPディレクティブの概要は、「ディレクティブ」を参照してください。)

デフォルトのエラー・リソースの詳細は、Sun社のJavaサーブレット仕様2.4を参照してください。

JSPエラー・ページ

オプションとして、別のJSPページを、元のJSPページからの実行時例外のエラー・リソースとして使用する方法があります。JSPエラー・ページには、isErrorPage="true"に設定するpageディレクティブが必要です。この方法で定義されたエラー・ページは、web.xmlファイルで宣言されているエラー・ページよりも優先されます。

エラーの情報を持つjava.lang.Throwableインスタンスは、エラー・ページでJSPの暗黙的なexceptionオブジェクトを介してアクセス可能です。このオブジェクトにアクセスできるのはエラー・ページのみです。exceptionオブジェクトなど、JSPの暗黙的なオブジェクトの詳細は、「暗黙的なオブジェクト」を参照してください。

元のJSPページにautoFlush="true"(デフォルト設定)のpageディレクティブがあり、そのページのJspWriterオブジェクトのコンテンツがレスポンスの出力ストリームにすでにフラッシュされている場合、取得されなかった例外をエラー・ページに転送しようとしても、レスポンスをクリアできない可能性があることに注意してください。一部のレスポンスは、ブラウザがすでに受信している可能性があります。

エラー・ページの使用例は、次の「JSPエラー・ページの例」の項を参照してください。

JSPエラー・ページの例

次のnullpointer.jspの例では、エラーを生成し、エラー・ページのmyerror.jspを使用して、暗黙的なexceptionオブジェクトのコンテンツを出力します。

nullpointer.jspのコード

<HTML>
<BODY>
<%@ page errorPage="myerror.jsp" %>
Null pointer is generated below:
<%
   String s=null;
   s.length();
%>
</BODY>
</HTML>

myerror.jspのコード

<HTML>
<BODY>
<%@ page isErrorPage="true" %>
Here is your error:
<%= exception %>
</BODY>
</HTML>

この例では、次の内容が出力されます。



注意

処理がエラー・ページに転送された場合、nullpointer.jspの「Null pointer is generated below:」の行は出力されません。これは、jsp:include機能とjsp:forward機能の違いを示しています。jsp:forwardの場合は、転送先ページの出力によって、転送元ページの出力が置換されます。 



戻る 次へ
Oracle
Copyright © 2007 Oracle Corporation.

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