ヘッダーをスキップ
Oracle Application Server JBossからの移行
10g リリース3(10.1.3.1.0)
B31846-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

3 サーブレットの移行

この章では、サーブレットの主な機能とAPI、JBossでのサーブレットAPIとその標準に対する拡張機能のサポート、およびOC4JでのサーブレットAPIのサポートについて説明します。

3.1 JavaサーブレットAPIの概要

サーブレットは、Webコンテナおよびサーブレット・エンジンで実行されるJavaクラスのインスタンスです。サーブレットを使用して、動的なWebページを生成します。サーブレットでは、通常はHTTPプロトコルを使用して、Webクライアントからのリクエストの受信および応答が行われます。

サーブレットには、従来のCGIプログラミングと比較すると次のメリットがあります。

サーブレットAPIは、javax.servletおよびjavax.servlet.httpという2つのJava拡張パッケージで指定されています。ただし、ほとんどのサーブレットでは、サーブレットAPIの標準的な実装であるjavax.servlet.GenericServletおよびjavax.servlet.http.HttpServletのいずれかが拡張されています。これらのうち、javax.servletのクラスおよびインタフェースはプロトコルに依存しませんが、javax.servlet.httpにはHTTPに固有のクラスが含まれています。

サーブレットAPIのサポートは、次の4つのカテゴリで提供されています。

使用する目的に応じて、サーブレットAPIクラスが識別されます。

表3-1 サーブレットAPIのクラス

目的 クラスまたはインタフェース

サーブレットの実装

javax.servlet.Servlet

javax.servlet.SingleThreadModel

javax.servlet.GenericServlet

javax.servlet.httpServlet

サーブレットの構成

javax.servlet.ServletConfig

サーブレットの例外

javax.servlet.ServletException

javax.servlet.UnavailableException

リクエスト/レスポンス

javax.servlet.ServletRequest

javax.servlet.ServletResponse

javax.servlet.ServletInputStream

javax.servlet.ServletOutputStream

javax.servlet.http.HttpServletRequest

javax.servlet.http.HttpServletResponse

セッション・トラッキング

javax.servlet.http.HttpSession

javax.servlet.http.HttpSessionBindingListner

javax.servlet.http.HttpSessionBindingEvent

javax.servlet.http.Cookie

サーブレット・コンテキスト

javax.servlet.ServletContext

サーブレット・コラボレーション

javax.servlet.RequestDispatcher


3.1.1 サーブレットのライフ・サイクル

サーブレットは、Webサーバー自体と同じプロセスの一部として、Webサーバー・プラットフォームで実行されます。Webサーバーでは、各サーブレット・インスタンスの初期化、起動、および破棄が行われます。Webサーバーでは、javax.servlet.Servletという単純なインタフェースを介してサーブレットとの通信が行われます。

このインタフェースは、次の3つの主要メソッドで構成されています。

  • init()

  • service()

  • destroy()

また、次の2つの補助メソッドも含まれています。

  • getServletConfig()

  • getServletInfo()

3.1.1.1 init()メソッド

サーブレットが初めてロードされると、init()メソッドが起動され、ファイルのオープン、サーバー接続の確立などの初期プロセスが開始されます。サーブレットは、サーバーに永続的にインストールされた場合、サーバーの起動時にロードされます。

そうでない場合、サーブレットは、サーブレットによって提供されるサービスへの最初のクライアント・リクエストがサーバーで受信されると、サーバーによってアクティブ化されます。init()メソッドは、service()メソッドへのコールなどの他のコールがサーブレットに行われる前に終了することが保証されています。init()メソッドは、1回のみコールされます。サーブレットがサーバーによって再ロードされないかぎり、再度コールはされません。

init()メソッドは、ServletConfigオブジェクトへの参照である1つの引数を取ります。このオブジェクトによって、サーブレットに初期化引数が提供されます。このオブジェクトには、サーブレットの環境に関する情報が格納されているServletContextオブジェクトを戻すgetServletContext()メソッドが含まれています。

3.1.1.2 service()メソッド

service()メソッドは、サーブレットの中心的な機能です。クライアントからのリクエストごとに、サーブレットのservice()メソッドが1回コールされます。service()メソッドでは、次の2つのパラメータを使用して、リクエストの読取りおよびレスポンスの生成が行われます。

  • クライアントからのデータが含まれているServletRequestオブジェクト。データは、パラメータの名前/値のペアおよびInputStreamで構成されています。クライアントのパラメータ情報を戻すいくつかのメソッドが提供されています。クライアントのInputStreamは、getInputStream()メソッドを使用して取得できます。このメソッドによってServletInputStreamが戻されます。これを使用して、クライアントから追加データを取得できます。バイト・レベルではなく文字レベルでデータを処理する必要がある場合は、かわりにgetReader()を使用してBufferedReaderを取得できます。

  • クライアントに戻すサーブレットの応答を表すServletResponse。レスポンスを準備する場合は、まずメソッドsetContentType()をコールして、応答のMIMEタイプを設定します。次に、getOutputStream()メソッドを使用してServletOutputStream取得するか、またはgetWriter()メソッドを使用してPrintWriterを取得し、データをクライアントに戻します。

クライアントがサーブレットに情報を送信するには2つの方法があります。1つはパラメータ値を送信する方法で、もう1つはInputStream(またはReader)を使用して情報を送信する方法です。パラメータ値は、URLに埋め込むことができます。service()メソッドのジョブは単純です。このジョブでは、ホスト・サーバーから送信されてくるクライアント・リクエストごとにレスポンスが作成されます。ただし、同時に処理されるサービス・リクエストが複数存在する場合があります。サービス・メソッドでファイル、データベース、外部データなどの外部リソースが必要な場合、リソースへのアクセスは、スレッドセーフにする必要があります。

3.1.1.3 destroy()メソッド

destroy()メソッドをコールすると、サーブレットがアンロードされる前に、サーブレットのすべてのリソース(オープンされているファイル、データベース接続など)をクリーンアップできます。このメソッドは、クリーンアップ操作が不要な場合、空にすることができます。

サーバーは、すべてのサービス・コールが完了するか、または一定の時間が経過するまでdestroy()メソッドのコールを待機します。つまり、destroy()メソッドは、実行時間が長いservice()メソッドの実行中にコールされる可能性があります。destroy()メソッドは、すべてのservice()コールが完了するまで必要なリソースがクローズされないように記述する必要があります。

3.1.2 セッション・トラッキング

HTTPは、ステートレスなプロトコルであるため、クライアントがリソースをリクエストするたびにサーバーに対して別の接続がオープンされます。また、接続間でコンテキストが保持されないため、各トランザクションは独立したものとなります。ただし、ほとんどのWebアプリケーションはステートレスではありません。堅牢なWebアプリケーションでは、ユーザーと対話し、ユーザーのリクエストの性質を記憶し、あるリクエストでユーザーに関して収集したデータを、同じユーザーからの次回のリクエストで利用できるようにする必要があります。代表的な例には、インターネット商取引でのショッピング・カート・アプリケーションがあります。サーブレットAPIでは、複数の接続にまたがる場合でも、セッションの識別およびセッションへのデータの関連付けのための技術が提供されます。これらの技術には、次のものがあります。

  • Cookie

  • URLリライティング

  • 非表示のフォーム・フィールド

(使用されている技術に関係なく)アプリケーション・コード内のセッション情報を手動で管理する必要性をなくすには、JavaサーブレットAPIのHttpSessionクラスを使用します。HttpSessionインタフェースを使用すると、サーブレットで次の処理を実行できます。

  • セッションに関する情報の表示および管理。

  • 複数のページ・リクエストおよび接続を含めるための複数のユーザー接続にまたがる情報の保持。

3.1.2.1 Cookie

Cookieがセッション・トラッキングの最も一般的な方法です。Cookieでは、クライアント・マシン上の人間が判読可能なファイルに、セッションに関する情報が格納されます。後続のセッションでは、Cookieにアクセスして情報を抽出できます。サーバーでは、CookieからのセッションIDがそのセッションのデータに関連付けられます。関連するCookieが複数ある場合、Cookieの有効期限を決定する必要がある場合、および一意のセッション識別子が多数必要な場合、この処理は複雑になります。また、Cookieには、最大サイズが4KB、ドメイン当たりの最大数が20個という制限もあります。Cookieには、ユーザーのプライバシの問題もあります。自身のローカル・ディスクの情報をプログラムによって格納および取得されることを好まず、Cookieを無効にしたり、Cookieを完全に削除するユーザーもいます。したがって、セッション・トラッキングのメカニズムをCookieのみに頼ることはできません。

3.1.2.2 URLリライティング

URLリライティング技術では、セッションを識別するためのデータが各URLの末尾に追加されます。サーバーでは、格納されているセッションに関するデータに識別子が関連付けられます。URLは、HTTP GETを使用して構築されます。このURLには、パラメータと値のペアが含まれている問合せ文字列を含めることができます。次に例を示します。

 http://www.server.com/getPreferences?uid=username&bgcolor=red&fgcolor=blue

3.1.2.3 HTMLでの非表示のフォーム・フィールド

非表示のフォーム・フィールドを使用して、セッションに関する情報を格納することもできます。非表示のデータは、後でHTTPServletRequestオブジェクトを使用して取得できます。このデータは、フォームの送信時に、GETまたはPOSTにインクルードされます。ただし、フォーム・フィールドは動的に生成されるページでのみ使用できるため、使用できる範囲が制限されることに注意してください。また、ユーザーがHTMLソースを表示して格納データを参照できるというセキュリティ・ホールもあります。

3.1.3 HttpSessionオブジェクト

セッション・データは、収集する方法にかかわらず、格納する場所が必要です。HttpSessionオブジェクトを使用すると、サーブレットのセッション・データを格納し、ユーザーに関連付けることができます。

HttpSessionオブジェクトを使用する場合の基本的な手順は、次のとおりです。

  1. セッション・オブジェクトを取得します。

  2. セッション・オブジェクトに対して読取りまたは書込みを行います。

  3. セッションを強制的に終了するか、または自動的に期限切れさせて終了します。

セッションは、サーブレットに設定されている値に応じて、特定の期間または永続的に持続します。同じクライアントからサーバーへの複数のリクエストの追跡に、一意のセッションIDが使用されます。永続性は、複数のサーブレットが含まれている可能性があるWebアプリケーションのコンテキスト内で有効です。サーブレットでは、別のサーブレットによって保存されているオブジェクトにアクセスできます。オブジェクトは、名前で識別され、セッションにバインドされているとみなされます。これらのオブジェクト(setおよびgetメソッドがこれらに対して実行される場合は属性と呼ばれる)は、リクエスト、セッションまたはアプリケーションの有効範囲内の他のサーブレットで使用できます。

サーブレットは、リクエスト間の状態を維持するために使用しますが、従来のCGIおよび多くのCGIに代わる方法で実装する場合、この操作は煩雑になります。1つのみのサーブレット・インスタンスが作成され、リクエストごとに、サーブレットのサービス・メソッドをコールする新しいスレッドが生成されます(サービス・メソッドによってdoGetまたはdoPostがコールされます)。このため、共有データは、サーブレットの通常のインスタンス変数(フィールド)に配置する必要のみがあります。したがって、サーブレットでは、ブラウザによるページの再ロード時に実行中の計算に適切にアクセスできます。また、リクエストの結果を新しい順にN個保持できるため、最近行ったリクエストのパラメータと同じパラメータが新しいリクエストで指定された場合、すぐに結果が戻されます。サーブレットにも、作成者は共有データへのマルチスレッド・アクセスを同期させる必要があるという通常のルールが適用されます。

また、サーブレットでは、ServletContextオブジェクト(getServletContextメソッドを介して使用可能)に永続的なデータを格納することもできます。ServletContextにはsetAttributeおよびgetAttributeメソッドが含まれています。これらのメソッドによって、指定したキーに関連付けられている任意のデータを格納できます。データをインスタンス変数に格納する場合とServletContextに格納する場合の相違点として、ServletContextがサーブレット・エンジンまたはWebアプリケーション内のすべてのサーブレットで共有される点があげられます。

3.1.4 J2EE Webアプリケーション

サーブレット仕様に定義されているとおり、Webアプリケーションは、サーブレット、JavaServer Pages(JSP)、Javaユーティリティ・クラスとライブラリ、静的ドキュメント(HTMLページ、イメージ、クライアント・サイドのアプレット、Bean、クラスなど)、およびサーブレット対応のすべてのWebサーバーに移植性を保持した状態でデプロイされるようにセットアップされたその他のWebリソースの集合です。Webアプリケーションは、そのまま1つのアーカイブ・ファイルに格納できます。また、そのファイルを特定のディレクトリに配置することによってデプロイできます。

3.1.4.1 Webアプリケーション・アーカイブ(WAR)

Webアプリケーション・アーカイブ・ファイルの拡張子は.warです。 WARファイルは、(jarユーティリティを使用して作成された).jarファイルを別の拡張子で保存したファイルです。JAR形式では、JARファイルを圧縮形式で保存し、そのコンテンツにデジタル署名できます。特定の操作用の.jarファイルを区別するために、.jarファイル拡張子のかわりに.warが選択されています。WARファイル・リストの例を次に示します。

index.html
howto.jsp
feedback.jsp
images/banner.gif
images/jumping.gif
WEB-INF/web.xml
WEB-INF/lib/jspbean.jar
WEB-INF/classes/MyServlet.class
WEB-INF/classes/com/mycorp/frontend/CorpServlet.class
WEB-INF/classes/com/mycorp/frontend/SupportClass.class

インストール時に、WARファイルをサーバー上の任意のURI接頭辞パスにマッピングできます。その接頭辞で始まるすべてのリクエストが、このWARファイルで処理されます。たとえば、前述のWARファイルが接頭辞/demoの下にインストールされた場合、サーバーでは/demoで始まるすべてのリクエストの処理にこのWARファイルが使用されます。/demo/index.htmlに対するリクエストでは、WARファイルのindex.htmlファイルが使用されます。/demo/howto.jspまたは/demo/images/banner.gifに対するリクエストの場合も、WARファイルのコンテンツが使用されます。

3.1.4.2 WEB-INFディレクトリの概要

WEB-INFディレクトリは、特殊なディレクトリです。このディレクトリ内のファイルは直接クライアントには提供されません。これらのファイルにはJavaクラスとWebアプリケーションの構成情報が含まれています。 このディレクトリは、JARファイルのMETA-INFディレクトリと同様に機能します。このディレクトリには、アーカイブ・コンテンツに関するメタ情報が含まれています。WEB-INF/classesディレクトリには、Webアプリケーションのサーブレットおよびサポートするクラスのクラス・ファイルが格納されます。WEB-INF/libには、JARファイルに格納されたクラスが含まれています。Webサーバー・クラス・ローダーによって、自動的にWEB-INF/classesおよびWEB-INF/libでクラスが検索されます。追加のインストール手順は不要です。

Webアプリケーションのサンプル・リストのWEB-INFの下にあるサーブレットは、/demo/servlet/MyServlet/demo/servlet/com.mycorp.frontend.CorpServletなどのURIを使用して起動できます。

このアプリケーションへのすべてのリクエストは、サーブレットへのリクエストの場合でも、/demoで始まることに注意してください。

WEB-INFディレクトリ内のweb.xmlファイルによって、Webアプリケーションの記述子が定義されます。web.xmlファイルには、このファイルが存在しているWebアプリケーションの構成情報が含まれています。web.xmlファイルは、サーブレットの登録、サーブレット初期化パラメータの定義、JSPタグ・ライブラリの登録、セキュリティ制約の定義、他のWebアプリケーション・パラメータの定義に使用されます。

3.1.5 サーブレット2.0、2.1および2.2の相違点

J2EE仕様のサーブレットAPIは、進化し続けています。2年の間にサーブレットAPI 2.0、2.1および2.2が公開されており、このドキュメントを記述している時点での最新バージョンはサーブレットAPI 2.3です。サーブレットの基本アーキテクチャに大きな変更はないため、ほとんどのAPIはそのまま機能します。ただし、強化点および新機能がいくつかあり、一部のAPIは非推奨となりました。

この項では、サーブレットAPI 2.0、2.1、2.2および2.3ドラフト仕様での主な相違点について説明します。

3.1.5.1 JavaサーブレットAPI 2.1の特徴

サーブレットAPI 2.1の特徴は、次のとおりです。

  • リソース(サーブレット)ごとのリクエスト・ディスパッチャ・ラッパー

    リクエスト・ディスパッチャは、HTTPリクエストの処理が可能なリソース(サーブレット、JSPなど)およびそのリソースに関連するファイル(静的なHTMLやGIFなど)のラッパーです。サーブレットまたはJSPがインスタンス化されるたびに、サーブレット・エンジンによってリクエスト・ディスパッチャが1つ生成されます。このリクエスト・ディスパッチャがクライアント・リクエストを受信して、リソースにディスパッチします。

  • アプリケーションごとのサーブレット・コンテキスト

    サーブレットAPI 2.0では、サーブレット・エンジンによって、すべてのサーブレットで共有されるサーブレット・コンテキストが1つ生成されました。サーブレットAPI 2.1では、アプリケーションごとに1つのサーブレット・コンテキストが生成されるため、アプリケーションのパーティション化が簡単に行われます。アプリケーション・プログラミング・モデルの説明のとおり、同じ仮想ホスト上のアプリケーションは、互いのサーブレット・コンテキストにアクセスできます。

  • 非推奨のHTTPセッション・コンテキスト

    サーブレットAPI 2.0では、HttpSessionContextインタフェースによって、特定のWebサーバーのすべてのセッションが1つのセッション・コンテキストにグループ化されていました。セッション・コンテキストのインタフェース・メソッドを使用して、サーブレットでセッション・コンテキストのセッションIDリストを取得し、特定のIDに関連付けられたセッションを取得することが可能でした。サーブレットAPI 2.1では、セキュリティ上の安全のため、このインタフェースは非推奨となりました。このインタフェース・メソッドは、NULLを戻すように再定義されています。

3.1.5.2 JavaサーブレットAPI 2.2の新機能

サーブレットAPI 2.2仕様では、「サーブレット・エンジン」という用語が「サーブレット・コンテナ」に変更されました。この変更は、JavaサーブレットAPIがJava 2 Platform Enterprise Edition(J2EE)仕様での必須APIになり、J2EEの用語全体で「コンテナ」が「エンジン」より優先使用されるようになったことを示しています。サーブレットAPI 2.2では、次の新機能が導入されました。

  • Webアプリケーション(前述のとおり)。

  • 外部データソースへの参照。(JNDIなど)JNDI参照表にリソース(データベース接続など)を追加できます。単純な名前参照を使用して、サーブレットでリソースを指定できます。

  • アプリケーションのパラメータ情報(アプリケーションの初期化パラメータ)。

  • サーブレット名の登録。サーブレットを登録し、サーブレットに名前を付ける場所が提供されています。以前は、サーブレットを登録するプロセスがサーバーごとに異なっていたため、デプロイが困難でした。

  • サーブレット初期化パラメータ。初期化時に、サーブレット・パラメータにパラメータを渡すことができます。これは、以前はサーバー依存のプロセスであった処理を実現するための新しい標準的な方法です。

  • サーブレットのロード順序。事前ロードするサーブレットおよびそのロード順序を指定します。

  • セキュリティ制約。保護する必要があるページおよびその保護メカニズムを指定します。フォーム・ベース認証が組み込まれています。

3.1.5.3 サーブレットAPI 2.3

サーブレットAPI 2.3では、サーブレットのコア部分にほとんど変更はありません。追加および変更された内容は、次のとおりです。

  • JDK 1.2以上が必要です。

  • フィルタ・メカニズムが作成されています。

  • アプリケーション・ライフ・サイクル・イベントが追加されています。

  • 国際化サポートがさらに追加されています。

  • JAR間の依存関係を表現する技術が正式に定義されています。

  • クラスのロード規則が明確化されています。

  • エラー属性およびセキュリティ属性が追加されています。

  • HttpUtilsクラスは非推奨になっています。

  • DTDの動作の多くが拡張され、明確化されています。

3.1.5.4 フィルタおよびサーブレット・チェーン

サーブレット2.3 APIの一部として、フィルタリング機能がサポートされています。JBoss 3.2.6では、同様のフィルタリング機能がJBoss固有のパッケージで実現されています。OC4Jでは、Javaサーブレット2.3のフィルタリング仕様がサポートされています。

フィルタリングは、Webサーバーでサーブレットをロードおよび起動する方法の1つです。ローカル・サーブレットとリモート・サーブレットのいずれも、サーブレット・チェーン(後述)の一部にすることができます。ただし、ローカルの内部サーブレットをチェーン化する場合は制約があり、その制約は使用するJ2EEコンテナに固有のものになります。たとえば、JBossでは、内部サーブレットをチェーンで使用する場合、内部サーブレットをチェーンの最初のサーブレットにする必要があります。内部サーブレットには、fileサーブレット、pageCompileサーブレット、ssIncludeサーブレットおよびtemplateサーブレットがあります。

3.1.5.5 サーブレット・チェーン

一部のリクエストでは、1つのサーブレットのみではなく、順序付けられたサーブレットのチェーンを起動できます。ブラウザからの入力がチェーンの最初のサーブレットに送信され、チェーンの最後のサーブレットからの出力が、ブラウザに返信されるレスポンスになります。チェーン内の各サーブレットによって、直前のサーブレットからの入力が受信され、直後のサーブレットに出力が送信されます。次のものを使用して、受信リクエストに対してサーブレット・チェーンをトリガーすることができます。

  • リクエストに対するサーブレット・チェーンを示すサーブレットの別名

  • チェーン内の次のサーブレットをトリガーするMIMEタイプ

3.1.6 JBossでのサーブレットAPIのサポート

JBoss 3.2.6では、Tomcatサーブレット・コンテナを介してJavaサーブレットAPI 2.2仕様がサポートされています。サード・パーティ製のサーブレット・コンテナは、オプションのJBoss-app.xml記述子、およびセキュリティにJBossセキュリティ層を使用するJBoss JNDIネームスペースにweb-app.xml JNDIの情報をマッピングすることによって、JBossと統合できます。

3.1.7 Oracle Application ServerでのサーブレットAPIのサポート

Oracle Application Server OC4Jは、Javaサーブレット2.2および2.3仕様に完全準拠して実装されています。したがって、Javaサーブレット2.2の標準コードが正常に動作します。