Slim3でrespond_toもどき
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文字列"
}
*/
てな感じになる。まったくをもってイケてないけど、こんな感じで行けなくもない感じ