首頁 >web前端 >js教程 >jsonp跨域請求的相關介紹

jsonp跨域請求的相關介紹

零下一度
零下一度原創
2017-07-16 15:22:241392瀏覽

這篇文章主要為大家詳細介紹了jsonp跨域請求的相關資料,啟動了所有介面支援瀏覽器跨域請求的封裝,具有一定的參考價值。

分開說明:

一、JSONP:

直覺的理解:

就是在客戶端動態註冊一個函數

function a(data),然後將函數名稱傳到伺服器,伺服器傳回一個a({/*json*/})到客戶端運行,這樣就呼叫客戶端的

function a(data),從而實現了跨域.

誕生背景:

1、Ajax直接請求普通文件存在跨域無權訪問的問題,甭管是靜態頁面、動態網頁、web服務、wcf、只要是跨域請求,一律不行。

2、不過,web頁面上呼叫js檔案時則不受此影響

3、進一步推廣,我們發現,凡是擁有Src屬性的標籤都有跨域能力,如: 3f1c4e4b6b16bbbd69b2ee476dc4f83aa1f02c36ba31691bcfe87b2722de723bd5ba1642137c3f32f4f4493ae923989c

4、於是,當前如果想透過純web端(ActiveX控制項、服務端代理程式、屬於未來的HTML5之Websocket等方式不算)跨域存取數據,就只能使用以下方式:就是在遠端伺服器上設法把資料裝進js格式的文字裡,供客戶端呼叫和進一步處理。

5、JSON就是一種純字元資料格式,且能唄js原生支援。

6、這樣解決方案出爐:web客戶端透過與呼叫腳本一模一樣的方式,來呼叫跨網域伺服器上動態產生的js格式檔案(一般以json為後綴)。

7、客戶端在對json檔案呼叫成功後,也就得到了所需數據,剩下的就是按照自己的需求進行處理了。

8為了便於客戶端使用數據,逐漸形成了一種非正式的傳輸協議,稱為jsonp。該協定的一個要點就是允許使用者傳遞一個callback參數給伺服器,然後伺服器返回資料時會將這個callback參數作為函數名稱來包裹住json數據,這樣客戶端就可以隨意自訂自己的函數來處理傳回資料了。

具體實現:

不管jQuery也好,extjs也罷,又或者是其他支持jsonp的框架,他們幕後所做的工作都是一樣的,下面我來循序漸進的說明一下jsonp在客戶端的實作:

1、我們知道,即使跨域js檔案中的程式碼(當然指符合web腳本安全策略的),web頁面也是可以無條件執行的。

遠端伺服器remoteserver.com根目錄下有個remote.js檔案程式碼如下:

alert('我是遠端檔案');

#話不多講,見核心代碼

1.定義一個類,繼承MappingJackson2HttpMessageConverter,重寫writeInternal方法,方法裡簡單判斷一下是否帶有callback參數,沒有直接返回數據,有的話將數據用callback參數的值括號包起來回傳。

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonProcessingException;

public class CallbackMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {

 // 做jsonp的支持的标识,在请求参数中加该参数
 private String callbackName;

 @Override
 protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException,
   HttpMessageNotWritableException {
  // 从threadLocal中获取当前的Request对象
  HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
    .currentRequestAttributes()).getRequest();
  String callbackParam = request.getParameter(callbackName);
  if (StringUtils.isEmpty(callbackParam)) {
   // 没有找到callback参数,直接返回json数据
   super.writeInternal(object, outputMessage);
  } else {
   JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
   try {
    String result = callbackParam + "(" + super.getObjectMapper().writeValueAsString(object)
      + ");";
    IOUtils.write(result, outputMessage.getBody(), encoding.getJavaName());
   } catch (JsonProcessingException ex) {
    throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
   }
  }

 }

 public String getCallbackName() {
  return callbackName;
 }

 public void setCallbackName(String callbackName) {
  this.callbackName = callbackName;
 }

}

2.定義Java bean,注意修改class掃描路徑,這樣每次請求過來都會調起MappingJackson2HttpMessageConverter類別裡的riteInternal這個方法,如果請求帶上了callback參數,則將以callbackValue('data ')格式的資料回傳給前端。

<!-- 定义注解驱动 -->
 <mvc:annotation-driven>
  <mvc:message-converters register-defaults="true">
   <bean
    class="xxx.xxx.xxx.CallbackMappingJackson2HttpMessageConverter">
    <property name="callbackName" value="callback" />
   </bean>
  </mvc:message-converters>
 </mvc:annotation-driven>

3.前端透過jquery封裝的ajax方式調用,這裡做了一些程式碼節省,關鍵程式碼已紅色標出

<script type="text/javascript">
 var feedback = {
  init: function(){
   var self = feedback;
   self.bind();
  },
  test: function(data){
   console.log("测试jsonp",data)
  },
  bind: function(){
    var self = feedback;

    var par = {};
     par.callback = &#39;feedback.test&#39;;

    $.ajax({ 
    url:"http://manage.danong.com/rest/open/queryInviteList", 
    data: par,
    dataType:&#39;jsonp&#39;, 
    jsonp:&#39;callback&#39;, 
    timeout:3000 
   }); 
  }
 }
 feedback.init();
</script>

4.瀏覽器列印log

 

以上是jsonp跨域請求的相關介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn