利用Jsonp實現跨域請求,spring MVC+JQuery

毛三十發表於2017-06-04

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/st… 。假設iFat3的st_no是3,當瀏覽器通過URL傳遞iFat3的st_id,也就是抓取http://tools.42du.cn/jsonp/st…,得到:

{"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"
        });
    })

5 相關資料

Spring處理Jsonp文件

JQuery Ajax官方文件

維基Jsonp條目

菜鳥Jsonp教程

JSON中文介紹

學生列表Jsonp地址

學生資訊Jsonp地址

相關文章