連載
» 2011年01月17日 00時00分 公開

iPhoneで動かす業務用Webアプリ開発入門(3):JavaサーブレットとJSON-libでできるiPhone向けAjax (1/2)

業務用アプリのiPhone対応経験を基に、iPhoneで動かすための、業務で使えるWebアプリケーションを作成するときのコツを紹介します

[石田健亮,株式会社ドリーム・アーツ]

 今回は、いよいよWebアプリを作ってみたいと思います。まずAjaxの基本をおさらいし、後半で、前回の「iUIで始めるiPhone用Webアプリ開発の基礎知識」で紹介した「iUI」に組み込みます。

開発者なら当然知っているであろう、Ajaxの基本

 iPhoneでもAjaxの使い方はPC向けWebブラウザと一緒で、XMLHttpRequestオブジェクトを使ってWebサーバからXMLJSONなどのコンテンツを取得して、それを基にJavaScriptHTMLを加工するという流れです。

 リンクをクリックしたら、画面の一部(「replaceIt」というIDの<div>要素)にサーバで生成されるコンテンツを非同期で表示するには、以下のようなコードです。

 1: <a href="javascript:void(0)" onclick="clickDiv()">クリックしてください</a>
 2: <div id="replaceIt"></div>
 3: <script>
 4: function clickDiv() {
 5:     var xhr = new XMLHttpRequest();
 6:     xhr.open("POST", "http://【Ajaxのサーバ側URL】", true);
 7:     xhr.onreadystatechange = function() {
 8:         if (xhr.readyState == 4) {
 9:             document.getElementById('replaceIt').innerHTML = xhr.responseText;
10:             xhr = null;
11:         }
12:     }
13:     xhr.send();
14: }
15: </script>

 このコードを解説します。

  • 5行目:XMLHttpRequestのインスタンスを作成
  • 6行目:open(【メソッド】,【URL】,【非同期フラグ】)メソッドでURLなどを指定。非同期フラグの値として「true」を指定すると、13行目のsend()メソッドの呼び出しは非同期通信となる
  • 7〜12行目:サーバからレスポンスが返ってきたときにクライアント側で実行する処理を関数オブジェクトとして定義している。ここでは「replaceIt」というIDのタグの中身をサーバからのレスポンスで置き換えている
  • 13行目:リクエストを発行。6行目のopen()で非同期フラグを指定しているので、この呼び出しは完了を待たずに、すぐに終了する

もはや定番! JSONによるAjaxのレスポンス

 先ほどの例では、Ajaxのサーバ側のサポートからはHTMLの断片が返ってくることを期待して、innerHTMLを使って<div>〜</div>の中に直接コンテンツを流し込みました。

 しかし、XMLHttpRequestを使ったAjax呼び出しは、別にXMLでなくても、どんなテキストデータも取り扱えます。アプリケーションを作成するには、innerHTMLを使う方法の他に、JSON形式でレスポンスを返して、iPhoneの側では直接JavaScriptのオブジェクトとして利用する方法が便利です。

 JSONとは「JavaScript Object Notation」の略で、JavaScriptのソースコードをそのままテキスト文字列として送信し、受信側でeval()関数を使って、その文字列を評価することでオブジェクトとして利用できるようにする仕組みです。

 JavaScriptで、JSON文字列を評価するには、eval()関数を直接使ってもいいのですが、eval()をセキュリティ的に安全に使うのはかなり難しいので、「json2.js」を使うのがいいでしょう。

 JSON形式でレスポンスを受け取る場合は、以下のようなコードで記述します。

 1: <script type="text/javascript" src="js/json2.js"></script>
 2: <a href="javascript:void(0)" onclick="clickDiv()">クリックしてください</a>
 3: <div id="replaceIt"></div>
 4: <script>
 5: function clickDiv() {
 6:     var xhr = new XMLHttpRequest();
 7:     xhr.open("POST", "http://【Ajaxのサーバ側URL】", true);
 8:     xhr.onreadystatechange = function() {
 9:         if (xhr.readyState == 4) {
10:             var obj = JSON.parse(xhr.responseText);
11:             document.getElementById('replaceIt').innerHTML = obj.message;
12:             xhr = null;
13:         }
14:     }
15:     xhr.send();
16: }
17: </script>

 先ほどの、innerHTML版との違いは、10行目でサーバからのレスポンスをJSON文字列としてパースしてJavaScriptオブジェクトにしているところです。

 この例では、以下のように「message」という名前のプロパティを持つオブジェクトがサーバ側から送信されています。

{
  "message": "このメッセージが表示されます。",
  "other1" : "その他の文字列1",
  "other2" : "その他の文字列2"
}

Java BeansをJSONに変換する「JSON-lib」

 Ajaxのサーバ側では、iPhoneからのXMLHttpRequestによる呼び出しに応答して、HTMLやJSONの文字列を生成するようなアプリケーションを作成します。このとき XMLHttpRequest から発行されるリクエストでも、“HTMLページのためのCookie”と同じCookieが送信されてくるので、一般的なWebアプリケーションと同じセッション管理の仕組みを利用できます。

 プラットフォームとしては、CGIでも、サーブレットでも、ASP.NETでも使い慣れたWebアプリケーションプラットフォームを利用するといいでしょう。

 筆者が業務で作っている「Shopらん」「店舗matic」ではJavaを使っているので、本稿ではJavaを使った場合について解説します。

 Javaを使ってAjaxのサーバ側を実装するときHTMLでの出力はいつもと同じやり方でOKです。JSONで出力するには、自分でJSON文字列を生成せずに、JavaScriptで使いたいオブジェクトをJava Beansとして実装して、それを「JSON-lib」というライブラリでJSONに変換する方法が簡単です。


 先ほどの例ですと、まずJavaScriptに渡したいデータをまとめた以下のようなクラスを作ります。

public class SampleObject {
    private final String message;
    private final String other1;
    private final String other2;
 
    public SampleObject(String message, String other1, String other2) {
        this.message = message;
        this.other1 = other1;
        this.other2 = other2;
    }
 
    public String getMessage() {
        return message;
    }
 
    public String getOther1() {
        return other1;
    }
 
    public String getOther2() {
        return other2;
    }
}
SampleObject.java

 そして、このクラスのインスタンスをJSONに変換して、サーブレットのレスポンスストリームに書き出します。

 1: response.setContentType("application/json; charset=UTF-8");
 2: response.setHeader("Cache-Control", "private");
 3: SampleObject obj = new SampleObject("このメッセージが表示されます。",
        "そのほかの文字列1",
        "そのほかの文字列2");
 4: JSONObject json = JSONObject.fromObject(obj);
 5: response.getOutputStream().write(json.toString().getBytes("UTF-8"));

 このコードを解説します。

  • 1行目:サーブレットの出力としてJSON形式の文字列を出力することを宣言
  • 2行目:JSON文字列をキャッシュしないように指定
  • 3行目:JavaScriptに渡すオブジェクトを生成。実際のアプリケーションではここでさまざまなデータを生成する
  • 4行目:自前のJava Beansを、JSON-libのインスタンスに変換
  • 5行目:JSON文字列に変換して、それをレスポンスストリームに書き出している

 この例では、文字列のみを出力していますが、そのほかにもいろいろなタイプのオブジェクトをJSONに変換して、JavaScriptで利用できます。

 基本的には、以上の動作の組み合わせです。

 試しに、「Shopらん」の内部で、実際にiPhoneとWebサーバの間でやりとりしている様子をキャプチャしてみました。このリクエストは表示するアカウントのリストを取得するためのものです。

 こうしたAjaxリクエストを組み合わせてiPhone向けのWebアプリケーションは作られています。

GET https://some-domain.shoprun.jp/h2/STRMobileViewAPI.do?func=favStores HTTP/1.1
Cache-Control: max-age=0
Referer: https://some-domain.shoprun.jp/h2/STRMobileView.do?v=1.2.10&lang=ja
User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7
HTTPリクエスト
HTTP/1.1 200 OK
Server: Apache
Cache-Control: private
Content-Encoding: gzip
Content-Length: 203
Content-Type: application/json;charset=UTF-8
 
{"FavoriteStores":[{"accountId":"635ba844-845e-425c-a057-4e5085696ec9","disabled":false,"loginId":"ebisu","name":"恵比寿店","type":9},{"accountId":"f8fdb7a8-b22b-4505-9b6e-72fa21a87541","disabled":false,"loginId":"hiroo","name":"広尾店","type":9}]}
HTTPレスポンス

 これまでの例では、iUIとは関係なく単なるAjaxの使い方でしたが、いよいよ次ページでは、iUIとAjaxを組み合わせたいと思います。

       1|2 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。