1 什么是Jsonp?
JSONP(JSON with Padding)是數據格式JSON的一種“使用模式”,可以讓網頁從別的網域要數據。另一個解決這個問題的新方法是跨來源資源共享。
由於同源策略,一般來說位於www.42du.cn的網頁無法與不是 www.42du.cn的服務器溝通,而HTML的 < script >元素是一個例外。利用 < script >元素的這個開放策略,網頁可以得到從其他來源動態產生的JSON數據,而這種使用模式就是所謂的JSONP。用JSONP抓到的數據並不是JSON,而是任意的JavaScript,用 JavaScript解釋器運行而不是用JSON解析器解析。
2 Jsonp基本原理
為了理解這種模式的原理,先想像有一個回傳JSON文件的URL,而JavaScript 程序可以用XMLHttpRequest跟這個URL要數據。假設我們的URL是 http://tools.42du.cn/jsonp/student/3 。假設iFat3的st_no是3,當瀏覽器通過URL傳遞iFat3的st_id,也就是抓取http://tools.42du.cn/jsonp/student/3,得到:
{"st_no":3,"st_name":"iFat3","st_desc":"iFat3是學校的超級學渣"}
這個JSON數據可能是依據傳過去URL的查詢參數動態產生的。
這個時候,把 < script >元素的src屬性設成一個回傳JSON的URL是可以想像的,這也代表從HTML頁面通過script元素抓取 JSON是可能的。
然而,一份JSON文件並不是一個JavaScript程序。為了讓瀏覽器可以在 < script >元素運行,從src里URL 回傳的必須是可運行的JavaScript。在JSONP的使用模式里,該URL回傳的是由函數調用包起來的動態生成JSON,這就是JSONP的“填充(padding)”或是“前輟(prefix)”的由來。
慣例上瀏覽器提供回調函數的名稱當作送至服務器的請求中命名查詢參數的一部分,例如:
<script type="text/javascript"
src="http://tools.42du.cn/jsonp/student/3?callback=callback>
</script>
服務器會在傳給瀏覽器前將JSON數據填充到回調函數(callback)中。瀏覽器得到的回應已不是單純的數據敘述而是一個腳本。在本例中,瀏覽器得到的是:
/**/callback({"st_no":3,"st_name":"iFat3","st_desc":"iFat3是學校的超級學渣"});
3 服務端生成Jsonp
本例中的Jsonp利用的是Spring Framework的JSonp處理部分生成,詳細內容請閱讀官方文檔。鏈接見相關資料中的spring部分,本人強烈建意您在實際開發過程中,先閱讀官方文檔,再進行代碼編寫。
3.1 模型(model)對象
Student模型對象的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,"王美麗","王美麗是學校的校花");
Student st2 = new Student(2,"毛三胖","毛三胖是學校的學霸");
Student st3= new Student(3,"iFat3","iFat3是學校的超級學渣");
students.add(st1);
students.add(st2);
students.add(st3);
}
}
4 客戶端取得Jsonp數據
利用JQuery的ajax方法取得所有學生的數據,並利用回調函數(callback)將數據插入到頁面中。更多JQuery的ajax方法參見相關資料中的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"
});
})