1. 程式人生 > >Nutz 框架下 測試 jQuery-JSONP 外掛跨域呼叫功能(Uncaught SyntaxError: Unexpected token : 出錯原因解釋)

Nutz 框架下 測試 jQuery-JSONP 外掛跨域呼叫功能(Uncaught SyntaxError: Unexpected token : 出錯原因解釋)

注:本文歡迎轉載,以下為本人親測,轉載請註明:http://blog.csdn.net/wqmain/article/details/8905287

外掛介紹:眾所周知,使用ajax直接發起請求存在跨域無許可權訪問的問題,這時候,需要使用jsonp協議(非官方的協議)處理,jQuery中的$.ajax方法也直接支援使用該協議進行跨域訪問。下面首先介紹使用jQuery的$.ajax方法進行跨域訪問,然後再介紹使用其它jQuery外掛(jQuery-JSONP)實現樣的功能。

1、新建一個jsp頁面,加入一段js程式碼內容如下:

<script type="text/javascript">  
function ajaxtest() {  
$.ajax({  
   url:'http://192.168.10.111/demo/testjson',  
   data:{rel:13},  
   dataType:"jsonp",  
   jsonp:"callback",  
   jsonpCallback:"success_jsonp",  
   timeout:3000,  
   dataFilter:function(json){  
       console.log("jsonp.filter:"+json);  
       return json;  
   },  
   success:function(json,textStatus){  
       console.log("jsonp.success:"+json.name);  
   },  
   error:function(XMLHttpRequest,textStatus,errorThrown){  
       console.log("jsonp.error:"+textStatus);  
   }  
});  
}  
</script> 

再新增一個按鈕用來測試該js方法,如下:

<input type="button" value="ajaxtest" onclick="ajaxtest()"/>
說明:當點選 ajaxtest 按鈕時,就會發起一個請求,由url、dataType、jsonp等引數可知,ajax使用jsonp協議向 http://192.168.10.111/demo/testjson 這個地址發起請求,並自動在url後追加callback引數,實際請求的url地址應為:http://192.168.10.111/demo/testjson?rel=13&callback=success_jsonp,請求超時時間為3秒,接收的資料為json格式字串。如果成功接收到遠端方法返回的json資料並且格式正確的話,首先會進入dataFilter方法(你可以在這個方法內對返回的json資料進行預處理,比如過濾、更改json資料等),然後進入success方法;如果請求失敗或者返回的json資料格式不正確的話會直接進入error方法。

那麼服務端的testjson方法應該返回什麼樣的資料呢?直接返回json物件或json字串是不對的!還需要在之前加上請求時傳過來的callback的引數值,後臺(以servlet為例)應類似如下處理:

public void testjson(HttpServletRequest request, HttpServletResponse response) {
	String callback = (String)request.getParameter("callback");
	String jsonData = "{\"id\":\"3\", \"name\":"zhangsan", \"telephone\":"13612345678"}";//為了演示效果,json資料是寫死的
	String retStr = callback + "(" + jsonData + ")";
	response.getWriter().print(retStr);
}

這樣後臺響應的的資料實際為:success_jsonp({"id":"3", "name":"zhangsan", "telephone":"13612345678"})    其中success_jsonp取決於ajax引數值的設定,如果未設定,jQuery將會自動生成一個名字作為callback的引數值。總之,後臺只需request接收parameter後,動態拼接callback變數的值就可以了。

如果返回的資料格式不按上述講的這樣,請求就會失敗並直接進入ajax的error方法。像 Uncaught SyntaxError: Unexpected token :類似這種錯誤就是返回的json資料沒用“(”和“)”小括號包起來或者前面沒加callback值而引起的

跨域呼叫功能除了用Query的$.ajax方法可以實現外,網路上還有其它眾多的jQuery外掛可以完成,下面就來看一下使用jQuery的jsonp外掛來進行跨域呼叫:

<script type="text/javascript" src="jquery.jsonp.js"></script>
<script type="text/javascript">
function jsonptest(){
$.jsonp({
   url:'http://192.168.10.111/demo/testjson',
   data:{rel:13},
   callbackParameter:"callback",
   timeout:3000,
   dataFilter:function(json){
    console.log("jsonp.filter:"+json.name);
    json.name = "測試123435";
return json;
},
   success:function(json,textStatus,xOptions){
       console.log("jsonp.success:"+json.name);
   },
   error:function(xOptions,textStatus){
    console.log("jsonp.error:"+textStatus+", rel="+xOptions.data.rel);
   }
});
}

再新增一個按鈕用來測試該js方法,如下:

<input type="button" value="jsonptest" onclick="jsonptest()"/>

說明:點選jsonptest按鈕後,控制檯打印出來的效果和使用$ajax方法時的基本一致,不同的是dataFilter方法:雖然二者都提供了dataFilter方法,但$.jsonp的dataFilter中資料已經直接轉換成json物件了,而$.ajax的dataFilter中獲取的卻是原生的帶callback方法名的json字串(測試時控制檯打印出來的是undefined)。如果需要對返回的資料做預處理的話,建議使用jQuery-JSONP外掛的$.jsonp方法

前面介紹了用servlet編寫testjson方法,假設你對nutz框架(http://www.nutzam.com/)熟悉的話,下面貼出使用nutz框架編寫testjson方法:
@At("/testjson")
@Ok("raw")
public String testjson(HttpServletRequest req, String callback, String rel) throws Exception {
	Map<String, String> jsonMap = new LinkedHashMap<String, String>();
	jsonMap.put("id", "3");
	jsonMap.put("name", "zhangsan");
	jsonMap.put("telephone", "13612345678");
	jsonMap.put("rel", rel);
	String jsonp = callback + "(" + Json.toJson(jsonMap) + ")";
	return jsonp;
}
注意:如果你在MainModule中設定了全域性的返回型別為json的話(@Ok("json")),那麼testjson方法上需要加上@Ok("raw")註解,不做解釋,不明白可以看nutz官方文件。