同源政策下,伺服器不能請求該伺服器以外的資源,及不能跨域請求。何為跨域,簡單說就是協定+主機名+端口号(存在的話)三者之一不同就可稱之為跨域。如:
1.http: //www.test.com 和 https: //www.test.com 之間協定不同,存在跨域
2.blog.csdn.net 和 blog.csdn.net:8080 之間端口号不同
3.write.csdn.net 和 blog.csdn.net 之間主機名不同
但是,如果需要進行跨域請求資源時怎麼辦呢?目前常用的方法有JSONP和CROS兩種方法(本篇博文主要寫一些JSONP相關的東西)。JSONP的原理是什麼呢?html标簽中存在一些如img、script等标簽球可以通過src屬性進行資源的請求。JSONP就是通過script标簽來進行跨域資源的請求的。當發起JSONP請求的時候,伺服器就會傳回一段js腳本,請求方通過傳回的該段腳本就可以獲得請求的資源了。
舉個栗子:
如:http://localhost:8080/webcontent/test.html頁面存在
一個 http 😕/localhost:8888/jsonp/test?callback=Test 的請求,那麼伺服器就會傳回Test({“test”:“this is json”})的字元串,該字元串可看做是一個名為Test的function,其參數為一個json object。當調用方得到該字元串時就會自動執行Test方法,來進行後續的處理。
代碼如下:
調用方的JS代碼
<script>
function Test(i) {// 該方法會在結果傳回時被自動調用
console.log(i.test);
console.log(JSON.stringify(i));
}
</script>
<script src="http://127.0.0.1:8888/SpringmvcDemo/jsonp/msg?callBack=Test"></script>
伺服器端代碼:
@Controller
@RequestMapping("/jsonp")
public class JsonpTestController {
@ResponseBody
@RequestMapping("/msg")
public String responseJsonp(HttpServletRequest request,
@RequestParam String callBack) {
String testJson = "{\"test\":\"this is json\"}";
String jsonp = callBack + "(" + testJson + ");";
return jsonp;
}
}
若直接請求伺服器,會傳回如下結果
JSONP跨域請求傳回的結果(開發者工具控制台)
通過以上示範可以看出,jsonp其實就是json外面包裹一個回調函數,通過該回掉函數就可以對json資訊進行後續的處了解析。
在實際項目中通常使用JQUERY進行JSONP調用
示例代碼:
$.ajax({
async:false,
type:'get',
url: 'http://127.0.0.1:8888/SpringmvcDemo/jsonp/msg',
cache : false,
dataType: "jsonp",
success: function(data) {
// 進行相應處理
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
});
JQUERY會在請求的Url後面加上callback=動态生成的回調函數名,伺服器傳回的資料就是生成的動态回調函數包裹json。JQUERY會預設使用callback,當然也可以指定callback為其他值,也可以指定回調函數名。
JSONP很友善的解決了跨域問題,但是由于本身隻能采用get方式進行請求,是以在請求參數過多的情況下就無法使用了。