ページの更新はもうたくさん:jQueryを使おう!
“不要なページの更新処理で苦しめてごめんなさい”これは私が構築に携わったWebサイトに掲載された弁明の句です。今年の初頭にjQueryについて学んだ直後に頭に浮かんだのがこの言葉でした。
jQueryは強力でありながら控え目なヒドイ名前のJavaScriptライブラリです。その簡潔さ、可読性の高さによって私は再びJavaScriptを書くことに目覚めました。その控え目さによってリッチな振舞い―例えばバックグラウンドでのフォーム送信―をWebアプリケーションの既存のコードに対するほんの少しの修正だけで簡単に追加できるのです。控えめであることはとりわけ大きなコード・ベースを扱っている際や、元の取れない広範囲なリファクタリングを行っている際に重要になります。私のボスは既存のサイトに対してちょっとした見栄えのよさを追加するだけのために4週間は与えてくれません。代わりに与えられるのは恐らく4時間だけで、このような場合にこそjQueryは役に立つのです。
簡単な例として、自動車のモデルに対する検索機能について考えてみましょう。入力フィールドに文字列を入力し、送信ボタンを押すと結果が表示されます。JSPは以下のようになるでしょう。
ユーザが自動車のモデル名を入力して送信ボタンを押すとページを更新する間画面全体が真っ白になった後、結果が表示されます。優れたユーザ・エクスペリエンスとは言えません。では、jQueryを使ってページ内の本当に変更が必要となる部分のみを更新させることによってこのユーザ・エクスペリエンスを向上させてみましょう。ページに対して以下の修正を行います。
- 検索フォームと検索結果を2つの別々のJSPに分けて、検索フォームを再表示することなく結果を独立して表示できるようにします。
-
<div>を使って検索結果を保持するためのプレースホルダを検索フォームに追加します。
- AJAXを使ってバックグラウンドで検索フォームを送信し、結果を<div>プレースホルダに表示するためのjQueryのコードを追加します。
修正後のコードは以下のようになります。
ユーザが自動車のモデル名を入力して送信ボタンを押すと検索結果の<div>だけが更新されます。ユーザ・エクスペリエンスが向上しました。しかもほとんどJavaScriptを記述していません。jQueryのスクリプト部分についてもう少し詳細に見てみましょう。
コードの意味は下記のようになります。
2行目 -- “ページが読み込みが完了したら”
3行目 -- “id='searchForm'であるフォームを選択してAJAX(バックグラウンドでの送信処理)を利用可能にします”
4行目 -- “GETではなくてPOSTを利用して”
5行目 -- “'searchResults'というidを持つDIVに結果を渡します”
jQueryのコードは行頭“$()”で始まり、常に操作するために“document”や“#searchForm”といった要素を選択します。jQueryはデコレータのように振舞い、AJAXによるフォーム送信、視覚効果、ドラッグ・アンド・ドロップなどといった好きな振舞いを追加することができるのです。
この例は数行のコードに込められた多くの機能を示しており、私がどうしてjQueryが好きなのかを表しています。デコレータによるアプローチは既存のWebアプリを拡張するのに最適なのです。既存のHTMLを書き換えるのではなく、既存のHTMLをデコレート(装飾)するのにjQueryを適用して新しい振舞いを追加するのです。
Spring MVCとXStream/Jettisonを使ってHTMLの代わりにデータを返す
最初の例ではjQueryをクライアント側で利用していました。しかしサーバ側は特に何も変わりありませんでした。尚も、ユーザがブラウザ上の何かをクリックしてサーバ側でリクエストを生成しHTMLが返される、という基本的なはそのままです。しかし、もしサーバがHTMLの代わりにJSONやXML形式のデータを返すことができるとしたらどうでしょう。
レンダリング可能なHTMLではなくデータを返すことによってクライアントは結果をキャッシュすることが可能になります。それによってサーバへのリクエストを削減することができます。データはHTMLと比べて簡潔な可能性があります―これによって(サーバが)返す結果のサイズも削減することができるのです。次の例を見て下さい。
通常のフローでは、ユーザとブラウザの作用によってサーバ側で3つのリクエストが生成されます。では、サーバがHTMLの代わりにデータを返すように最適化したフローを見てみましょう。
最適化したフローでは、ユーザの3つの動作によってサーバでは1つのリクエストだけが生成されます。
サーバはいろいろな形式のデータを返すことができます。そしてそれは状況に応じて選択します。以下にいくつかの選択肢について選択のポイントをまとめました。
サーバが返す形式 | 用途 | 使用頻度 |
HTMLページ全体 | 初期表示 | 低 |
HTMLの断片 | サーバ側でのレンダリングの方が簡単であるか必須である場合。例えば<displaytag> |
低 |
JSONB { "car": { "id": "5", "make": "Acura", "model": "MDX" } } |
多くのサーバ・レスポンスに適用することができる一般的なデータ形式。簡潔でJavaScriptで扱い易い。 | 高 |
XML <car id="5"> <make>Acura</make> <model>MDX</model> </car> |
JSONで表現するのが難しい複雑なデータ構造。JSONでは要素しかないが、XML構造には要素と属性がある。 | 低 |
サーバがJSONデータを返す例のコードを見てみましょう。元の自動車のモデル検索の例を修正してmake(メーカー)とmodel(モデル)のドロップ・ダウンを含んだページに変えてみましょう。ユーザがメーカーを選択すると、選択したメーカーのモデルが読み込まれます。続いてユーザがモデルを選択すると、そのモデルの入手可能な年式が表形式で表示されます。
まずサーバ側から見てみましょう。Spring MVCをXStreamやJettsionと一緒に使ってどのようにJSONデータを扱ったらいいのかを確認してください。まずSpring MVCコントローラを作ります。
1行目 ― @ControllerアノテーションによってSpring MVCに対してこのクラスを、察しのように、コントローラとして扱うことを示します。
4行目 ― @RequestMappingアノテーションによってリクエストURLとハンドラ・メソッドをマッピングします。
6行目 ― carselector.jspにマッピングするModelAndViewオブジェクトを“carselector”という名前で生成します。
7行目 ― “makeList”というキー名でメーカーのリストをModelAndViewに追加します。このオブジェクトは${makeList}という記述でJSPから参照することができます。
11行目 ― もう一度@RequestMappingアノテーションによってリクエストURLとハンドラ・メソッドをマッピングします。
12行目 ― @RequestParamアノテーションはリクエスト・パラメータをメソッドの引数にマッピングします。
13行目 ― このModelAndViewは私が作成したJsonViewという簡単なJSONレンダリングをするViewクラスを使って生成します。Spring MVCではかなり簡単に独自のviewを作成することがします。JsonViewクラスはXSteamがフックするポイントになります。
14行目 ― JsonViewが必要とするキー名でモデルのリストをModelAndViewに追加します。
まとめると、コントローラは“carselector.html”と“models.html”という2つのURLに対して応答することになります。“carselector.html”というURLに対しては、通常のJSPビューを通してHTMLページをレンダリングします。では、JsonViewクラスについて見てみましょう。このクラスは“models.html”への要求に対してJSON形式のデータを作成して返します。
4行目 ― XMLの代わりにJSONを出力するためにJettisionMappedXmlDriverを使ってXStreamを初期化します。
6行目 ― Spring MVC Viewのクラスはrender()メソッドを実装しなければなりません。
9行目 ― コントローラで生成されたデータをモデルから取り出します。
11行目 ― (メソッド名のtoXMLに反して)JSON形式のデータを生成します。
たったこれだけです。この他にもXStreamにはドメイン・オブジェクトやデータ転送オブジェクトに付加してどのようにJSON形式にレンダリングしたらいいのかを伝えるヒントを与えるためのアノテーションも含まれています。ただし、通常ライブラリは最小限の設定だけで機能します。
さて、これでサーバ側はJSONを生成するようになりましたが、クライアントはどうでしょう?この質問に対する答えとして再びjQueryを見てみましょう。ハンドリングしなくてはならないイベントが2つあったことを思い出して下さい。“make”ドロップダウンを選択すると“model”ドロップダウンが生成されます。モデルのドロップダウンロを選択すると年式の一覧表が生成されます。イベント・ハンドラを設定するためにjQueryに用意されているready関数を見てください。
“select[name^=make]”という表記法はCSSセレクタのようにも見えます。というのも、jQueryのセレクタが実はCSSセレクタのスーパー・セットだからです(ちょうどCSSと正規表現の間の子ができたような感じです)。このような表記法はとても強力で、一つもしくは複数の要素を同時に選択することができます。今回の例でいうとこの表記は“name属性が'make'という値である<select>要素を選択してchangeイベントにloadModels関数をバインドする”と解釈されます。ユーザがドロップダウンから値を選択するたびにブラウザによってchangeイベントが生成され、loadModels関数が実行されます。
続いてイベント・ハンドラの一つを見てみましょう。
2行目 - getJSONメソッドはAJAXリクエストを生成しサーバからJSON形式のデータが返されるのを待ちます。このメソッドには3つのパラメータがあります。リクエストURL、任意のリクエスト・パラメータ、そしてサーバからの応答の際に実行されるコールバック関数です。
4行目 - コールバック関数はクロージャです。JavaScriptのクロージャはJavaにおける匿名内部クラスに似ていて、コールバック関数として利用するのに向いています。この関数はサーバから返されるJSONをパラメータにとる必要があることに注意してください。
6行目 - ここまでくるとこの例で扱っているJSONの構造について少し知っておく必要があるでしょう。この例ではmodelデータは下記のような構造をしています。
6行目のコードは、"それぞれのmodelに対して"という意味です。
7,8行目 - それぞれのmodelに対してHTMLの要素を作成します。
10行目 - name=modelである<select>要素を選択して<option>のリストを作成したものに置き換えます。
たったこれだけの最小限のJavaScriptで以下のようなことが出来るようになりました。
- イベント・ハンドラの登録
- JSON形式のデータを非同期に取得
- ドロップダウンの選択項目をJSON形式のデータを基に置換
とても強力な性質で、これは私がjQueryをとても好きな理由の一つです。では、キャッシュについてはどうでしょう?簡単なことにgetJSONを呼び出す前に"if"分を追加して既に結果がキャッシュ内に存在しているか確認するだけでいいのです。jCacheと呼ばれるよく出来たjQueryプラグインを使うこともできます。
結論
jQuery + Spring MVC + XStream/Jettisonはデータとプレゼンテーションをきれいに分離したWebアプリケーションを素早く開発するためのとても優れた組み合わせです。これによって向上したユーザ・エクスペリエンスを提供し、潜在的にパフォーマンスも改善します。同じことを成し遂げる他の高品質なフレームワークはありますか?勿論あります。しかし、私はjQuery, Spring MVCそしてXStream/Jettisonの組み合わせが好きです。そしてこの組み合わせのどのライブラリもそれぞれの市場における最善のものであると考えています。
ここで用いた例のコードはこちらからダウンロードできます。(リンク)
著者について
最初のJavaの仕事である、Java1.0.2での帳票作成、にアサインされて以来Joel Confino氏はJava技術に入れ込んでいます。分散システム、様々なWebアーキテクチャ、そして過去10年に及ぶJEE設計とプログラミングなどに従事してきました。Confino氏は多くの金融サービスや製薬会社のコンサルティングをし、彼らがビジネスを拡張し洗練されたWebベースのシステムで顧客との距離を縮めるためにJavaを利用するを助けてきました。氏は現在JavaアーキテクトとしてChariot Solutions社に所属しています。
Chariot Solutions, LLCについて
Chariot SolutionsはJavaやオープン・ソース技術を用いたアプリケーション開発やシステム構築に特化したITコンサルティング・ファームです。Chariot社のコンサルタントには全米でも有数のソフトウェア・アーキテクトが在籍していて、その全員が珍しい組み合わせの深い専門的技術、業務知識を有していて、自分達の仕事に愛着を持っています。Chariot社のコンサルティング・チームはChariot社をあらゆる規模の会社にとってミッション・クリティカルなシステムの設計、製造、デプロイ、構築、サポートそしてチューニングをする際の最善のパートナーとなるべく成長させました。Chariot社のWebページ(リンク)をぜひ訪問してください。
原文はこちらです:http://www.infoq.com/articles/First-Cup-Web-2.0-Joel-Confino
(このArticleは2008年9月15日に原文が掲載されました)