1 什么是Jsonp?
JSONP(JSON with Padding)是數(shù)據(jù)格式JSON的一種“使用模式”鸯旁,可以讓網(wǎng)頁從別的網(wǎng)域要數(shù)據(jù)铺罢。另一個(gè)解決這個(gè)問題的新方法是跨來源資源共享。
由于同源策略缩滨,一般來說位于server1.example.com的網(wǎng)頁無法與不是 server1.example.com的服務(wù)器溝通辞居,而HTML的 < script >元素是一個(gè)例外瓦灶。利用 < script >元素的這個(gè)開放策略,網(wǎng)頁可以得到從其他來源動(dòng)態(tài)產(chǎn)生的JSON數(shù)據(jù)刃泡,而這種使用模式就是所謂的 JSONP烘贴。用JSONP抓到的數(shù)據(jù)并不是JSON撮胧,而是任意的JavaScript,用 JavaScript解釋器運(yùn)行而不是用JSON解析器解析芹啥。
2 Jsonp基本原理
為了理解這種模式的原理墓怀,先想像有一個(gè)回傳JSON文件的URL,而JavaScript 程序可以用XMLHttpRequest跟這個(gè)URL要數(shù)據(jù)虱朵。假設(shè)我們的URL是 http://tools.42du.cn/jsonp/student/3 碴犬。假設(shè)iFat3的st_no是3,當(dāng)瀏覽器通過URL傳遞iFat3的st_id羞福,也就是抓取http://tools.42du.cn/jsonp/student/3蚯涮,得到:
{"st_no":3,"st_name":"iFat3","st_desc":"iFat3是學(xué)校的超級(jí)學(xué)渣"}
這個(gè)JSON數(shù)據(jù)可能是依據(jù)傳過去URL的查詢參數(shù)動(dòng)態(tài)產(chǎn)生的遭顶。
這個(gè)時(shí)候棒旗,把 < script >元素的src屬性設(shè)成一個(gè)回傳JSON的URL是可以想像的,這也代表從HTML頁面通過script元素抓取 JSON是可能的饶深。
然而敌厘,一份JSON文件并不是一個(gè)JavaScript程序朽合。為了讓瀏覽器可以在 < script >元素運(yùn)行曹步,從src里URL 回傳的必須是可運(yùn)行的JavaScript。在JSONP的使用模式里尿孔,該URL回傳的是由函數(shù)調(diào)用包起來的動(dòng)態(tài)生成JSON纳猫,這就是JSONP的“填充(padding)”或是“前輟(prefix)”的由來。
慣例上瀏覽器提供回調(diào)函數(shù)的名稱當(dāng)作送至服務(wù)器的請(qǐng)求中命名查詢參數(shù)的一部分尚骄,例如:
<script type="text/javascript"
src="http://tools.42du.cn/jsonp/student/3?callback=callback>
</script>
服務(wù)器會(huì)在傳給瀏覽器前將JSON數(shù)據(jù)填充到回調(diào)函數(shù)(callback)中绳匀。瀏覽器得到的回應(yīng)已不是單純的數(shù)據(jù)敘述而是一個(gè)腳本棋傍。在本例中耐朴,瀏覽器得到的是:
/**/callback({"st_no":3,"st_name":"iFat3","st_desc":"iFat3是學(xué)校的超級(jí)學(xué)渣"});
3 服務(wù)端生成Jsonp
本例中的Jsonp利用的是Spring Framework的JSonp處理部分生成颜曾,詳細(xì)內(nèi)容請(qǐng)閱讀官方文檔泽示。鏈接見相關(guān)資料中的spring部分械筛,本人強(qiáng)烈建意您在實(shí)際開發(fā)過程中埋哟,先閱讀官方文檔,再進(jìn)行代碼編寫赤赊。
3.1 模型(model)對(duì)象
Student模型對(duì)象的get和set方法未列出抛计。
public class Student extends BaseBean implements Serializable {
private Integer st_no;
private String st_name;
private String st_desc;
}
3.2 spring的Jsonp處理
@ControllerAdvice
@RequestMapping("/jsonp")
public class StudentJsonpAdvice extends AbstractJsonpResponseBodyAdvice {
private List<Student> students = new ArrayList<Student>();
public StudentJsonpAdvice() {
super("callback");
initData();
}
@RequestMapping(value="/student/all",method= RequestMethod.GET)
@ResponseBody
public List<Student> list(){
return students;
}
@RequestMapping(value="/student/{st_no}",method= RequestMethod.GET)
@ResponseBody
public Student info(@PathVariable Integer st_no){
if(st_no != null) {
if(st_no > 0 && st_no <4) {
return students.get(st_no -1);
}
return students.get(0);
}
return null;
}
private void initData() {
Student st1 = new Student(1,"王美麗","王美麗是學(xué)校的幸瑁花");
Student st2 = new Student(2,"毛三胖","毛三胖是學(xué)校的學(xué)霸");
Student st3= new Student(3,"iFat3","iFat3是學(xué)校的超級(jí)學(xué)渣");
students.add(st1);
students.add(st2);
students.add(st3);
}
}
4 客戶端取得Jsonp數(shù)據(jù)
利用JQuery的ajax方法取得所有學(xué)生的數(shù)據(jù)录豺,并利用回調(diào)函數(shù)(callback)將數(shù)據(jù)插入到頁面中。更多JQuery的ajax方法參見相關(guān)資料中的JQuery部分饭弓。
function callback(data) {
$(data).each(function(i,item){
$("#stu_ul").append("<li>"+item.st_name+"</li>");
});
}
$(document).ready(function () {
$.ajax({
type:"get",
dataType:"jsonp",
url:"http://tools.42du.cn/jsonp/student/all",
jsonpCallback:"callback"
});
})