前へ     目次     索引     DocHome     次へ     
iPlanet Application Server 開発者ガイド



第 2 章   Servlet によるアプリケーションの制御


この章では、iPlanetTM Application Server 上で行われるアプリケーション対話の制御に有効な Servlet (標準の Servlet を含む) の作成方法について説明します。また、標準を拡張する iPlanet Application Server の機能について説明します。

この章には次の節があります。



Servlet について

Servlet はアプレットと同様に再利用可能な Java アプリケーションです。ただし、Servlet は Web ブラウザ上ではなく、アプリケーションサーバまたは Web サーバ上で動作します。

iPlanet Application Server でサポートされる Servlet は、Java Servlet 仕様書バージョン 2.2 に基づいています。この仕様書は install_dir/ias/docs/index.htm からアクセス可能です。install_dir は、iPlanet Application Server がインストールされている場所です。

Servlet はアプリケーションのプレゼンテーションロジックに使われます。Servlet はフォーム入力処理、EJB にカプセル化されているビジネスロジックのコンポーネント起動、JSP を使った Web ページ出力のフォーマットなど、アプリケーションのセントラルディスパッチャとして機能します。Servlet はユーザからのリクエストに応じてコンテンツを生成し、ユーザ対話から次のユーザ対話に続くアプリケーションフローを制御します。

Servlet の基本的な特徴は次のとおりです。

  • Servlet は、iPlanet Application Server の Servlet エンジンによって実行時に作成され、管理される

  • Servlet は、request オブジェクトにカプセル化されている入力データを処理する

  • Servlet は、 response オブジェクトにカプセル化されているクエリデータに応答する

  • Servlet は EJB を呼び出してビジネスロジック機能を実行する

  • Servlet は JSP を呼び出してページレイアウト機能を実行する

  • Servlet は拡張可能であり、iPlanet Application Server とともに提供される API を使って機能を追加する

  • Servlet は対話間のユーザセッション情報のパーシスタンスを提供する

  • Servlet は、アプリケーションの一部にすることも、複数のアプリケーションに使えるように分離してアプリケーションサーバ上に置くこともできる

  • Servlet はサーバの動作中にダイナミックに再読み込みされる

  • Servlet は、URL でアドレスを指定できる。アプリケーションのページ上のボタンが Servlet を指している場合がある

  • Servlet はほかの Servlet を呼び出すこともできる

iPlanet Application Server のいくつかの API 機能によって、アプリケーションは iPlanet の特定の機能をプログラムに基づいて利用できます。詳細については、「iPlanet Application Server のオプション機能へのアクセス」を参照してください。


Servlet のデータフロー

ユーザが「Submit」ボタンをクリックすると、表示ページに入力された情報が Servlet に送信されます。Servlet は受信したデータを処理し、コンテンツを作成してレスポンスを構成します。このときビジネスロジックコンポーネント (EJB) を使う場合があります。コンテンツが作成されると、Servlet は通常、そのコンテンツを JSP に転送してレスポンスページを作成します。レスポンスはクライアントに返送され、次のユーザの対話について設定します。

次の図は、Servlet との間でやり取りされる情報のフローを示しています。

  1. Servlet がクライアントのリクエストを処理する

  2. Servlet がコンテンツを作成する

  3. Servlet がレスポンスを作成し、

    1. それをクライアントに返送する

      または

    2. そのタスクを JSP にディスパッチする



Servlet はほかのリクエストを処理できるようにメモリに残ります。


Servlet の種類

Servlet には主に次の 2 種類があります。

  • 汎用 Servlet

    • javax.servlet.GenericServlet を拡張します。

    • プロトコルに依存しません。継承 HTTP のサポートやほかの転送プロトコルは含まれていません。

  • HTTP Servlet

    • javax.servlet.HttpServlet を拡張します。

    • 組み込み HTTP プロトコルがサポートされているので、iPlanet Application Server 環境では便利。

これらの Servlet はそれぞれ、コンストラクタメソッドである init() とデストラクタメソッドである destroy() を実装し、リソースを初期化したり、リソースの割り当てを解除したりできます。

すべての Servlet が、Servlet に対するリクエストを処理する service() メソッドを実装する必要があります。汎用 Servlet の場合は、サービスメソッドをオーバーライドしてリクエスト処理用のルーチンを用意します。HTTP Servlet には、使用中の HTTP 転送メソッドに基づいて Servlet 内の別のメソッドに自動的にリクエストを転送するサービスメソッドがあります。したがって、HTTP Servlet の場合は doPost() をオーバーライドして POST リクエストを処理し、doGet() をオーバーライドして GET リクエストを処理します。



サーバエンジンについて



Servlet は iPlanet Application Server の Java サーバプロセスに存在し、Servlet エンジンによって管理されます。この Servlet エンジンは、Servlet のすべてのメタファンクションを処理する内部オブジェクトです。このメタファンクションには、インスタンス化、初期化、破棄、ほかのコンポーネントからのアクセス、設定管理などがあります。


Servlet のインスタンス化と削除

Servlet エンジンは、Servlet をインスタンス化したあと、その init() メソッドを実行して必要な初期化を行います。カウンタの初期化など、Servlet の生存期間の初期化関数を実行するには、このメソッドをオーバーライドします。

Servlet がサービスから削除されると、サーバエンジンは、最後のタスクを実行し、リソースの割り当てを解除できるように、Servlet 内の destroy() メソッドを呼び出します。ログメッセージを書き込んだり、ガベージコレクション時に検出されない残留コネクションを削除したりするには、このメソッドをオーバーライドします。


リクエスト処理

リクエストが行われると、iPlanet Application Server は受信データを Servlet エンジンに渡します。Servlet エンジンは、リクエストの入力データ (フォームデータ、cookie、セッション情報、URL の Name-value ペアなど) を HttpServletRequest リクエストオブジェクトタイプに処理します。

また、Servlet エンジンは、HttpServletResponse レスポンスオブジェクトタイプ内にカプセル化することによってクライアントのメタデータを取り込みます。その後、両方のオブジェクトをパラメータとして Servlet の service() メソッドに渡します。

HTTP Servlet 内のデフォルトの service() メソッドは、HTTP 転送メソッド (POSTGET など) に基づいてリクエストをほかのメソッドに転送します。たとえば、HTTP POST リクエストは doPost() メソッドに転送され、HTTP GET リクエストは doGet() メソッドに転送されます。これにより、Servlet は使用中の転送メソッドに応じてリクエストデータをさまざまな方法で処理できます。リクエストの転送はサービスメソッドによって行われるため、一般的に HTTP Servlet の service() をオーバーライドする必要はありません。その代わり、予想されるリクエストタイプに従って doGet()doPost() などをオーバーライドします。


ヒント

HTTP Servlet での自動転送を有効にするには、HTTP 転送メソッドを備えている request.getMethod() を呼び出します。iPlanet Application Server ですでにリクエストデータが Name-value リストに前処理されているため、機能を失うことなく簡単に HTTP Servlet の service() メソッドをオーバーライドできます。ただし、これによって前処理されたリクエストデータに依存することになるため、Servlet の移植性は低下します。



リクエストに応答するタスクを実行するには、service() メソッド (汎用 Servlet) または doGet() メソッドや doPost() メソッド (HTTP Servlet) をオーバーライドします。多くの場合、EJB にアクセスしてビジネストランザクションを実行し、リクエストオブジェクトまたは JDBC ResultSet オブジェクト内で情報を照合したあと、新たに作成されたコンテンツを JSP に渡してコンテンツのフォーマットとユーザへの配信を行います。


Servlet エンジンのリソースの割り当て

デフォルトでは、Servlet エンジンは新規リクエストごとにスレッドを作成します。この場合、リクエストごとにメモリ内で Servlet の新規コピーをインスタンス化するよりもリソースに与える影響は小さくなります。各スレッドが同じメモリ空間で動作し、変数が互いを上書きする場合があるので、スレッド問題の発生を避ける必要があります。

Servlet が特にシングルスレッドとして作成されている場合、Servlet エンジンは受信リクエストに使う Servlet のインスタンスを 10 個プールします。すべてのインスタンスが使用中であるときにリクエストを受信すると、インスタンスが使用可能になるまでリクエストはキューに入れられます。プールするインスタンスの数は、iPlanet Application Server 固有の XML ファイルである配置記述子 (DD) で設定できます。配置記述子の詳細については、第 11 章「配置のためのパッケージ化」を参照してください。

スレッド問題の詳細については、「スレッドの処理」を参照してください。


実行時の Servlet のダイナミック再読み込み

コンフィグレーションファイルを変更する必要がない場合は、iPlanet Application Server での Servlet の再読み込みは、サーバを再起動しなくても、Servlet を配置し直すだけで行うことができます。同じディレクトリ内で Servlet クラスファイルを新しいクラスファイルに置き換えても、再読み込みを実行できます。

iPlanet Application Server は、新しいコンポーネントを検出し、次の Servlet 要求時にそれを再読み込みします。詳細については、付録 B 「実行時の注意事項」を参照してください。



出荷時、この機能はデフォルトでオフになっています。必要に応じてオンにしてください。




配置用の Servlet の設定

Servlet を配置用に設定するときは、アプリケーションフレームワーク内での Servlet オブジェクトの作成および使用時にアプリケーションサーバが使うメタデータを指定します。Servlet の設定の詳細については、第 11 章「配置のためのパッケージ化」を参照してください。


Servlet ファイルの検索

Servlet ファイルとほかのアプリケーションファイルは、iPlanet Application Server によって AppPath として認識されるディレクトリ構造内にあります。この変数は、アプリケーションの論理ディレクトリツリーのトップを定義します。AppPath 変数は Web ブラウザのドキュメントパスに似ています。デフォルトでは、AppPath には値 BasePath/APPS が入っています。BasePath は iPlanet Application Server のベースディレクトリです。

AppPathBasePath は、サーバおよびアプリケーションメタデータのリポジトリである、iPlanet Application Server のレジストリに保持されている変数です。詳細については、「iPlanet Application Server レジストリ」と配置ツールのオンラインヘルプを参照してください。

AppPathBasePath に加えて、レジストリには ModulesDirName という名前の 3 番目の変数があります。この変数は、J2EE アプリケーションの一部でない Web モジュールのホームである AppPath の下位ディレクトリに対応します。これらの Web モジュールはスタンドアロンモジュールとして登録されます。

表 2-1 に、重要なファイルおよび Servlet の場所を示します。


表 2-1    重要なファイルおよび Servlet の場所 

場所変数

説明

BasePath  

iPlanet Application Server ツリーのトップ。このディレクトリ内のすべてのファイルが iPlanet Application Server の構成要素である。レジストリ変数 BasePath によって定義される  

AppPath  

アプリケーションツリーのトップ。この場所のサブディレクトリにアプリケーションがある。レジストリ変数 AppPath によって定義される  

ModulesDirName  

スタンドアロンエンティティとして登録されたすべての J2EE Web モジュールおよび EJB モジュールが入っている特別なディレクトリ ( Default アプリケーション内)。このディレクトリは AppPath の下位にある。レジストリ変数 ModulesDirName によって定義される。レジストリにあるこの変数のデフォルトの値は modulesである  

AppPath/appName/*  

アプリケーション appName のサブツリーのトップ。appName ディレクトリには、アプリケーション内のさまざまなモジュールのサブディレクトリがある。詳細については、「Servlet の起動」を参照してください。  


Servlet の配置

Servlet は通常、iPlanet Application Server Deployment Tool を使って、アプリケーションの残りの部分と共に配置します。また、サーバの動作中に Servlet の検査または更新を行う場合は、Servlet を手動でも配置できます。詳細については、配置ツールのオンラインヘルプを参照してください。



Servlet の設計



この節では、アプリケーションの構成に役立つ Servlet の計画時に必要となる基本的な設計上の決定事項について説明します。

通常、Web アプリケーションはリクエスト/レスポンスパラダイムに従います。したがって、ユーザはフォームの入力および送信の手順に従って Web アプリケーションと対話できます。Servlet は各フォームのデータを処理し、ビジネスロジック関数を実行し、次の対話を設定します。

アプリケーション全体の設計方法が決まると、対話ごとに必要な入出力パラメータを定義することにより、各 Servlet の設計方法が決まります。


Servlet の種類の選択

HttpServlet を拡張する Servlet は HTTP 環境用に設計されているため、HTTP 環境で非常に役立ちます。この組み込み HTTP サポートを利用する場合は、すべての iPlanet Application Server Servlet をGenericServlet からではなく HttpServlet から拡張することをお勧めします。詳細については、「Servlet の種類」を参照してください。


標準または非標準 Servlet の作成

アプリケーションの Servlet に関する重要な決定事項の 1 つに、公式仕様書に厳密に準拠した Servlet を作成して移植性を最大限に高めるか、または iPlanet Application Server の API で提供されている機能を利用するかがあります。この API を利用すると、iPlanet Application Server のフレームワークにおける Servlet の有用性が格段に向上します。

また、Servlet が iPlanet Application Server 環境で動作する場合は、iPlanet Application Server の機能だけを利用する移植性の高い Servlet も作成できます。

iPlanet Application Server 固有の API の詳細については、「iPlanet Application Server のオプション機能へのアクセス」を参照してください。


Servlet の再利用計画

Servlet は本来、サーバ上で動作する、独立した再利用可能なアプリケーションです。Servlet を 1 つのアプリケーションに関連付ける必要はありません。Default という名前のアプリケーションに Servlet ライブラリを配置すると、複数のアプリケーションで共有できます。

ただし、特定のアプリケーションの一部でない Servlet を使う欠点もあります。特に、Default アプリケーションの Servlet は、アプリケーションの一部である Servlet とは別に設定します。



Servlet の作成



Servlet を作成するには、次のタスクを実行します。

  • Servlet をアプリケーションに組み込みます。つまり、Servlet に汎用的な方法でアクセスされた場合、Servlet からアプリケーションデータにアクセスできないように設計します。

  • GenericServlet または HttpServlet を拡張するクラスを作成し、リクエストを処理する適切なメソッドをオーバーライドします。

  • iPlanet Application Server 管理ツール (iASAT) を使って、Servlet の Web アプリケーション配置記述子 (DD) を作成します。



iPlanet アプリケーションの Servlet ファイル

Servlet を構成するファイルは次のとおりです。


Servlet のクラスファイル

この節では、Servlet の作成方法、アプリケーションに関する決定事項、およびアプリケーション内の Servlet の配置場所について説明します。


クラス宣言の作成

Servlet を作成するには、基本的な I/O サポートと javax.servlet パッケージを持つ共有 Java クラスを記述します。このクラスは、GenericServlet または HttpServlet を拡張する必要があります。iPlanet Application Server Servlet は HTTP 環境に存在するので、HttpServlet の拡張をお勧めします。Servlet がパッケージに含まれる場合は、クラスローダがその Servlet を正しく配置できるようにパッケージ名も宣言する必要があります。

次のヘッダーの例は、myServlet という HTTP Servlet の宣言を示しています。

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

public class myServlet extends HttpServlet {
   ...
servlet methods...
}


メソッドのオーバーライド

次に、1 つまたは複数のメソッドをオーバーライドして、意図したタスクを実行するための指示を Servlet に与えます。Servlet によるすべての処理が、リクエストごとに、サービスメソッド (汎用 Servlet の service() メソッドまたは HTTP Servlet の doOperation() メソッドのどれか) で行われます。このメソッドは受信リクエストを受け取り、与えられた指示に従ってリクエストを処理し、出力を適切に送信します。同じように、この Servlet のほかのメソッドも作成できます。

ビジネスロジックには、トランザクションを実行するためのデータベースアクセスや EJB へのリクエスト送信を含めることができます。


初期化メソッドのオーバーライド
カウンタなどの Servlet インスタンスの生存期間のリソースを初期化したり割り当てたりするには、クラスを初期化する init() をオーバーライドします。init() メソッドは、Servlet がインスタンス化されてからリクエストを受け入れるまでの間に実行されます。詳細については、Servlet の API 仕様書を参照してください。



範囲を設定するために、すべての init() メソッドで super.init(ServletConfig) を呼び出す必要があります。これにより、この Servlet の設定オブジェクトをほかの Servlet メソッドでも使うことができるようになります。この呼び出しを省略すると、Servlet の起動時に「500 SC_INTERNAL_SERVER_ERROR」がブラウザに表示されます。



次の init() メソッドの例では、thisMany という共有整数変数を作成することによってカウンタを初期化します。

public class myServlet extends HttpServlet {
   int thisMany;

   public void init (ServletConfig config) throws ServletException
   {
       super.init(config);
       thisMany = 0;
   }
}

これで、ほかの Servlet メソッドがこの変数にアクセスできるようになります。


破壊メソッドのオーバーライド
ログメッセージを書き込んだり、ガベージコレクション時に解放されないリソースを解放したりするには、クラスデストラクタ destroy() をオーバーライドします。destroy() メソッドは、Servlet 自体がメモリの割り当てから解放される直前に実行されます。詳細については、Servlet の API 仕様書を参照してください。

たとえば、上記の「初期化メソッドのオーバーライド」の例に基づいて、destroy() メソッドで次のようなログメッセージを書き込むことができます。

out.println("myServlet was accessed " + thisMany " times.¥n");


Service、Get、および Post メソッドのオーバーライド
リクエストが行われると、iPlanet Application Server は受信データを Servlet エンジンに渡してリクエストを処理します。リクエストにはフォームデータ、cookie、セッション情報、URL の Name-value ペアなどが含まれており、リクエストオブジェクトと呼ばれる HttpServletRequest タイプのオブジェクトによって処理されます。クライアントのメタデータは、レスポンスオブジェクトと呼ばれる HttpServletResponse タイプのオブジェクトとしてカプセル化されます。Servlet エンジンは、Servlet の service() メソッドのパラメータとして両方のオブジェクトを渡します。

HTTP Servlet 内のデフォルトの service() メソッドは、HTTP 転送メソッド (POST、GET など) に基づいてリクエストをほかのメソッドに転送します。たとえば、HTTP POST リクエストは doPost() メソッドに転送され、HTTP GET リクエストは doGet() メソッドに転送されます。これにより、Servlet は転送メソッドに応じてさまざまなリクエストデータ処理を実行できます。リクエストの転送は service() で行われるため、一般的に HTTP Servlet の service() をオーバーライドする必要はありません。その代わり、予想されるリクエストタイプに従って doGet()doPost() をオーバーライドします。

HTTP Servlet での自動転送は、HTTP 転送メソッドを備えている request.getMethod() の呼び出しに基づいています。iPlanet Application Server では、Servlet がデータを参照する前にリクエストデータが Name-value リストに前処理されているため、HTTP Servlet の service() メソッドをオーバーライドしても機能は失われません。ただし、これによって前処理されたリクエストデータに依存することになるため、Servlet の移植性は低下します。

リクエストへの返答に必要なタスクを実行するには、service() メソッド (汎用 Servlet) または doGet()and/or メソッドやdoPost() メソッド (HTTP Servlet) をオーバーライドします。多くの場合、EJB にアクセスしてビジネストランザクションを実行し、リクエストオブジェクトまたは JDBC ResultSet オブジェクト内で必要な情報を照合したあと、新たに作成されたコンテンツを JSP に渡してコンテンツのフォーマットとクライアントにへの配信を行います。

フォームを伴う多くのオペレーションで GET または POST オペレーションが使われるため、ほとんどの Servlet について doGet() または doPost() をオーバーライドします。次の例のように、両方のメソッドを実装して両方の入力タイプに備えたり、リクエストオブジェクトを中央処理メソッドに渡したりできます。

public void doGet (HttpServletRequest request,
                      HttpServletResponse response}
          throws ServletException, IOException {
   doPost(request, response);
}

HTTP Servlet におけるリクエストごとの負荷はすべて、適切な doOperation()メソッドで処理されます。このメソッドには、セッション管理、ユーザ認証、EJB や JSP のディスパッチ、および iPlanet Application Server の機能へのアクセスが含まれています。

Servlet が RequestDispatcher メソッドの include() または forward() を呼び出す場合は、リクエスト情報が HTTP の POST や GET として転送されなくなるので注意してください。つまり、Servlet が doPost() をオーバーライドする場合、呼び出し側の Servlet が HTTP GET 経由でデータを受け取ると、ほかの Servlet が doPost() を呼び出しても何も処理されません。このため、上記の例のように可能性のあるすべての入力タイプのルーチンを実装してください。RequestDispatcher メソッドは常に、service() を呼び出します。

詳細については、「プログラムによる Servlet の呼び出し」を参照してください。


パラメータへのアクセスとデータの保存

受信データはリクエストオブジェクトにカプセル化されます。HTTP Servlet の場合、リクエストオブジェクトのタイプは HttpServletRequest です。汎用 Servlet の場合、リクエストオブジェクトのタイプは ServletRequest です。リクエストオブジェクトは、属性と呼ばれるユーザ独自のリクエスト値を含む、すべてのリクエストパラメータを持っています。

受信リクエストのすべてのパラメータにアクセスするには、getParameter() メソッドを使います。次のようにします。

String username = request.getParameter("username");

リクエストオブジェクト内の値の設定および取得を行うには、それぞれ setAttribute()getAttribute() を使います。次のようにします。

request.setAttribute("favoriteDwarf", "Dwalin");

上記の例は、データを JSP に転送する方法を示しています。これは、JSP に暗黙的 Bean としてのリクエストオブジェクトへのアクセス権があるためです。詳細については、 「JavaBeans の使用法」を参照してください。


セッションとセキュリティの処理

Web サーバまたはアプリケーションサーバから見ると、Web アプリケーションは関連のないサーバヒットの連続です。数秒前に対話したばかりでも、ユーザがそのサイトにアクセスしたことがあるかどうかの自動認識は行われません。セッションは、アプリケーションの状態を記憶することによってユーザとの複数の対話を関連付けます。クライアントは各対話時に cookie を使って自己を特定します。また、cookie のないブラウザの場合は、URL にセッション識別子を入れることによって自己を特定します。

セッションオブジェクトは、表形式データ、アプリケーションの現在のステートについての情報、現在のユーザについての情報などのオブジェクトを格納できます。セッションに関連付けられたオブジェクトは、同じセッションを使うほかのコンポーネントから使用できます。

詳細は、第 12 章「ユーザセッションの作成と管理」を参照してください。

ログインに成功したら、標準オブジェクト内でユーザの識別情報を確立するように Servlet に指示する必要があります。この標準オブジェクトはセッションオブジェクトと呼ばれ、ユーザのログイン名や保存の必要がある補足情報など、現在のセッションに関する情報を保持しています。アプリケーションコンポーネントはセッションオブジェクトに対してクエリを実行し、ユーザ認証を取得できます。

アプリケーションに対して安全なユーザセッションを行うには、第 13 章「安全なアプリケーションの作成」を参照してください。


ビジネスロジックコンポーネントへのアクセス

iPlanet Application Server のプログラミングモデルでは、データベーストランザクション、ディレクトリトランザクション、複雑な計算などのビジネスロジックを EJB に実装します。request オブジェクトの参照は、指定されたタスクを実行するための EJB パラメータとして渡すことができます。

データベーストランザクションからの結果を JDBC ResultSet オブジェクトに格納し、フォーマットとクライアントへの配信を行うためにコンポーネントにオブジェクト参照を渡します。また、request.setAttribute() メソッドを使ってリクエストオブジェクトの結果を格納したり、session.putValue() メソッドを使ってセッションに格納したりできます。リクエストオブジェクトに格納されるオブジェクトは、リクエストが有効であるかぎり有効です。つまり、個別の Servlet スレッドだけに有効です。セッションに格納されるオブジェクトは、セッションが持続している間は存続します。これによって、多くのユーザ対話にまたがることができます。

JDBC リザルトセットは直列化できないため、クラスタ内の複数のサーバに分散させることはできません。したがって、リザルトセットを分散セッションに保存しないでください。詳細は、第 12 章「ユーザセッションの作成と管理」を参照してください。

次の例は、ShoppingCart という EJB にアクセスする Servlet を示しています。Servlet は、カートのリモートインタフェースをインポートしてからユーザのセッション ID をカートに割り当てることによって、カートに対するハンドルを作成します。カートはユーザのセッション内に保存されます。

import cart.ShoppingCart;
    
   // ユーザのセッションおよびショッピングカートを取得します。
   HttpSession session = request.getSession(true);
   ShoppingCart cart =
      (ShoppingCart)session.getValue(session.getId());

   // ユーザがカートを持っていない場合は新規に作成します。
   if (cart == null) {
       String jndiNm = "java:comp/env/ejb/ShoppingCart";
       javax.naming.Context initCtx = null;
       Object home = null;
       try {
          initCtx = new javax.naming.InitialContext(env);
          java.util.Properties props = null;
          home = initCtx.lookup(jndiNm);
          cart = ((IShoppingCartHome) home).create();
       }
        catch (Exception ex) {
       .....
       .....
       }
   }

Java Naming Directory Interface (JNDI) を使って Servlet から EJB にアクセスし、EJB へのハンドルまたはプロクシを確立します。次に、正規オブジェクトとして EJB を参照します。このとき、オーバーヘッドは Bean のコンテナによって管理されます。

次の例は、ショッピングカートのプロクシを検索する JNDI を示しています。

String jndiNm = "java:comp/env/ejb/ShoppingCart";
javax.naming.Context initCtx;
Object home;
   try
   {
       initCtx = new javax.naming.InitialContext(env);
   }
   catch (Exception ex)
   {
       return null;
   }
   try
   {
       java.util.Properties props = null;
       home = initCtx.lookup(jndiNm);
   }
   catch(javax.naming.NameNotFoundException e)
   {
       return null;
   }
   catch(javax.naming.NamingException e)
   {
       return null;
   }
   try
   {
       IShoppingCart cart = ((IShoppingCartHome) home).create();

}
catch (...) {...}

EJB の詳細については、第 4 章「Enterprise JavaBeans の紹介」を参照してください。


スレッドの処理

デフォルトでは、Servlet はスレッドセーフになっていません。通常、1 つの Servlet インスタンス内のメソッドは、使用可能なメモリの範囲内で同時に何回も実行されます。メソッドの実行は、それぞれ別のスレッドで行われますが、Servlet エンジンには Servlet のコピーが 1 つしか存在しません。

これによってシステムリソースの使用率が向上しますが、Java でのメモリ管理方法に起因する危険性があります。パラメータ (オブジェクトおよび変数) が参照によって渡されるため、別のスレッドが同じメモリ空間を上書きしてしまうことがあります。Servlet (または Servlet 内のブロック) をスレッドセーフにするには、次のどちらかを行います。

  • public synchronized void method() (メソッド全体) または synchronized(this) {...} (ブロックのみ) のように、すべてのインスタンス変数に対する書き込みアクセスの同期をとります。同期をとることによって応答時間が大幅に遅くなるため、ブロックだけの同期をとるか、または Servlet 内の同期が不要なブロックを記述してください。

    たとえば、次の Servlet には doGet() 内にスレッドセーフのブロックがあり、さらに mySafeMethod() というスレッドセーフのメソッドがあります。

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

       public class myServlet extends HttpServlet {

       public void doGet (HttpServletRequest request,
                              HttpServletResponse response}
                 throws ServletException, IOException {
           //前処理
           synchronized (this) {
              //このブロック内のコードはスレッドセーフです。
           }
           //前処理
           }

    public synchronized int mySafeMethod (HttpServletRequest request)
           {
           // このメソッド内で行われる処理はすべてスレッドセーフです。
           }
       }

  • SingleThreadModel を使ってシングルスレッドの Servlet を作成します。この場合、現在のディレクトリを基準に .tld ファイルが検索されます。シングルスレッドの Servlet を iPlanet Application Server に登録すると、Servlet エンジンは受信リクエストに備えて Servlet インスタンスを 10 個プールします。つまり、同じ Servlet の 10 個のコピーをメモリ内に用意します。このプール内の Servlet インスタンスの数は、iPlanet Application Server 固有の Web アプリケーション配置記述子 (DD) の number-of-singles 要素を別の数値に設定することによって変更できます。iPlanet Application Server 固有の Web アプリケーション DD のこの数値を変更するには、iPlanet Application Server 配置ツールを使います。iPlanet Application Server の Web アプリケーション DD の詳細については、第 11 章「配置のためのパッケージ化」、IPlanet Application Server 配置ツールのオンラインヘルプ、および『管理者ガイド』を参照してください。シングルスレッドの Servlet は、新規リクエストを処理するためにインスタンスの空きを待つ必要があるため、その負荷によって動作が遅くなります。ただし、ロードバランスが有効な分散アプリケーションでは、比較的ビジーでない kjs プロセスに負荷が自動的にシフトするため、これが問題になることはありません。

    たとえば、次の Servlet は完全なシングルスレッドです。

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

       public class myServlet extends HttpServlet
           implements SingleThreadModel {
           
     servlet methods...
       }


クライアントへの結果の配信

ユーザとの対話の最終作業はクライアントにレスポンスページを配信することです。レスポンスページは次の 2 つの方法で配信できます。


Servlet レスポンスページの作成
出力ストリームに書き込むことによって、Servlet 内で出力ページを生成します。出力のタイプによって推奨方法は異なります。

すべての出力を開始する前に、setContentType() を使って出力の MIME タイプを必ず指定します。次に例を示します。

response.setContentType("text/html");

単純な HTML などのテキスト出力の場合は、PrintWriter オブジェクトを作成してから println を使って書き込みます。次のようにします。

PrintWriter output = response.getWriter();
output.println("Hello, World
¥n");

バイナリ出力の場合は、ServletOutputStream オブジェクトを作成してから print() を使って書き込むことによって、出力ストリームに直接書き込みます。次のようにします。

ServletOutputStream output = response.getOutputStream();
output.print(binary_data);



Servlet が、PrintWriter または ServletOutputStream オブジェクトから JSP を呼び出すことはできません。





iPlanet Application Server と iPlanet Web Server を併用する場合は、setDateHeader() を使って出力ストリーム内で日付ヘッダーを設定しないでください。設定すると、サーバがクライアントに返送するレスポンスページの HTTP ヘッダー内の日付フィールドが重複します。これは、iPlanet Web Server によってヘッダーフィールドが自動的に設定されるためです。これに対し、Microsoft の Internet Information Server (IIS) では日付ヘッダーが追加されないため、手動で設定する必要があります。




JSP レスポンスページの作成
Servlet は次の 2 つの方法で JSP を起動できます。

  • RequestDispatcher インタフェースの include() メソッドは、JSP を呼び出し、JSP が返されてから対話処理を続行します。include() メソッドは、特定の Servlet 内で複数回呼び出すことができます。

    次の例は、include() を使った JSP を示しています。

       RequestDispatcher dispatcher =
          getServletContext().getRequestDispatcher("
    JSP_URI");
       dispatcher.include(request, response);
       ... //処理の継続

  • RequestDispatcher インタフェースの forward() メソッドは対話の制御を JSP に渡します。forward() を呼び出すと、Servlet は現在の対話の出力と無関係になります。つまり、特定の Servlet で forward() メソッドを呼び出すことができるのは 1 回だけです。



    PrintWriter オブジェクトまたは ServletOutputStream オブジェクトをすでに定義している場合は、forward() メソッドを使うことができないので注意してください。



    次の例は、include() を使った JSP を示しています。

       RequestDispatcher dispatcher =
          getServletContext().getRequestDispatcher("
    JSP_URI");
       dispatcher.forward(request, response);



    URI (Universal Resource Identifier) を指定して、呼び出す JSP を指定してください。このパスは、ServletContext の範囲内にあるパスを記述する String です。また、絶対パスを示す String 引数を取るリクエストオブジェクトには、getRequestDispatcher() メソッドもあります。このメソッドの詳細については、Java Servlet 仕様書バージョン 2.2 の第 8 章を参照してください。



JSP の詳細については、第 3 章「JavaServer Pages によるアプリケーションページの表示」を参照してください。


Servlet の配置記述子

Servlet の配置記述子は、iPlanet Application Server 配置ツールによって作成されます。手動でも作成することができます。これらの記述子ファイルは、Web アプリケーション の aRchive (.war)ファイル内にパッケージされています。aRchive ファイルには、メタデータとともに、Servlet を識別しそのアプリケーションの役割を確立する情報が含まれています。



WAR モジュール名は、.war拡張子ではなく、ファイル名の最初の部分によって識別されます。Application Server に配置する WAR モジュール名は、一意でなければなりません。これらのモジュールのファイル名には、Java パッケージ方式の命名規則を使ってください。Java パッケージ方式の命名規則を使えば、名前の衝突は発生しません。この命名規則は、iPlanet Application Server だけでなく、ほかの J2EE アプリケーションサーバでも使うことをお勧めします。



iPlanet Application Server のサンプルアプリケーションには、Servlet の配置記述子を作成する手順が含まれています。これらのサンプルアプリケーションは、install_dir/ias/ias-samples ディレクトリにあります。


要素

Servlet の配置記述子には、iPlanet Application Server 固有の要素だけでなく標準の J2EE 規定の要素があります。Servlet の配置記述子は、開発者、編成者、および配置者間で、Web アプリケーションの要素および設定の情報を伝えます。これらの要素の詳細については、第 11 章「配置のためのパッケージ化」を参照してください。


コンフィグレーションファイルの変更

配置記述子の設定を変更するには、配置ツールを使うか、またはエディタと Ant のようなコマンドラインユーティリティを組み合わせて使い、更新された配置記述子の情報を再構成し、配置します。


配置ツールの使用法

  1. EAR、WAR、または EJB JAR ファイルを開きます。

  2. 配置記述子を変更します。

  3. EAR、WAR、または EJB JAR モジュールを再配置します。

  4. アプリケーションサーバを再起動して変更した配置記述子の設定を取得します。


コマンドラインの使用法
Ant ベースの build.xml ファイルを使ってコマンドラインからアプリケーションおよびモジュールを再構成する例の詳細については、サンプルアプリケーション (install_dir/ias/ias-samples ディレクトリ内) を参照してください。

  1. 適切な配置記述子ファイル weblxml または ias-web.xml を手動で編集します。

  2. Ant ビルドコマンド (build war など) を実行して適切な EAR、WAR、または EJB JAR モジュールを再構成します。

  3. iasdeploy コマンドを使って EAR または WAR のファイルまたはモジュールを配置します。

  4. アプリケーションサーバを再起動して変更した配置記述子の設定を取得します。


iPlanet Application Server のオプション機能へのアクセス

数多くの iPlanet 機能の追加によって、iPlanet Application Server 環境での Servlet の使用が強化されます。これらの機能は公式の仕様書では規定されていませんが、一部の機能は Sun の標準に基づいており、将来の標準に準拠する予定です。

iPlanet Application Server の機能の詳細については、第 14 章「iPlanet Application Server の機能の活用」を参照してください。

iPlanet Application Server は、前バージョンモデルの iPlanet Application Server に基づいたより強力なセッションをサポートしています。このモデルは、Servlet 2.2 仕様に記述されているセッションモデルと同じ API を使っており、 iPlanet Application Server はこの API もサポートしています。分散セッションの詳細については、第 12 章「ユーザセッションの作成と管理」を参照してください。



Servlet の起動



Servlet を起動するには、URL を使ってアプリケーションページから直接アドレス指定するか、またはすでに実行している Servlet からプログラムで呼び出します。Servlet パラメータを確認することもできます。次の節を参照してください。


URL による Servlet の呼び出し

多くの場合、アプリケーションのページにリンクとして埋め込まれた URL を使って Servlet を呼び出します。この節では、標準の URL を使って Servlet を起動する方法について説明します。


特定のアプリケーション Servlet の起動

リクエストに応答する Servlet への URL リクエストパスは、いくつかのセクションから構成されます。各セクションは適切な Servlet を特定する必要があります。リクエストオブジェクトは、リクエストの URI パスを取得すると次の要素を公開します。

  • Context Path

  • Servlet Path

  • PathInfo

これらの要素の詳細については、Java Servlet 仕様書バージョン 2.2 の第 5.4 節を参照してください。

次のように、特定のアプリケーションの一部である Servlet をアドレス指定します。

http://server:port/IASApp/moduleName/servletName?name=value

表 2-2 は、URL の各セクションについて説明しています。


表 2-2    特定のアプリケーションに含まれる Servlet の URL フィールド  

URL 要素

説明

server:port  

リクエストを処理する Web サーバのアドレスおよびオプションのポート番号  

IASApp  

この URL が iPlanet Application Server アプリケーション用であることを Web サーバに示す。リクエストは、iPlanet Application Server の Executive Server に送信される  

moduleName  

Servlet のモジュール名 (サーバ全体で固有の名前)。moduleName はアプリケーションの一部として登録されたモジュールの AppPath/applicationName 下にあるディレクトリに対応する。これは Servlet と JSP が含まれている .war モジュール名を示し、その内容は .war モジュールの内容と同じ  

servletName  

XML ファイルに設定された Servlet の名前  

次のようにします。

http://www.my-company.com/IASApp/OnlineBookings/directedLogin


汎用アプリケーション Servlet の起動

次のように、汎用の Default アプリケーションの一部である Servlet をアドレス指定します。

http://server:port/servlet/servletName?name=value

表 2-3 は、URL の各セクションについて説明しています。


表 2-3    汎用アプリケーションに含まれる Servlet の URL フィールド

URL 要素

説明

server:port  

リクエストを処理する Web サーバのアドレスおよびオプションのポート番号  

servlet  

この URL が汎用 Servlet オブジェクトのものであることを Web サーバに示す  

servletName  

Web アプリケーションの XML ファイルの servlet-name 要素で指定された Servlet の名前  

?name=value...  

Servlet のオプションの Name-value パラメータ  

次のようにします。

http://www.leMort.com/servlet/calcMortgage?rate=8.0&per=360&bal=180000



/servlet パスを使って配置するすべての Servlet が、Default というアプリケーション名で配置される必要があります。また、/servlet で始まるリクエストを iPlanet Application Server に渡すには、Web サーバインスタンスの Servlet エンジンを無効にする必要があります。




プログラムによる Servlet の呼び出し

まず、URI を指定して、呼び出す Servlet を指定します。通常、これは現在のアプリケーションに対応する相対パスになります。たとえば、Servlet が Office という名前のコンテキストルートを持つアプリケーションの一部である場合、ブラウザから ShowSupplies という名前の Servlet への URL は次のとおりです。

http://server:port/IASApp/Office/ShowSupplies?name=value

プログラムによってほかの Servlet からこの Servlet を呼び出す方法は次の 2 とおりあります。

  • ほかの Servlet の出力を含めるには、RequestDispatcher インタフェースから include() メソッドを使います。このメソッドは、URI で Servlet を呼び出し、Servlet が返されてから対話処理を続行します。include() メソッドは、特定の Servlet 内で複数回呼び出すことができます。

    次のようにします。

       RequestDispatcher dispatcher =
          getServletContext().getRequestDispatcher("/ShowSupplies");
       dispatcher.include(request, response);

  • ほかの Servlet に対話制御を渡すには、RequestDispatcher インタフェースの forward() メソッドに Servlet の URI をパラメータとして使います。



    リクエストを転送した場合、forward() を呼び出すと、元の Servlet は現在の対話の出力とは無関係になるので注意してください。つまり、特定の Servlet で forward() を呼び出せるのは 1 回だけです。



    次の例は、include() を使った JSP を示しています。

       RequestDispatcher dispatcher =
          getServletContext().getRequestDispatcher("/ShowSupplies");
       dispatcher.forward(request, response);



    include()forward() を使って Servlet をプログラムで起動するメカニズム、または Servlet を URL から起動するメカニズムでは、<servlet-name> エントリ内だけでなく、配置記述子の XML ファイルに指定されている Servlet の URL パターンを使うことができます。たとえば、web.xml ファイル内の Servlet の XML エントリが次のような場合を検討します。

    <servlet-name>Fortune</ servlet-name>
    <servlet-mapping>
    <servlet-name>Fortune</ servlet-name>
    <url-pattern>/Business</url-pattern>
    </servlet-mapping>

    この場合、次のどちらかの方法で Servlet にアクセスできます。

    • http://server:port/IASApp/context_root/Fortune

    • http://server:port/IASApp/context_root/Business




Servlet パラメータの確認

Servlet に渡されたパラメータを確認できます。この機能により、iPlanet Application Server の応答時間を増やし、開発時間を短縮できます。

iPlanet Application Server はパラメータの確認用に指定されたクラスを呼び出すことができます。確認した結果に基づき、サーバは Servlet メソッドを呼び出すか、または Servlet への呼び出しを中止して、 ユーザをエラーページにリダイレクトできます。Servlet の配置時に、パラメータの確認クラスを用意し、配置ツールで指定する必要があります。どのパラメータが有効であることを指定できます。

パラメータの確認コードは、Servlet 内に存在する必要はありません。複数の Servlet が同じパラメータを受け入れる場合は、各 Servlet がそのパラメータが同じパラメータであるか確認する機能を使う必要があります。

配置ツールの Servlet 記述子の「IAS Params」タブでは、各パラメータに対して次の要素を指定できます。

  • パラメータの名前

  • 確認の必要性

  • 確認のために呼び出すクラスおよびメソッド

  • パラメータのフォーマット

  • パラメータの範囲

  • エラーの場合に表示するエラーページ


前へ     目次     索引     DocHome     次へ     
Copyright © 2002 Sun Microsystems, Inc. All rights reserved.

最新更新日 2002 年 3 月 6 日