>  기사  >  웹 프론트엔드  >  Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

php中世界最好的语言
php中世界最好的语言원래의
2018-04-04 14:20:421240검색

이번에는 Ajax의 크로스 도메인 문제를 해결하기 위해 Jsonp를 소개하겠습니다. Jsonp가 Ajax의 크로스 도메인 문제를 해결하는 데 사용할 수 있는 notes는 무엇입니까?

1. 소개

최근 크로스도메인 이슈가 많이 발생하는데, 우연히 이걸 보고 정리해봤습니다. JSONP에 관해서 바이두에는 정말 많은 것들이 있고, 많은 것들이 있습니다. 계속해서 따라하다 보면 사실 몇 가지 정보밖에 나오지 않을 텐데, 아직은 능력의 문제일 수도 있겠네요. 기본. 주목해야 할 점은 여기에서 Jsonp가 ajax의 도메인 간 문제를 해결하는 데 사용된다는 것입니다. 특정 구현은 실제로 ajax가 아닙니다.

1. 동일 출처 정책

브라우저에는 동일 출처 정책이라는 매우 중요한 개념이 있습니다. 소위 동일 출처란 도메인 이름, 프로토콜 및 포트가 동일함을 의미합니다. 서로 다른 소스의 클라이언트측 스크립트(JavaScript, ActionScript)는 명시적인 인증 없이는 서로의 리소스를 읽거나 쓸 수 없습니다.

2. JSONP

JSONP(JSON with Padding)는 주류 브라우저의 도메인 간 데이터 액세스 문제를 해결하는 데 사용할 수 있는 JSON의 "사용 모드"입니다. 일반적으로 동일 출처 정책으로 인해 server1.example.com에 위치한 웹 페이지는 HTML 스크립트 요소를 제외하고는 server1.example.com 이외의 서버와 통신할 수 없습니다. <script> 요소의 이러한 공개 정책을 사용하면 웹 페이지는 다른 소스에서 동적으로 생성된 JSON 데이터를 얻을 수 있으며 이러한 사용 패턴을 JSONP라고 합니다. JSONP로 캡처된 데이터는 JSON이 아니라 JSON 파서로 구문 분석하는 대신 JavaScript 인터프리터로 실행되는 임의의 JavaScript입니다. </script>

2. 연습

1. 도메인 간 요청 시뮬레이션

이 머신에서 Tomcat 두 개를 만드세요. 포트는 각각 8080과 8888이며 이는 원본이 아닌 원본 조건을 충족합니다. 하나에서 시작 포트가 다른 포트에서 데이터를 얻기 위해 ajax를 보내는 경우 크로스 도메인 요청 문제가 발생합니다.

Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

여기에는 jsonp(8080)와 other(8888)라는 두 개의 프로젝트가 있습니다. jsonp 프로젝트의 index.jsp는 다음과 같습니다.

nbsp;html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">


<title>Insert title here</title>
<script></script>
<script>
function jsonp_fun(){
$.ajax({
url:&#39;http://localhost:8888/other/index.jsp&#39;,
type:&#39;post&#39;,
dataType:&#39;text&#39;,
success:function(data){
console.log(data);
}
});
}
</script>


<input>

다른(8888) 프로젝트의 index.jsp는 다음과 같습니다. 다음: // jsp가 실제로는 서블릿이기 때문에 여기서는 데모용으로 서블릿 대신 jsp를 사용합니다.

nbsp;html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">


<title>Insert title here</title>
<script></script>


other domain

사실 위에 보이는 것은 다른 페이지의 데이터를 가져오기 위해 jsonp 페이지에서 ajax 버튼을 클릭하는 것에 지나지 않습니다.

결과는 다음과 같습니다: chrome console

Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

XMLHttpRequest가 http://localhost:8888/other/index.jsp를 로드할 수 없습니다. 요청한 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다. 따라서 원본 'http://localhost:8080'에는 액세스가 허용되지 않습니다.

위 팁은 8888 도메인의 리소스에 8080 도메인에서 액세스할 수 없다는 내용입니다.

2. 다른 도메인의 js 파일에 액세스하려면 script 태그를 사용하세요.

<script> 태그의 src는 도메인 간 요청을 지원합니다. 가장 일반적인 것은 CDN 서비스를 적용하는 것입니다. 예를 들어 제 프로젝트에서 jQuery를 사용하고 싶지만 그러한 js 파일이 없으면 다운로드하는 데 시간이 오래 걸리고, 잘 모르겠습니다. 버전이 정확하면 Baidu에서 jquery cdn을 검색할 수 있습니다. 예를 들어 bootstrap의 CDN(http://www.bootcdn.cn/jquery/) 중에서 선택할 수 있습니다. 프로젝트에 추가하세요. 가장 큰 단점은 인터넷에 연결되어 있지 않으면 그냥 가져오지 못한다는 것입니다. </script>

2.1 other의 루트 경로에 js/other.js 파일을 생성합니다. 내용은 다음과 같습니다.

alert("this is other(8888) js");

2.2 jsonp/index.jsp에 script 태그를 추가하고 other의 js를 소개합니다

<script></script>

http://localhost:8080/jsonp/index.jsp를 입력하면 가져온 js 파일이 자동으로 실행되고 도메인 간 js 요청이 성공했음을 나타내는 경고가 즉시 나타납니다.

Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

2.3 마찬가지로 직접 인용은 즉시 알림을 실행한 다음 other.js에 함수를 작성하고 jsonp/index.jsp에서도 호출할 수 있습니다. 이것은 대부분 시연되지 않습니다. 개발이 완료되었으며 페이지가 js/css와 분리되었습니다.

2.4 另外说明一点,如果在other.js中有函数通过ajax调用8080中的东西,然后引入之后,调用这个函数,也是可以的,但是如果other.js中函数ajax调用8888的东西,引入之后,调用这个函数,同样是跨域的。

3、script实现跨域请求

3.1 简单模拟服务器返回数据

将jsonp/index.jsp改成如下:这里注意引入的other.js的位置,是在函数getResult之后的,如果在它之前的话,会提示函数不存在。js加载顺序是从上开始,在之前调用没创建的,不能成功。注意这里是指引入的js文件,如果是同一个js文件或者当前页面的js中,先执行调用,然后再写函数也是没有问题的,但是如果先执行调用引入js文件中的函数,然后再引入js文件,就会提示函数不存在。

<script></script>
<script>
function jsonp_fun(){
$.ajax({
url:&#39;http://localhost:8888/other/index.jsp&#39;,
type:&#39;post&#39;,
dataType:&#39;text&#39;,
success:function(data){
console.log(data);
}
});
}
function getResult(data){
alert(data.result);
}
</script>
<script></script>

然后other.js

getResult({"result":"this is other domain's data"});

也就是在jsonp/index.jsp页面写好函数,然后引入其他域的js传入参数去调用这个函数,这里的参数你可以先看做是其他域服务器的接口返回的数据。

刷新页面,效果当然是

弹出alert框,this is other domain's data

3.2 模拟接口访问

看到这里,你会不会还是想不懂,上面js弄啥的,传个死的数据,有什么实际意义吗?,其实script的src不仅可以接js的地址,还可以接servlet的地址,也就是http接口地址,所以接下来,懒得写servlet,这里还是写jsp当做接口,在other项目中新建other.jsp页面,内容如下:


内容很简单,也就是接受一个params的参数,然后返回数据给调用者。

我们在jsonp/index.jsp中加上

<script></script>

看到这个地址,你是不是很熟悉,不熟悉的证明你用servlet用蠢了,jsp也是servlet,流程就是页面一加载的时候,script标签就会去发送请求,然后返回数据。那么我们刷新页面,看看效果。

Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

Uncaught SyntaxError: Unexpected identifier

报错了,如上,然后代码有问题?No,点击错误,你会看到请求的东西也打印出来了,就是提示错误,表示这个东西浏览器不认识,其实是script不认识啦。

Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

还不明白,那么你去页面加上如下内容,你看报不报错!!肯定报错

<script>
ajax cross success,the server receive params : jsonp_param
</script>

那么js不能解析,我们换一种思路,要是我们输出的是JSON字符串或者调用当前页面函数的字符串了,类似于3.1中返回的getResult({“result”:”this is other domain's data”});

所以改造一下,把other.jsp中的内容改成


别忘了,之前jsonp/index.jsp中我们定义了,那么加入引用之后,依然记得getResult函数与引入函数的先后顺序问题。

<script>
function getResult(data){
alert(data.result);
}
</script>
<script></script>

刷新页面,发现大工告成。

Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

至此,大部分原理已经讲完了,还有一个问题,这里服务器返回的是getResult(xxx),其中这里的xxx可以当做是经过接口的很多处理,然后塞进去的值,但是这个getResult这个函数名,调用方与其他域服务器这一方怎么约定这个名字是一致的了,况且很多公司自己做服务的,别的公司的开发人员去调用,难道每个人都去那么公司去约定调用函数的名字?怎么可能,所以有人就想出来了一种解决方案,当然不是我~~,其实也很简单啦,也就是把回调的函数名字也一起传过去不就行了,所以代码如下:

<script></script>

other.jsp


代码很简单,也就是传递一个回调函数的参数名,然后经过该接口一系列操作,将返回数据,塞到回调函数里面,调用端的函数就得到了该接口的数据,也就是类似于ajax中succsss:function(data),然后处理data一样,这里的success回调函数,相当于上面的getResult函数。当然你也可以写的优雅一点,比如:

function CreateScript(src) {
$("<script>/script>").attr("src", src).appendTo("body")
}
function jsonp_fun(){
CreateScript("http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult")
}</script>

4、Jquery的JSONP

至此跨域请求的原理已经讲清楚了,但是仍然还有一个问题,总觉得这样用有点怪是不是,如果用jquery的话,调用就很简单了,其实jquery底层实现也是拼了一个script,然后指定src这种方式,跟上面讲的一样,只是jquery封装了一下,显得更加优雅,跟ajax调用方式差不多,所以容易记,代码如下:

<script>
function getResult(data){
alert("through jsonp,receive data from other domain : "+data.result);
}
function jsonp_fun(){
$.ajax({
url:&#39;http://localhost:8888/other/other.jsp&#39;,
type:&#39;post&#39;,
data:{&#39;params&#39;:&#39;fromjsonp&#39;},
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"getResult",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以不写这个参数,jQuery会自动为你处理数据
success: function(data){
},
error: function(){
alert(&#39;fail&#39;);
}
});
}
</script>

<input>

这里的jsonCallback,回调函数设置为getResult,那么返回后会先调用getResult函数中的代码,再调用success函数中的代码,一般情况下,不用定义getResult函数,同样jsonCallback不需要设置,那么就只执行success中的代码,也就跟平时的ajax一样用啦。

所以实际工作用法如下:

function jsonp_fun(){
$.ajax({
url:'http://localhost:8888/other/other.jsp',
type:'post',
data:{'params':'fromjsonp'},
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
success: function(data){
alert("through jsonp,receive data from other domain : "+data.result);
},
error: function(){
alert('fail');
}
});
}

这里没有指定jsonpCallback,实际上jquery底层拼装了一个函数名,当然生成函数规则就没研究了。

Jsonp는 Ajax의 도메인 간 문제를 해결합니다.

补充:

1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;

2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。</script>

3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。

4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Ajax+Session失效后即刻跳转登录页面

ajax操作全局监测,用户session失效怎么处理

위 내용은 Jsonp는 Ajax의 도메인 간 문제를 해결합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.