Fujitsu The Possibilities are Infinite

 

J2EE入門
2章:サーブレット

[索引]  サーバサイドシステムの種類 |  サーブレット/JSPとASP.NETとの比較 |  サーブレットの特徴 |  サーブレットのライフサイクル |  サーブレットプログラムの骨組み |  セッション管理 

2.1 サーバサイドシステムの種類


図解: サーバサイドシステムの種類

サーバサイドシステム

サーブレットはサーバサイドシステムの一種です。 サーバサイドシステムは一言で言えば、クライアントからの要求(request)をサーバのプログラムで処理して、その結果を応答(response)として返すシステムです。 クライアント側にはインターネットエクスプローラ(IE)やネットスケープなどのWebブラウザが使われます。 サーバ側のシステムにはサーブレットの他もいくつかの種類があります。 ここではサーブレットの理解を深めていただくために、主なサーバサイドシステムを紹介します。

CGI(Common Gateway Interface)

CGIは最も古くから実用化され今でも使われているサーバサイドシステムです。 CGIはもともとサーバと外部アプリとの対話のために作られた仕組みで、特に言語には制約がありません。 CGIは独立なプロセスとして動作するので、プログラムがクラッシュしてもサーバには影響を与えません。

CGIはサービス要求を受けるたびに生成されるので応答を返すまでに時間がかかります。 同時アクセスがあるとその数だけプロセスを生成するのでメモリが多く必要です。 言語としては、Perlがよく使われますが、Perlはインタープリタなので、実行前に翻訳が必要となり、さらに応答に時間がかかることになります。

ASP.NET(ASP dot NET)

マイクロソフト社はCGIの性能問題を解決すべく、同社が提供するWebサーバであるIIS(Internet Information Server)にISAPI(Internet Server Application Program Interface)という機能拡張を導入しました。 ISAPIはサーバと同じプロセス内で実行されるので高速です。 しかし、ISAPIがクラッシュするとサーバ全体がダウンしてしまうことがありました。 そこで、ISAPIに代わる方法としてASP(Active Server Pages)を開発しました。 最近ではさらに機能を拡大したASP.NETが提供され広く普及しています。

PHP(Hypertext Preprocessor)

もともとCGIのマクロ的な位置付けで始まった、関数を主体とした平易な言語です。 HTMLのタグを拡張して処理を記述するという手法はASPやJSPと同じです。 手軽にサーバサイドシステムを開発することができますが、構造がフラットなので大規模システムには向きません。

JSP/サーブレット

Java技術を利用した本格的なサーバサイドシステムです。 当初はJava言語そのものに近いサーブレットだけでしたが、後に画面処理が得意なJSP(Java Server Pages)が提供され、特に中~大規模システムではこれらを組み合わせて使うことが多くなっています。 ASPのようにOSがWindows限定ではないので、信頼度の高いUNIXでのシステム構築が可能です。

2.2 サーブレット/JSPとASP.NETとの比較


図解: サーブレット/JSPとASP.NETとの比較

サーブレット/JSPとASP.NET

サーブレット/JSPとASP.NETの内容をまとめておきます。 画面と業務ロジックを分けて開発する考え方は双方同じです。 サーブレット/JSPはOSは選べるが言語はJavaに固定、逆にASP.NETは言語は選べるがOSはWindowsが主体です。 推進の仕方も、仕様やソースを公開して大勢の英知を集めるSUNの方式と、巨大な資本を集中させて強力に開発を進めているMSの方式は対照的です。

2.3 サーブレットの特徴


図解: サーブレットの特徴

特徴

サーブレットの主な特徴を示します。

プラットホーム非依存

前述のようにサーブレットはWindows、UNIX、Linuxなど複数のOS上で動作します。 これはサーブレットだけでなく、Javaのプログラムの大きな特徴です。

マルチスレッド

1つのインスタンス(プログラム実体)で複数のリクエストを並行して処理することができます。 このとき各リクエストを処理する単位がスレッドです。 同様な概念としてタスクがありますが、タスクは使用する変数の値など、プログラムが動作する際の環境を入れ換えるのに対し、スレッドは周りの環境はそのままにして制御の流れだけを切り換えます。 したがってマルチスレッドは軽快で高速です。 しかし、別のスレッドのプログラムにメモリの内容を破壊されないようにするなど、プログラムを作る上で一定の配慮が必要です。 この考え方をスレッドセーフと言います。 サーブレットのプログラムはスレッドセーフに作らねばなりません。 このようなマルチスレッド動作も、サーブレットだけでなく、Javaのプログラム一般の特徴です。

ライフサイクル

一度起動されたサーブレットは、そのままメモリ上に常駐し、次のリクエストを待つ状態になるため、2回目以降のリクエストでは早く処理を行えます。 また起動時にのみ実行されるメソッドや、最後に破棄されるときに実行されるメソッドなどが決まっています。 このようにサーブレットにはライフサイクルがあります。

セッション管理

本格的な業務処理を行おうとすると、一問一答の処理しかできないHTTPだけでは困難であり、セッション管理が必要になります。 サーブレットでは、クッキーを利用してプログラマーに意識させない形でセッション管理機能を実現しています。

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


図解: サーブレットのライフサイクル

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

サーブレットにはライフサイクルがあり、それに従ってプログラムが動作します。 サーブレットは、プログラマーが記述したメソッドをコンテナ(サーブレットのエンジン部分)がライフサイクルに従ってメソッドを呼び出すことで処理が進みます。 このようにコンテナがユーザのブログラムを順次呼び出すやり方をコールバック方式と呼びます。

最初のリクエスト

  • 最初のリクエストが来るとサーブレットがメモリにロードされます(A)。
  • 初期化処理が実行されプログラマーが書いたinitメソッドが呼ばれます(B)。
  • 引き続いてサービス処理が実行されプログラマーが書いたserviceメソッドが呼ばれます(C)。
  • 実行が終了すると要求待ち状態になり、次のリクエストを待ちます。

2度目以降のリクエスト

2度目以降のリクエストでは、サービス処理が実行され、serviceメソッドが呼ばれます(C)。 処理が終わると要求待ち状態になります。 初期化が不要なためより早く処理が行えます。

サーブレット破棄の指示

プログラマーが書いたdestroyメソッドが呼ばれた後、消滅処理が実行されてメモリから消えます(D)。

<<参考>> コールバック方式


図解: コールバック方式

コールバック方式

通常のプログラムでは、全体はプログラマーが作り、特定の機能をライブラリ(部品)に頼るという構造が普通です。 これに対し、全体の枠組みが提供され、その一部をカスタマイズして望む機能を実現するやり方があります。 これをコールバック方式と言います。 このやり方は英語では Don't call us. We'll call you. と表現され、高慢なプロデューサの言葉になぞらえて「ハリウッドの法則」と呼ばれることがあります。

Javaでは「継承」や「オーバライド(再定義)」の機能により、このコールバックがうまく実装できます。 コールバック方式では一般に開発量が少ないので生産性が向上します。 しかし、コールバック方式では実現できることは限られます。

2.5 サーブレットプログラムの骨組み


図解: サーブレットプログラムの骨組み

サーブレットプログラム

サーブレットプログラムはコールバック方式で動作します。 コールバック方式の枠組みとして使用するのはHttpServletと言うクラスです。 枠組みの指定はHttpServletを継承することによって行います。 実際に継承するにはextends HttpServletと書くだけでよいのです。 継承さえしておけばプログラマーはHttpServletの内容をあまり意識する必要はありません。 initやdoGetなどのメソッドの使い方さえ心得ていればよいので、簡単にプログラムを書くことができます。

主なメソッド

  • initメソッド
    Servletのシステムが起動されたときに一度だけ呼ばれます。 データベースのオープンの処理など、最初に一度だけ実行する作業を記述します。
  • serviceメソッド
    クライアントからの要求があるたびに呼ばれます。 応答を作成する処理を記述します。
  • doGetメソッド、doPostメソッド
    HttpリクエストにはGetとPostの2種類があります。 それぞれが来たときに呼ばれます。 通常はServiceメソッドは定義せずに、こちらのメソッドを定義します。
  • destroyメソッド
    サーブレットが破棄状態になる前に一度だけ呼ばれます。 データベースのクローズ処理などを記述します。 このメソッドも必要がなければ定義しなくてもかまいません。

このプログラムの動作

このプログラムはクライアントからのリクエストで起動されます。 リクエストにはパラメーターとして操作者の名前が含まれています。 このプログラムはそれを読み取り、HTML文を組み立てて返す処理を行っています。

2.6 セッション管理


図解: セッション管理

HTTPプロトコルはステートレス

前に述べたようにHTTPプロトコルはステートレスです。 すなわち、要求と応答が一問一答で、前回の状態は記憶されません。 これに対し、状態を覚えている通信をステートフルと言います。

情報の記憶が必要なとき

一般のWebでは一問一答方式で十分です。 例えば、ある会社のサイトからその会社が扱っている全製品のページ、詳しい製品リストのページ、さらに個々の製品の詳細情報のページというように探しに行くとします。 このとき、ユーザーは階層をどんどん追っているつもりになるかも知れませんが、毎回あらたなページのアドレスをもらっているだけで、サーバが前の画面のことを覚えている訳ではありません。 その証拠にURLが分かれば最初から一度で詳細情報のページに到達することができます。

ところが、これではすまないときがあります。 例えば、認証が必要なページにアクセスしたとします。 パスワードを照合し認証が成功したら、サーバはページの内容を応答として送出します。 ここでサーバとクライアントの関係が終わってしまうと、次の認証が必要なページを見ようとしたらまた認証を行わなければなりません。 これでは大変なので、このような時はサーバはクライアントとの結びつきを覚えておく必要があります。 この結びつきがセッションです。 セッションを実現するための処理をセッション管理と言います。

セッションIDによる管理方式

Webブラウザにはクッキーと呼ばれる情報格納領域があります。 クッキーに直接情報を書くことも可能ですが、サーブレットではクッキーにはセッションIDだけを書く方式でセッション管理を行います。 セッションIDはセッション開始時にサーブレットが発行する固有の番号です。 同じクライアントでも接続するタイミングにより異なった値が割り当てられます。 Webブラウザはこれを受け取るとクッキーに書いておき、その後の応答としてそのIDを付加してサーバに送ります。 サーブレットはIDごとにユーザ固有セッション情報を格納してあるので、IDでその情報を検索して前回の続きの処理を継続できます。 セッションIDの発行やクッキーへの書き込みはプログラマーが意識しなくても自動的に行ってくれます。

非表示データを利用する方式

クッキーを使わずにセッション情報を引き継ぐ方法として、HTMLの<FORM>タグにhidden(非表示)属性で情報を書いておくやり方があります。 CGIではこの方式が使われますが、セキュリティ上問題の多いやり方です。

設計のポイント

セッション情報は、リクエストをまたいで保存されるのでサーバのメモリ負荷を増大させます。 1つ1つは大したことがなくても大規模なシステムでは同時接続数に大きく影響します。 そのため、必要最小限のもののみをセッションデータとする、必要になるまでセッションは作らない、不要になったらすぐに開放するなどの注意が必要です。

<<参考>> クッキー


図解: クッキー

クッキー(cookie)の仕組み

Webブラウザにはサーバからの指示でちょっとした情報が書き込めるクッキーと呼ばれる情報格納領域があります。 セキュリティ確保のため制約は多いですが便利な仕組みです。 サイズは1つ4KB以下、1台のサーバが1台のクライアントに格納できるのは20個以下などの制限があります。

また、クライアントのユーザーがクッキーの使用を拒否することもできます。 サーブレットはそれに備えてURLにセッションIDを付加するURL書き換え方式を準備しています。