이번에는 Ajax 크로스 도메인 문제를 해결하기 위해 JSONP를 소개합니다(코드 포함). JSONP가 Ajax 크로스 도메인 문제를 해결하는 데 사용할 수 있는 주의 사항은 무엇입니까?
JSON과 JSONP
JSONP와 JSON이 비슷해 보이죠?
JSON(JavaScript Object Notation)은 경량 데이터 교환 형식입니다. 누구나 JSON에 대해 잘 알고 있어야 합니다. JSON에 대해 잘 모르는 친구는 json.org를 방문하여 간단하고 쉽게 알아볼 수 있습니다.
JSONP는 JSON의 약어로 Padding을 추가한 것입니다. 이는 서버 측에서 스크립트 태그를 통합하고 이를 클라이언트에 반환하여 자바스크립트 콜백 형식으로 도메인 간 액세스를 가능하게 하는 비공식 프로토콜입니다(이는 JSONP의 간단한 구현일 뿐입니다).
JSONP는 JSON+Padding(여기서 Padding은 패딩으로 이해함)과 같습니다. 먼저 아래의 작은 예를 살펴보고 자세히 소개하겠습니다.
동일출처 정책
왜 이런 오류가 발생하나요? 이는 Javascript를 지원하는 모든 브라우저가 동일 출처 정책을 사용하기 때문입니다. Baidu의 설명을 살펴보세요:
Netscape가 제안한 유명한 보안 정책인 동일 출처 정책. JavaScript를 지원하는 모든 브라우저는 이제 이 전략을 사용합니다. 소위 동일한 출처는 도메인 이름, 프로토콜 및 포트가 동일함을 의미합니다. Baidu와 Google 페이지가 브라우저의 두 탭 페이지에서 열리면 Baidu 브라우저가 스크립트를 실행할 때 스크립트가 어느 페이지에 속하는지, 즉 스크립트가 Baidu와 동일한 출처인지 확인하게 됩니다. 실행.
이것이 데이터를 얻을 수 없는 이유입니다. 그렇다면 크로스 도메인 문제를 어떻게 해결할 수 있을까요? 맞습니다. 이제 본론으로 들어가서 JSONP가 무엇인지 이해할 수 있습니다.
크로스 도메인의 간단한 원리
정의만 봐서는 그다지 명확하지 않으니, 먼저 수동으로 간단하고 이해하기 쉬운 테스트를 해보겠습니다. 새로운 asp.net 웹 프로그램을 만들고, 샘플.html 웹 페이지와 test.js 파일을 추가하세요. 코드는 다음과 같습니다:
sample.html 코드:
<!DOCTYPE html PUBLIC "-//WC//DTD XHTML . Transitional//EN" "http://www.w.org/TR/xhtml/DTD/xhtml-transitional.dtd"> <html xmlns="http://www.w.org//xhtml" > <head> <title>test</title> <script type="text/javascript" src="test.js"></script> </head> <body> </body> </html>
test.js 코드:
alert("success");
샘플.html을 열면 "성공"과 같은 메시지 상자가 나타납니다. 이는 아무 의미가 없는 것 같습니다. 크로스 도메인 문제를 해결하는 방법은 무엇입니까? 자, 이제 비동질적인 환경을 시뮬레이션합니다. Visual Studio를 사용하여 새 웹 프로그램(여기서는 프로그램 A라고 함)을 만듭니다. 이제 새 Visual Studio를 열고 새 웹 프로그램(프로그램 B)을 만듭니다. ). ), 프로그램 A에서 이전 test.js 파일을 제거하고 프로그램 B에 복사합니다. 두 프로그램이 모두 실행된 후 Visual Studio에서는 프로그램 A가 localhost:20001이고 프로그램 B가 localhost:20002라고 가정합니다. 이는 도메인 이름은 동일하지만 포트는 동일합니다. 숫자가 다르기 때문에 균일하지 않습니다.)
좋아요, test.js 파일이 프로그램 B에 있고 URL이 localhost:20002가 되므로 다음으로 Sample.html의 코드를 변경해야 합니다.
sample.html 코드 부분:
<script type="text/javascript" src="http://localhost:20002/test.js"></script>
두 개의 웹 프로그램 AB를 계속 실행하세요. localhost:20001/sample.html을 다시 새로 고치면 이전과 같이 "성공" 대화 상자가 나타납니다. 동일한 출처가 아닌 소위 원격 서비스인 localhost:20002/test.js에 성공적으로 액세스했습니다. 이 시점에서는 모든 사람이 도메인 간 액세스의 원칙을 대략적으로 이해해야 한다고 생각합니다.
<script> 태그의 src 속성은 동일 출처 정책에 의해 제한되지 않으므로 서버에서 어떤 스크립트라도 얻어서 실행할 수 있습니다. </p> <p style="text-align: left;"><span style="background-color: #808080">JSONP 구현 모드--CallBack</span></p> <p style="text-align: left;"> 작은 예에서는 교차 도메인의 원리를 설명했을 뿐입니다. 다시 JSONP 정의에 언급된 자바스크립트 콜백의 형식을 살펴보겠습니다. 그럼 코드를 수정하고 JSONP의 자바스크립트 콜백 형태를 구현하는 방법을 살펴보겠습니다. </p> <p style="text-align: left;">프로그램 A의 샘플 코드 일부: </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <script type="text/javascript"> //回调函数 function callback(data) { alert(data.message); } </script> <script type="text/javascript" src="http://localhost:20002/test.js"></script>
프로그램 B의 test.js 코드:
//콜백 함수를 호출하고 설명으로 json 데이터 형식으로 전달하여 콜백을 완료합니다
callback({message:"success"});
这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义吧。
一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。
程序A中sample的部分代码:
<script type="text/javascript"> function callback(data) { alert(data.message); } //添加<script>标签的方法 function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function(){ addScriptTag("http://localhost:/test.js"); } </script>
程序B的test.js代码不变,我们再执行下程序,是不是和原来的一样呢。如果我们再想调用一个远程服务的话,只要添加addScriptTag方法,传入远程服务的src值就可以了。这里说明下为什么要将addScriptTag方法放入到window.onload的方法里,原因是addScriptTag方法中有句document.body.appendChild(script);,这个script标签是被添加到body里的,由于我们写的javascript代码是在head标签中,document.body还没有初始化完毕呢,所以我们要通过window.onload方法先初始化页面,这样才不会出错。
上面的例子是最简单的JSONP的实现模型,不过它还算不上一个真正的JSONP服务。我们来看一下真正的JSONP服务是怎么样的,比如Google的ajax搜索接口:http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=?&callback=?
q=?这个问号是表示你要搜索的内容,最重要的是第二个callback=?这个是正如其名表示回调函数的名称,也就是将你自己在客户端定义的回调函数的函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调。有点罗嗦了,还是看看实现代码吧:
<script type="text/javascript"> //添加<script>标签的方法 function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function(){ //搜索apple,将自定义的回调函数名result传入callback参数中 addScriptTag("http://ajax.googleapis.com/ajax/services/search/web?v=.&q=apple&callback=result"); } //自定义的回调函数result function result(data) { //我们就简单的获取apple搜索结果的第一条记录中url数据 alert(data.responseData.results[].unescapedUrl); } </script>
像这样的JSONP服务还有很多(以下信息来自使用 JSONP 实现跨域通信,第 1 部分: 结合 JSONP 和 jQuery 快速构建强大的 mashup):
接下来我们自己来创建一个简单的远程服务,实现和上面一样的JSONP服务。还是利用Web程序A和程序B来做演示,这次我们在程序B上创建一个MyService.ashx文件。
程序B的MyService.ashx代码:
public class MyService : IHttpHandler { public void ProcessRequest(HttpContext context) { //获取回调函数名 string callback = context.Request.QueryString["callback"]; //json数据 string json = "{\"name\":\"chopper\",\"sex\":\"man\"}"; context.Response.ContentType = "application/json"; //输出:回调函数名(json数据) context.Response.Write(callback + "(" + json + ")"); } public bool IsReusable { get { return false; } } }
程序A的sample代码中的调用:
<script type="text/javascript"> function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function(){ //调用远程服务 addScriptTag("http://localhost:/MyService.ashx?callback=person"); } //回调函数person function person(data) { alert(data.name + " is a " + data.sex); } </script>
这就完成了一个最基本的JSONP服务调用了,是不是很简单,下面我们来了解下JQuery是如何调用JSONP的。
jQuery对JSONP的实现
jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法(详细可以参考http://api.jquery.com/jQuery.getJSON/)。那我们就来修改下程序A的代码,改用jQuery的getJSON方法来实现(下面的例子没用用到向服务传参,所以只写了getJSON(url,[callback])):
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> <script type="text/javascript"> $.getJSON("http://localhost:20002/MyService.ashx?callback=?", function(data){ alert(data.name + " is a a" + data.sex); }); </script>
结果是一样的,要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。这个函数名大家可以debug一下看看,比如jQuery17207481773362960666_1332575486681。
当然,加入说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现(参数较多,详细可以参考http://api.jquery.com/jQuery.ajax)。先来看看如何实现吧:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> <script type="text/javascript"> $.ajax({ url:"http://localhost:20002/MyService.ashx?callback=?", dataType:"jsonp", jsonpCallback:"person", success:function(data){ alert(data.name + " is a a" + data.sex); } }); </script>
没错,jsonpCallback就是可以指定我们自己的回调方法名person,远程服务接受callback参数的值就不再是自动生成的回调名,而是person。dataType是指定按照JSOPN方式访问远程服务。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
위 내용은 JSONP는 Ajax 도메인 간 문제를 해결합니다(코드 포함).의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!