Slim3でrespond_toもどき

2012-08-19T00:00:00+00:00 Java JavaScript

IndexController.java

package server_director.controller.profile;

import org.slim3.controller.Navigation;

import server_director.controller.ServerDirectorController;
import server_director.model.Profile;
import server_director.service.ProfileService;

import com.google.appengine.api.users.User;

public class IndexController extends ServerDirectorController {

    ProfileService service = new ProfileService();

    @Override
    protected Navigation run() throws Exception {
        User user = service.getUser();

        if (!service.isLogin() || user == null) {
            return redirect(service.createLoginURL("/profile"));
        }

        Profile profile = service.getProfile();

        requestScope("profile", profile);

        return forward("/WEB-INF/jsp/index.jsp");
    }
}

まぁてな感じで継承しているクラス以外は普通のSlim3コントローラークラス。もちろんコントローラー側でJSONに変換したりっていう処理は含まれない(あるがJSONに変換する処理自体はModelに。それは以下参照)

Profile.java

package server_director.model;

import java.io.Serializable;

import org.slim3.datastore.Attribute;
import org.slim3.datastore.InverseModelListRef;
import org.slim3.datastore.Model;
import org.slim3.datastore.json.Expanded;
import org.slim3.datastore.json.Json;

import server_director.meta.ProfileMeta;
import server_director.meta.ServerMeta;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.users.User;

@Model
public class Profile implements Serializable, JsonModel {

    private static final long serialVersionUID = 1L;

    @Attribute(primaryKey = true)
    private Key key;

    @Attribute(persistent = true)
    @Json(ignore = true)
    private User user;

    @Attribute(persistent = false)
    @Json(ignore = false, coder =Expanded.class)
    private InverseModelListRef<Server, Profile> servers = new InverseModelListRef<Server, Profile>(
        Server.class,
        ServerMeta.get().profileRef.getName(),
        this
    );

    public Key getKey() {
        return key;
    }

    public void setKey(Key key) {
        this.key = key;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public InverseModelListRef<Server, Profile> getServers() {
        return servers;
    }

    public String toJson() {
        return ProfileMeta.get().modelToJson(this, 1);
    }
}

普通のSlim3 Datastore Modelと、JsonModelっていうインタフェースを利用する。JsonModel.javaは

package server_director.model;

public interface JsonModel {
    public String toJson();
}

なだけ。別にtoStringメソッドをオーバーライドしてJSON化する処理入れれば良いって思ったけど、それはそれであかんと思ったので却下

ServerDirectorController.java

package server_director.controller;

import java.util.Enumeration;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.datastore.Model;
import org.slim3.repackaged.org.json.JSONObject;
import org.slim3.util.StringUtil;

import server_director.model.JsonModel;

public abstract class ServerDirectorController extends Controller {

    @Override
    public Navigation runBare() throws Throwable {
        Navigation nav = super.runBare();

        if (nav != null && isAjax()) {
            response.setContentType("application/json");

            @SuppressWarnings("unchecked")
            Enumeration<String> e = request.getAttributeNames();

            JSONObject json = new JSONObject();

            while(e.hasMoreElements()) {
                String k = e.nextElement();
                Object v = request.getAttribute(k);

                // org.slim3.datastore.Modelアノテーションが付与及びJsonModelインターフェースが実装されているかチェック

                if (v.getClass().isAnnotationPresent(Model.class) && v instanceof JsonModel) {
                    json.put(k, ((JsonModel)v).toJson());
                }
            }

            response.getWriter().print(json.toString());

            return null;
        }

        return nav;
    }

    // Acceptがapplication/jsonで始まり、X-Requested-WithがXMLHttpRequestであるかをチェック

    public boolean isAjax() {
        String accept = request.getHeader("Accept");
        String requestedWith = request.getHeader("X-Requested-With");

        if (!StringUtil.isEmpty(accept) && !StringUtil.isEmpty(requestedWith)) {
            if (accept.startsWith("application/json") && requestedWith.equals("XMLHttpRequest")) {
                return true;
            }
        }

        return false;
    }
}

でJavaScriptとかで

$.getJSON("/profile", function(data) {
  console.log(data);
});

/* 結果
{
  "profile": "モデルをJSON化した結果のJSON文字列"
}
*/

てな感じになる。まったくをもってイケてないけど、こんな感じで行けなくもない感じ

Chrome Extension開発を勉強してみる (17) - oauth.jsを使ってDropbox API - modelToJsonでInverseModelListRefを扱う