Javaを紐解くための重点キーワード
米持幸寿
日本アイ・ビー・エム
2000/10/10
2001/7/6改訂
Java Servlet(サーブレット) |
■サーブレットの生い立ち
Java Servletは、Webサーバ、つまりはHTTPサーバを、Javaアプリケーション・サーバに変身させるJavaテクノロジである。そのため、Java Servletは必ずといってよいほどCGIと比較される。
現在でも、かなりのWebプログラマーが、Perl/CGIによるアプリケーション開発を行っている。筆者の周りでも、Webアプリケーション開発のプロジェクトが始まってから十分な人数のJavaプログラマーが見つからず、「CGI なら慣れているから」という理由で、CGI開発を進めるケースがいまでも見受けられる。
CGIは、UNIXプログラマーにとって非常に分かりやすい構造だった。CGI プログラムは、UNIXでいうところの、いわゆる「フィルタ・プログラム=パイプ・プログラム」だからである。CGIプログラムは、基本的に1つのプロセスで動作する。入力として環境変数(GET方式/PUT方式)または標準入力(PUT方式)を使い、結果として標準出力を使うという点は、UNIX プログラマーにとって非常に受け入れやすい。また、コマンドプロンプトを使って動作確認もできるので、非常に便利だ。また、開発言語が UNIXプログラマーにはなじみの深いPerl であることも理由の1つであろう。
Java ServletとCGIの違いについて理解するために、まずはCGIについて簡単に説明しよう。図1はクライアントからのリクエストがCGIに対してのものではなかった場合のサーバ側の動作を説明している。
図1 クライアントからのリクエストがCGIに対するものでなかった場合 |
次の図2が、クライアントからのリクエストがCGIに対してのものだった場合のサーバ側の動作である。
図2 クライアントからのリクエストがCGIだった場合 |
しかしながらCGIには欠点があるといわれている。それは主に次のようなことである。
- プロセス起動のためパフォーマンスが悪い
- ステートレス(複数のリクエストにまたがってメモリ上でデータを維持できない)
- コンピュータの機種によってPerlの互換性がない
Java Servletではこれらを克服している。
■Java Servletの開発手順
Java Servletは、ユーザー・プログラムを作成するときに、HttpServletクラスを継承したクラスを作成する。ここでは、便宜上これをユーザー・サーブレットと呼ぶことにする。これは、JavaAppletと同じような思想だ。オブジェクト指向では当たり前のやり方であるが、オブジェクト指向が身に付いていない人には分かりにくいかもしれない。
ユーザー・サーブレットは、サーバ・プロセスである「サーブレット・エンジン」に、ユーザー・クラスとしてロードされ、基本的には1つの共通インスタンスを生成する。サーブレット・エンジンはそれ自身がJavaのプログラムである。該当サーブレットに対するHTTPリクエストは、このインスタンスに対してのスレッドとしてリダイレクトされる。これによって、HTTPリクエストの処理がユーザー・プログラムによって処理され、結果がブラウザに送られる(図3)。
図3 Java Servletでは、ユーザー・サーブレットがサーブレット・エンジンにクラスとしてロードされ、1つのインスタンスを生成する。クライアントからのHTTPリクエストがあると、インスタンスからスレッドが起動されて処理が行われる。処理結果はブラウザに送られる |
この方法だと、プロセスの起動や終了処理がなく、スレッドであるため高速で、使用するリソースも少ない。さらに、インスタンスは一度ロードされるとメモリ上に維持されるため、アプリケーションの状態を維持することも可能である。これによりステートフルな技術であるといわれている。さらに、Javaであることから、非常に高い移植性を発揮する。
サーバ・プロセスであるサーブレット・エンジンがユーザー・サーブレットを呼び出すルールは、基本的に次の順序で行われる。
- リクエストに対するサービス・メソッドが定義されているか確認する。例えば、GETリクエストに対してはdoGetメソッド、POSTに対してはdoPostメソッド、である
- doXXXメソッドが1つでも定義されており、リクエストに合致するメソッドが提供されていないとき、このリクエストはそのServletによって処理できないことを意味する。例えば、doPostメソッドはあるが、doGetメソッドのないServletを作った場合、そのServletはURL指定や <A HREF=> タグによって直接参照することはできない。必ずフォームを作成して呼び出す必要がある
- doXXXメソッドが1つもなく、serviceメソッドがあれば、それが呼ばれる
ユーザー・サーブレットはサーバに呼び込まれたとき、インスタンスを生成し、そのインスタンスが共通に使われることになる。共通に使われるため、スレッド間で共有できるようなものはインスタンス生成時に初期化しておきたい。これを行うためには、initメソッドを使う。これもAppletに似ているので、分かりやすいだろう。initメソッドには、ServletConfigオブジェクトが渡されることになっており、このデータを使ってサーブレットに外部データを簡単に渡すことができる。例えば、RDBにアクセスするときのJDBC-URLなどをここで渡す。ServletConfig は、サーブレットのクラスファイルと同じディレクトリにクラス名「.servlet」というファイル名でXML形式にて置く。また、終了処理も当然ながら必要だが、これはdestroyメソッドで行う。
以上を総括すると、サーブレット・プログラムの開発(コーディング)手順は以下のようにまとめられる。
- HttpServletを継承したクラスを作成する
- 必要に応じてinit、destroyメソッドを記述する(パラメータは決まっている)
- 必要に応じてservice、doGet、doPostといったメソッドを記述する(パラメータや例外は決まっている)
- コンパイルし、サーバの定められたクラスパス上に置く
|
旧来のJavaアプリケーション・サーバでは、サーブレットのクラスファイルはアプリケーション・サーバの特定のクラスパスに、JSP、HTML、JPG、GIFのようなコンテンツ・データはHTTPサーバのドキュメント・ルートに置かれるようにデザインされていた。
しかし、J2EE対応サーバでは、これらのファイルはすべて*.WAR(Web Application Archive)といわれるJARファイルに入れて配布、配置が行われることになった。今後、サーブレットなどを開発するときには、クラスファイルと同じディレクトリでファイルの書き込みを行うような行為は避けるべきである。
Java Servlet にはセッション管理機能が備えられている。本当の意味で、サーブレットのステートフルを支えているのは、このセッション管理機能である。Java Servlet の仕様は、Sun Microsystems社のJavaWebServer(JWS)で提供され、その後分離した仕様として公開された後、J2EEに吸収された。セッション管理はJWS 1.1 alpha時代から追加された考え方であり、システム(サーブレット・エンジン)がこの管理を行う。基本的な考え方は以下のようなものである。
HTTPリクエストは、基本的にセッションレスである。1回のリクエスト/レスポンスでセッションが終了し、それ以降は関係が維持されない。そのため、複数の画面で構成されるようなアプリケーションを開発するとき、それぞれの画面での持続性を維持する機能をHTTPリクエストより上層で提供する必要がある(図4)。
図4 HTTPリクエストは、基本的にはセッションレスである。HTTPには2つのリクエストが同じクライアントかどうかを確認する情報はない |
これを実現しているのがセッション管理である。セッション管理には、セッションIDといわれる自動生成されるストリングとセッション・オブジェクトといわれるクラス・オブジェクトが関連している。セッションIDによってWebブラウザとセッション・オブジェクトをひも付けし、セッション・オブジェクトに自由にデータを貼り付けることによってWebブラウザとユーザー・データを管理しようというものである。
セッションIDは基本的にWebブラウザのクッキーに保存される。あるブラウザが初めてアプリケーション・サーバにアクセスしてきたとき、セッション管理機構がセッションIDを生成し、クッキーに保存する。次回以降のアクセスでは、このクッキーを読み出すことにより、そのWebブラウザが前にアクセスにきたことのあるものであることと、どのセッション・オブジェクトを利用しているかを認識する(図5)。
図5 セッション管理の方法。基本的にセッションIDはWebブラウザのクッキーに保存される |
|
1回1回のHTTPリクエストは、スレッド処理としてServletに送られる。基本的には、同じインスタンスで、複数のWebブラウザからのHTTPリクエストが、スレッドとなって同時に処理される可能性がある。これらがどうやって別々のセッションデータを管理するのだろうか。
サーブレットの処理ルーチンとなるサービス・メソッド(service、doGet、doPostなど)には、パラメータとしてHttpServletRequest
と HttpServletResponseオブジェクトが渡る。そのリクエストを送ってきたWebブラウザとひも付けされたセッション・オブジェクトは、HttpRequest.getSession()によってリクエスト・オブジェクトのインスタンスから取得することができる。セッション・オブジェクトには、名前を付けたオブジェクトを自由に貼り付けたり、取り出したりできるので、これによってWebブラウザごとのセッションにまたがったデータをメモリ上で簡単に管理することができる。これには、putValue、getValue
メソッドを使う(図6)。
図6 putValue、GetValueメソッドを使ってWebブラウザごとのセッションにまたがったデータをメモリ上で管理することができる |
Javaを紐解くための重点キーワード |
- 実運用の障害対応時間比較に見る、ログ管理基盤の効果 (2017/5/9)
ログ基盤の構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。今回は、実案件を事例とし、ログ管理基盤の有用性を、障害対応時間比較も交えて紹介 - Chatwork、LINE、Netflixが進めるリアクティブシステムとは何か (2017/4/27)
「リアクティブ」に関連する幾つかの用語について解説し、リアクティブシステムを実現するためのライブラリを紹介します - Fluentd+Elasticsearch+Kibanaで作るログ基盤の概要と構築方法 (2017/4/6)
ログ基盤を実現するFluentd+Elasticsearch+Kibanaについて、構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。初回は、ログ基盤の構築、利用方法について - プログラミングとビルド、Androidアプリ開発、Javaの基礎知識 (2017/4/3)
初心者が、Java言語を使ったAndroidのスマホアプリ開発を通じてプログラミングとは何かを学ぶ連載。初回は、プログラミングとビルド、Androidアプリ開発、Javaに関する基礎知識を解説する。
|
|