上篇博客介紹了同源策略和跨域訪問概念,其中提到跨域經常使用的基本方式:JSONP和CORS。
那這篇博客就介紹JSONP方式。
JSONP原理
在同源策略下,在某個服務器下的頁面是沒法獲取到該服務器之外的數據的,但img、iframe、script等標籤是個例外,這些標籤能夠經過src屬性請求到其餘服務器上的數據。
而JSONP就是經過script節點src調用跨域的請求。
當咱們經過JSONP模式請求跨域資源時,服務器返回給客戶端一段javascript代碼,這段javascript代碼自動調用客戶端回調函數。
舉個例子
客戶端http://localhost:8080訪問服務器http://localhost:11111/user,正常狀況下,這是不容許的。由於這兩個URL是不一樣域的。
若咱們使用JSONP格式發送請求的話?
http://localhost:11111/user?callback=callbackfunction
則服務器返回的數據以下:
callbackfunction({"id":1,"name":"test"})
仔細看看服務器返回的數據,其實就是一段javascript代碼,這就是函數名(參數)格式。
服務器返回後,則自動執行callbackfunction函數。
所以,客戶端須要callbackfunction函數,以便使用JSONP模式返回javascript代碼後自動執行其回調函數。
注意:其中url地址中的callback和callbackfunction是隨意命名的。
具體的JS實現JSONP代碼。
JS中: javascript
- <script>
- var url = "http://localhost:8080/crcp/rcp/t99eidt/testjson.do?jsonp=callbackfunction";
- var script = document.createElement('script');
- script.setAttribute('src', url); //load javascript
- document.getElementsByTagName('head')[0].appendChild(script);
-
- //回調函數
- function callbackfunction(data){
- var html=JSON.stringify(data.RESULTSET);
- alert(html);
- }
服務器代碼Action:
後臺返回的json外面須要由回調函數包裹。具體的方法以下:
- public class TestJson extends ActionSupport{
-
- @Override
- public String execute() throws Exception {
- try {
- JSONObject jsonObject=new JSONObject();
- List list=new ArrayList();
- for(int i=0;i<4;i++){
- Map paramMap=new HashMap();
- paramMap.put("bank_no", 100+i);
- paramMap.put("money_type", i);
- paramMap.put("bank_name", i);
- paramMap.put("bank_type", i);
- paramMap.put("bank_status", 0);
- paramMap.put("en_sign_ways", 1);
- list.add(paramMap);
- }
- JSONArray rows=JSONArray.fromObject(list);
- jsonObject.put("RESULTSET", rows);
- HttpServletRequest request=ServletActionContext.getRequest();
- HttpServletResponse response=ServletActionContext.getResponse();
- response.setContentType("text/javascript");
-
-
- boolean jsonP = false;
- String cb = request.getParameter("jsonp");
- if (cb != null) {
- jsonP = true;
- System.out.println("jsonp");
- response.setContentType("text/javascript");
- } else {
- System.out.println("json");
- response.setContentType("application/x-json");
- }
- response.setCharacterEncoding("UTF-8");
- Writer out = response.getWriter();
- if (jsonP) {
- out.write(cb + "("+jsonObject.toString()+")");
- System.out.println(jsonObject.toString());
- }
- else{
- out.write(jsonObject.toString());
- System.out.println(jsonObject.toString());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return null;
- }
- }
JQUERY實現JSONP代碼。
Jquery從1.2版本開始也支持JSONP的實現。
- $(function(){
- jQuery.getJSON("http://localhost:8080/crcp/rcp/t99eidt/testjson.do?jsonp=?",function(data)
- {
- var html=JSON.stringify(data.RESULTSET);
- $("#testjsonp").html(html);
- }
- );
- });
第一個?表明後面是參數,與我們通常調用同樣。重要的是第二個?,則是jquery動態給你生成毀掉函數名稱。
至於後臺代碼和上述一致,使用同一個後臺。
JQUERY中Ajax實現JSONP代碼。
- $.ajax({
- type:"GET",
- async :false,
- url:"http://localhost:8080/crcp/rcp/t99eidt/testjson.do",
- dataType:"jsonp",
- success:function(data){
- var html=JSON.stringify(data.RESULTSET);
- $("#testjsonp").html(html);
- },
- error:function(){
- alert("error");
- }
-
- });
注意:這種形式,默認的參數是callback,而不是會是其餘。則action代碼中獲取calback值則
String cb=request.getParameter("callback");
而且生成的回調函數,默認也是相似上述一大串數字。
根據Ajax手冊,更改callback名稱以及回調函數名稱。
http://www.w3school.com.cn/jquery/ajax_ajax.asp
jsonpCallback:callbackfunction,則請求的地址爲:
最後返回前臺的是:
callbackfunction(具體的json值)
其中上述JS實現JSONP代碼中,若不是動態拼接script腳本,而是直接寫script標籤,相似以下:
<script type="text/javascript" src=""></script>
若這樣寫的話,經過debug發現,的確正確返回了,可是一直提示找不到回調函數。即便js也提供了回調函數【各個瀏覽器都測試】
若要經過JS來顯示,則經過代碼動態create script標籤。
JSONP跨域方式,很方便,同時也支持大多部分瀏覽器,可是惟一缺點是,只支持GET提交方式,不支持其餘POST提交。
若url地址傳輸的參數過多,如何實現呢?下篇博客會講解另外一種跨域方案CROS原理以及具體調用示例。
本文轉載自:http://blog.csdn.net/yuebinghaoyuan/article/details/32706277