Jsonp插件

 

1、同域AJAX

使用 eclipse + tomcat 开发

模仿获取手机号码归属地接口,有以下主要组件:

1)TestJsonpServlet.java类返回一个封装号码信息的json数据,访问地址为:http://localhost:8080/JsonpServer/testJsonp.do

2)index.html文件,使用ajax访问后台获取号码信息后展示在页面上面

 

项目结构如下:

 

2、跨域 AJAX 失败

使用 hbuilder 开发环境,jquery 库和 index.html 可以复制前面示例中的文件

项目结构如下:

 

访问http://localhost:8020/AjaxJsonp/index.html页面,点击查询控制台出错:

Failed to load http://localhost:8080/JsonpServer/testJsonp.do: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8020' is therefore not allowed access.

 

这就是浏览器对跨域 ajax 请求的限制

 

3、script 标签的 src 属性可以跨域

我们经常使用 CDN 服务器上面的 js 或者 css 文件,所以 script 标签的 src 属性是可以跨域的


示例1:

修改 localhost:8020 的 index.html 文件,加一个 script 标签,去获取 localhost:8080 的一个 js 脚本,地址为 http://localhost:8080/JsonpServer/script.jsp

<script type="text/javascript" src="http://localhost:8080/JsonpServer/script.jsp"></script>

 

http://localhost:8080/JsonpServer/script.jsp 返回一个 alert("我是跨域的js脚本") 内容

 

 访问 http://localhost:8020/AjaxJsonp/index.html 页面,可以看到弹出了 “我是跨域的js脚本”

 

 

 

 示例2:

 在 localhost:8020 的 index.html 文件全部 script 标签之前再加一个 script 标签,这个里面定义一个函数

 

1 <script type="text/javascript">
2     function fn(data) {
3         alert(data);
4     }
5 </script>

 

 

localhost:8080 的 script.jsp 内容修改为返回一个 fn("我是跨域的js脚本,调用fn函数") 内容

 

访问 http://localhost:8020/AjaxJsonp/index.html 页面,可以看到弹出了“我是跨域的js脚本,调用fn函数”

 

 

示例3:

现在 localhost:8020 的 index.html 文件的 script 标签是固定写在那里的,如果我们使用按钮触发一个函数,函数里面动态地生成一个 script 插入到 head 中,是不是可以让效果更好

把示例1在 localhost:8020 的 index.html 文件加入的 script 标签的 src 删除掉,再添加 jsonp() 函数动态向 head 插入 script

 

按钮点击弹出 “我是跨域的js脚本,调用fn函数”

 

4、开发通用的 jsonp 函数

通过 3 中的几个例子,我们可以知道:

1)js中可以动态地向head插入script标签,并且src属性可以是跨域的地址

2)这个src地址可以返回一个“本地函数调用”,把需要处理的数据当做参数传递给这个函数

3)本地函数需要预先加载到内存


下面我们就可以在 localhost:8020 中开发一个 javascript 版本的通用 jsonp 访问函数

 1 /**
 2  * 跨域的 jsonp 请求函数
 3  * 
 4  * url - 地址
 5  * funcNameArg - 目标服务器用于获取回调函数名的请求参数名
 6  * callBack - 回调函数
 7  */
 8 function jsonp(url, funcNameArg, callBack) {
 9     
10     // 生成一个随机的函数名
11     var rnd = "";
12     for(var i = 0; i < 10; i++)
13         rnd += Math.floor(Math.random() * 10);
14 
15     rnd += "_" + (new Date()).getTime();
16 
17     var funcName = "jsonp_" + rnd;
18 
19     // 把回调函数注册到window上面
20     window[ funcName ] = callBack;
21 
22     // 创建script节点
23     var script = document.createElement("script");
24     script.setAttribute("type", "text/javascript");
25 
26     if(url.indexOf("?") == -1)
27         script.setAttribute("src", url + "?" + funcNameArg + "=" + funcName);
28     else
29         script.setAttribute("src", url + "&" + funcNameArg + "=" + funcName);
30 
31     // 把script节点添加到head上面
32     var head = document.getElementsByTagName("head")[0];
33 
34     head.appendChild(script);
35 
36     // 把script节点移除
37     head.removeChild(script);
38 }

 

修改查询按钮的点击事件函数

 1 var reg = /^1\d{10}$/;
 2 
 3 function getPhoneInfo() {
 4     var phone = document.getElementById("phone").value.trim();
 5     if(!reg.test(phone)) {
 6         alert("请输入手机号码");
 7         return;
 8     }
 9 
10     // 调用jsonp函数进行跨域请求获取手机归属地信息
11     jsonp(
12         "http://localhost:8080/JsonpServer/testJsonp.do?phone=" + phone, 
13         "callback", 
14         function(data) {
15             var phone = "phone = " + data.phone;
16             var country = "country = " + data.country;
17             var province = "province = " + data.province;
18             var city = "city = " + data.city;
19             document.getElementById("info").innerHTML = 
20                             phone + "<br />" + 
21                             country + "<br />" + 
22                             province + "<br />" + 
23                             city + "<br />";
24         }
25     );
26 }

 

修改localhost:8080的servlet代码,让其可以处理兼容jsonp请求

1 // 兼容JSONP请求
2 String callback = request.getParameter("callback");
3 
4 if (callback == null)
5     response.getWriter().print(json);
6 else
7     response.getWriter().print(callback + "(" + json + ");");

 

然后,我们就可以在 localhost:8020 上面跨域访问 localhost:8080 的服务了。服务端返回了一个 jsonp_6316231340_1523246571704(函数名是 jsonp 函数动态生成后传递给服务器的)函数调用

 

5、jquery 的 jsonp 请求

 1 <script type="text/javascript">
 2 
 3     var reg = /^1\d{10}$/;
 4 
 5     function getPhoneInfo() {
 6         var phone = document.getElementById("phone").value.trim();
 7         if(!reg.test(phone)) {
 8             alert("请输入手机号码");
 9             return;
10         }
11         
12         // http://localhost:8080/JsonpServer/testJsonp.do?phone=
13         $.ajax({
14             type:"get",
15             url:"http://localhost:8080/JsonpServer/testJsonp.do?phone=" + phone,
16             dataType: "jsonp",
17             jsonp: "callback",
18             success: function(data) {
19                 var phone = "phone = " + data.phone;
20                 var country = "country = " + data.country;
21                 var province = "province = " + data.province;
22                 var city = "city = " + data.city;
23                 document.getElementById("info").innerHTML = 
24                                 phone + "<br />" + 
25                                 country + "<br />" + 
26                                 province + "<br />" + 
27                                 city + "<br />";
28                 }
29         });
30     }
31 </script>

 

6、示例代码下载

 代码下载

 

posted @ 2018-04-09 20:34  用户不存在!  阅读(143)  评论(0)    收藏  举报