はじめに
アプリから、外部のサーバーのデータを取りたい場合のJSONP編。
JSONPとは
通常、異なるドメインに対してAjax通信をしようとすると怒られる。
これをクロスドメイン制約という。
XMLHttpRequest cannot load http://exampleexample.com/.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'https://example.com/' is therefore not allowed access.
それでも外部のサーバーのデータを取るのは不可欠なので、
http://example.com/jsonp_project/JsonpServlet?callback=displayCustomer
上記のようなURLでアクセスした時に、
callback
パラメーターの値をサーバー側で受け取り、
displayCustomer([{"age":16,"name":"テスト太郎"}])
のようなJavaScriptの関数を呼び出す形式でサーバー側からJSONデータ返ってくるようにしておく。
displayCustomer
がクライアント側で呼び出したいJavaScriptの関数名となっている。
この関数名は任意のものにして、callbackパラメーターとして設定しとけばよい。
受け取ったデータを
<script>
displayCustomer([{"age":16,"name":"テスト太郎"}])
</script>
な感じで画面側に追加して、クライアント側で定義してあるJavaScriptの関数(この場合displayCustomer)を実行することで、外部のデータを取得した上での処理を実行するというのがJSONP。
scriptタグが外部のソースを読み込みこめることを利用している。
手順
サーバー側でJSON形式にてデータを返すようにする。
今回はサーブレットで適当に作ったデータをJSONで返すように実装。
実際はデータベースからデータを取得して
@WebServlet(name = "JsonpServlet", urlPatterns = {"/JsonpServlet"})
public class JsonpServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// URLからcallbackパラメーターに設定されている値を取得
String callback = request.getParameter("callback");
Customer[] customers = {
new Customer("テスト太郎", 16)
};
// JSONにエンコード
String jsonText = JSON.encode(customers);
String responseData = "";
if(callback == null || "".equals(callback)){
responseData = jsonText;
}else{
// ここで関数名(JSON)の形式でレスポンスを返すように設定
responseData = callback + "(" + jsonText + ")";
}
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.print(responseData);
}
}
画面はボタンがあって、それを押したらJSの関数を実行するのみ。
<ons-page>
<ons-toolbar>
<div class="center">AjaxJSON</div>
</ons-toolbar>
<div style="text-align: center">
<br>
<ons-button onclick="addScript()">
JSONP
</ons-button>
<div id="ajax"></div>
</div>
</ons-page>
callbackパラメーターにクライアント側で呼びたいJS関数の名前を指定。
// ボタンが押された時にデータを受け取ってscriptタグとして画面に追加
function addScript(){
var script = document.createElement('script');
script.src = 'http://example.com/jsonp_project/JsonpServlet?callback=displayCustomer';
document.body.appendChild(script);
}
// 上記で「関数名(JSON)」の形式でスクリプトが追加され、これが呼ばれる
function displayCustomer(data){
for(i = 0; i < data.length; i++){
$("#ajax").append("<div>" + data[i].name + "</div>");
}
}
実行結果
まとめ
気象情報APIのようなJSONPを提供しているところがあるので、そういうところのAPIを利用したり、サーバー側でいい感じに返すようにしたらいいと思いました。