えいのうにっき

a-knowの日記です

GAE/J + Slim3 で、Json形式のデータをクライアントにお手軽に返す方法

JavaでのGAE(Google App Engine)開発を行う場合、特に意識しなければフロントエンドはjspにするのが自然の流れかと思うのですが、

  • できるだけサーバでの処理は少なくしたい
    • サーバでの処理量・使用リソース量に比例してコストも上がるので
  • 静的コンテンツなら、レスポンス速度の早い別サーバ(staticサーバ)から受け取ることができる
    • 動的に生成されるコンテンツであるjspに対して、htmlやJavaScriptは静的コンテンツである(もちろん画像ファイルなども)
  • つまり、htmlとJavaScriptAjax)でコンテンツを構成するほうが、jspで同様のことをするよりもUX向上の点で有利

といった理由から、今やセオリーは「フロントエンドはHTMLとJavaScript(Ajax)で構成」「サーバ側は、フロントエンドからのAjaxリクエストに対してJson形式でデータを返す」という構成になっているようです。(ぼくの自己紹介ページ・えいのうのいえも、この構成で作ってみています。)


で、サーバ側がJson形式のデータを返す方法は、まぁ色々とあると思うんですが、Slim3Json形式への変換機能がお手軽です。 流れとしては、以下のようなかんじ。

  • Json形式で返したいデータの構造を持ったModelクラスをつくる
  • 返送データをModelクラスにセットするよう、アプリケーション内で記述する
  • ModelクラスからJson形式への変換を行う
  • クライアントへのレスポンスにJson形式データを書き込む

では、ひとつずつ。

Json形式で返したいデータの構造を持ったModelクラスをつくる

例えば、とあるWebアプリケーションにおいて、「いつ」「だれが」「どうした」というようなアクティビティの情報をクライアントに返送したい、といった場合を想定します。 そのとき、「Json形式で返したいデータの構造を持ったModelクラス」は、以下のようになります。

@Model
public class ActivityInfo {
    @Attribute(primaryKey = true)
    @Json(ignore = true)
    Key key;
    
    //いつ
    Date date;
    //だれが
    String loginID;
    //どうした(0:ユーザー新規登録, 1:日記更新, 2:プロフィール更新)
    int activityCode;
    
    //以下アクセサ(省略)
}

Modelクラスなので、主キー用のフィールドを宣言しておかなくてはならないのですが、クライアントに返すJsonデータとしては、その情報は不要なわけです。そういったフィールドには、アノテーション@Json(ignore = true)」を付加しておくことで、Json形式への変換対象から、そのフィールドは無視されるようになります。

返送データをModelクラスにセットするよう、アプリケーション内で記述する

これはもう、普通にやってやればOKです。

ActivityInfo activityInfo = new ActivityInfo();
activityInfo.setDate(new Date());
activityInfo.setLoginID("a-know");
activityInfo.setActivityCode(1);

こんなかんじで。

ModelクラスからJson形式への変換を行う

クライアントへのレスポンスにJson形式データを書き込む

最後のふたつは、一気にやってしまいます。

response.setCharacterEncoding("utf-8");
response.setContentType("application/json");
response.getWriter().println(ActivityInfoMeta.get().modelToJson(activityInfo));
response.flushBuffer();

ここでのresponseは、Controllerを継承したControllerクラスがフィールドとして持っているresponse、HttpServletResponseです。

ActivityInfoMetaはSlim3のAPT機能により、Modelクラス・ActivityInfoを作った時点で自動的に作られているとおもいます(Eclipse + Slim3プラグイン)。 そのActivityInfoMeta.modelToJson()を使用してやることで、ModelクラスをJson形式文字列へと簡単に変換してやることができます(複数のModelクラスをJson形式に変換できるmodelsToJson()もあります)。 なので、この文字列をresponse.getWriter().println()、response.flushBuffer()を使って書き込んでやります。

あとはJavaScript(Ajax)で受け取るだけ!

こんなかんじ。(上記処理を行なっているのが、ActivityControllerだとした場合。)

$.ajax({
    url: '/activity', type: 'get'
}).success(onSuccess).error(onError);

Ajaxによる通信・その後の描画完了までの間は、なにかしらローディング中であることがわかるGIFアニメーションかなんかを表示しておいてやるのが良さそうですね!(参考:かなりかっこいいデザインのローディング用アニメーションを生成するスクリプト -Sonic

Google API Expertが解説する Google App Engine for Java実践ガイド

Google API Expertが解説する Google App Engine for Java実践ガイド

follow us in feedly