BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース Java EE 6のWeb層:サーブレットが非同期をサポートし、拡張性が改善

Java EE 6のWeb層:サーブレットが非同期をサポートし、拡張性が改善

原文(投稿日:2010/01/15)へのリンク

多くのwebアプリケーションは、Apacheの Wicket、Java ServerFaces, Struts あるいはSpringMVCのようなフレームワークをベースに作られる。フレームワークを使うために、開発者は、アプリケーションのweb.xmlコンフィグレーション・ファイルにサーブレット、フィルタそしてリスナのようなフレームワークのアーティファクト(部品)を登録する。このために、大きくて、複雑なコンフィグレーション・ファイルになったり、汎用的なフレームワークのXMLとアプリケーション特有のXMLが混ざり合ってしまっている。Servlet 3.0の仕様の主目的は、web.xmlデプロイ用の記述ファイルを、マニュアルによる編集無しで、サーブレット、フィルタそしてリスナのデプロイができるようにすることであり、そしてweb.xmlファイルを別々のモジュールに分割する手段を提供することである。このために、Servlet 3.0の仕様は、アノテーション ベースのコンフィグレーション(@WebServlet, @ServletFilter と @WebServletContextListener)を追加し、web.xmlファイルをオプションにした。そしてwebフラグメント(XMLのコード片のこと)について新しい概念を導入した。

webフラグメントは、フレームワークの"お決まり"のXMLとアプリケーションのコンフィグレーション用の残りの部分とを分けるのに使え、アプリケーションが自己登録できるようになる。webフラグメントは、web-fragment.xmlという名前のファイルになければならず、webアプリケーションのクラスパス中のどの位置にあってもよいが、典型的には、フレームワークのjarファイルのMETA-INFディレクトリに置かれるだろう。XMLは、<web-fragment>要素で始まり、その後に、web.xmlの記述子と同じ要素を多く持つことができる。例えば :
 

<web-fragment>
	<filter>
		<filter-name>MyXSSFilter</filter-name>
		<filter-class> MyXssFilter</filter-class>
	</filter>
	<servlet>
		<servlet-name>myFrameworkServlet</servlet-name>
		<servlet-class> MyFrameworkServlet</servlet-class>
	</servlet>
	<listener>
		<listener-class> MyFrameworkListener</listener-class>
	</listener>
</web-fragment>

XMLフラグメントは、デプロイ中にコンテナによって処理され、最終的な記述子が組み立てられる。コンテナが、web.xmlファイルを組み立てる責任があるので、もしフレームワークのサーブレット、フィルタそしてリスナが特別な順番で呼び出される必要がある場合、問題が起きることになる。このような問題を避けるため、Servlet 3.0 APIは、配備記述子の絶対的と相対的の2つの順番付けをサポートしている。絶対的な順番付けを指定するには、web.xmlで <absolute-ordering>要素を使用する、すると以下のように動く:WEB-INF/libにある各jarには、META-INF/web-fragment.xmlファイル中に<name>要素を持つことにより、名前がつけられる。その場合、webアプリケーションのWEB-INF/web.xmlファイルは、順番に沿ってフラグメントの名前をリストする <absolute-ordering>要素を持つことができ、またいっしょに、オプションで、そのような名前を持たないjarを含めるか、そしていつ含めるかを特定するのに、<others/>要素を使うことができる。デプロイヤは、デプロイするのに信用できるjarのみを選んでリストできるので、予想外のデプロイを防ぐことができる。更に、順番付けにより、web-fragment.xmlファイルを発見する以上には、走査する必要の無いjarを排除できるので、アプリケーションのデプロイが早くなるはずである。最後に、もし、実稼働環境で、自己登録をまったく止めたければ、web.xmlファイル中の <metadata-complete>要素を使って、webコンテナにwebフラグメントではなく、アノテーションを探すように指示できる。

フラグメントをサポートし、代わりのコンフィグレーションの仕組みとして、アノテーションを利用する他に、フレームワークの共有のコピーをプラグインする能力も提供する。このフレームワークには、JAX-WS, JAX-RS そしてJSFがあり、ServletContainerInitializersを使って、webコンテナ上に作られている。これらは、jarサービスAPIを介して発見され、それらが扱える型のリストを明示することができる。WEB-INF/libにある、jarの中に存在する型のクラスは、ServletContainerInitializerに渡すことができ、それは、ServletContextListenerと同じように、プログラム的なコンフィグレーションAPIを使うことができる。

Servlet APIが始めて設計されてから、webアプリケーションを作る手法が、ずいぶんと変わってきて、サーバにバックグラウンドでHTTPリクエストし、非同期のweb技術を使うのが、広く普及したやり方になった。この一群のテクニックは、Ajax あるいは Web 2.0と一般に呼ばれ、webクライアント(例えばブラウザ)とwebサーバ間のトラフィックの様相に大きなインパクトをもたらした、ページ単位でやりとりするモデルより、ずっとクライアントは、サーバにリクエストを行っているのである。

もしサーバサイドのプロセスが、終了するのに長い時間かかると、状況は、更に悪くなる。例えば、枯渇したJDBCコネクッションのプールからの接続を待ったり、JMSキューからのメッセージを待ったりする場合である。サーブレットの中で待つのは、非常に効率が悪い、それは、スレッドと他の限りあるリソースを消費する、停止した動作である。Servlet 3.0は、スレッドがコンテナに戻り、他のタスクを実行できるように、リクエストを非同期に処理できる能力を提供する。リクエストで、非同期処理が開始すると、他のスレッドあるいは、コールバックにより、レスポンスが生成され、コールが終了する、あるいは、リクエストをディスパッチして、AsyncContext.dispatchメソッドを使って、コンテナのコンテキストで、スレッドは走れるようになる。

非同期のサーブレットは、非同期でないものとは、非常に動きが違うので、Servlet 3.0では、サーブレットが非同期のリクエストをサポートすることを示すために、asyncSupported=trueと明示しなければならない。サーブレット・フィルタも非同期と明示することができる。新しいServletRequestインターフェースを継承したメソッド群も非同期処理をサポートする。例えば、startAsync()は、AsyncContextオブジェクトを返すが、このオブジェクトは、メソッドをコールする際に、リクエストとレスポンスのオブジェクトを保存しておくのに使われる。この時点で、もとのリクエストに応えたスレッドは、他の動作に使える。更に、APIには、新しいリスナクラスAsyncListenerが加わり、非同期な動作が終了したり、タイムアウトが発生すると、通知する。AsyncContextクラスには、complete()メソッドがあり、これを使って、非同期動作が終了した後に、レスポンスを実行できる。AsyncListenerクラスには、dispatch()メソッドがあり、コンテナに非同期のリクエストを転送する。このため、JSPのような他のフレームワークが、レスポンスを生成できる。

いくつもの新しい技術や手法を導入したと同時に、Servlet 3.0の仕様は、もっと小さな改善をいくつも行った。例えば、HttpServletRequest は、ついにそのままで、multipart/form-dataのMIME形式をサポートするようになったし、Cookieクラスがあるタイプのクロスサイトスクリプティング攻撃を避けるために、"HttpOnly"クッキーをサポートするようになった。そして、サーブレットとフィルタをプログラムでコンテキストに加えられるように、ServletContext APIが更新された。

この記事に星をつける

おすすめ度
スタイル

BT