当前位置: 首页 > article >正文

JSONP原理以及示例

同源策略

浏览器的同源策略限制从一个源加载的文档或脚本与来自另一个源的资源进行交互。如果要在js里发起跨域请求获取数据,有两种方式:

  • JSONP;
  • 采用后端代理的方式。

看一个示例:

1)准备两个不同端口的服务:(不同的端口,也是不同域的服务)

接口数据:

 

前端页面:

2)前端代码:

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8"  language="java" %>
<html>
<head><title>跨域测试</title><script src="js/jquery-1.7.2.js"></script><script>$(document).ready(function () {$("#btn").click(function () {$.ajax({url: 'http://localhost:9090/student',type: 'GET',success: function (data) {$(text).val(data);}});});});</script>
</head>
<body><input id="btn" type="button" value="跨域获取数据" /><textarea id="text" style="width: 400px; height: 100px;"></textarea>
</body>
</html>

3)后端接口代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//数据List<Student> studentList = getStudentList();JSONArray jsonArray = JSONArray.fromObject(studentList);String result = jsonArray.toString();response.getWriter().write(result);
}

 4)在前段界面上请求数据:

 

可以看到跨域的请求被浏览器拦截了。

 

JSONP原理

首先我们需要明白,在页面上直接发起一个跨域的ajax请求是不可以的,但是,在页面上引入不同域上的js脚本却是可以的,就像你可以在自己的页面上使用<img src=""> 标签来随意显示某个域上的图片一样。比如我在8080端口的页面上请求一个9090端口的图片:

 

可以得出结论:对于<img><script>这类标签中的src属性是可以跨域请求的(可以看作是浏览器给我们留下一个跨域访问的后门)。

1)原理:

JSONP就是利用了<script>标签的src属性发起的跨域请求,由于script标签的作用是用来执行src指定的js代码。那么我们可以跟后端协商一个函数名,后端将要返回的数据作为函数的参数,一起返回给前端,前端事先定义好该函数,这样就完成了跨域请求。

2)JSONP的缺点:

  • 首先,它没有关于JSONP调用的错误处理,一旦回调函数调用失败,浏览器会以静默失败的方式处理。
  • 其次,它只支持GET请求,这是由于该技术本身的特性所决定的。因此,对于一些需要对安全性有要求的跨域请求,JSONP的使用需要谨慎一点了。
  • JSONP不支持用async:false的方法设置同步。

3)JSONP的优点:

由于JSONP对于老浏览器兼容性方面比较良好,因此,对于那些对IE8以下仍然需要支持的网站来说,仍然被广泛应用。不过,针对高级浏览器,建议还是用CORS 方法。

示例:

1)前端代码:

 

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8"  language="java" %>
<html>
<head><title>跨域测试</title><script src="js/jquery-1.7.2.js"></script><script>//回调函数function showData (result) {var data = JSON.stringify(result); //json对象转成字符串$("#text").val(data);}$(document).ready(function () {$("#btn").click(function () {//向头部输入一个脚本,该脚本发起一个跨域请求$("head").append("<script src='http://localhost:9090/student?callback=showData'><\/script>");});});</script>
</head>
<body><input id="btn" type="button" value="跨域获取数据" /><textarea id="text" style="width: 400px; height: 100px;"></textarea>
</body>
</html>

2)服务端:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//数据List<Student> studentList = getStudentList();JSONArray jsonArray = JSONArray.fromObject(studentList);String result = jsonArray.toString();//前端传过来的回调函数名称String callback = request.getParameter("callback");//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了result = callback + "(" + result + ")";response.getWriter().write(result);
}

说明:当点击"跨域获取数据"的按钮时,添加一个<script>标签,用于发起跨域请求;注意看请求地址后面带了一个callback=showData的参数;showData即是回调函数名称,传到后台,用于包裹数据。数据返回到前端后,就是showData(result)的形式,因为是script脚本,所以自动调用showData函数,而result就是showData的参数。

jquery的jsonp跨域示例:

1、配置dataType:

服务端代码同上,ajax请求时只需配置一个dataType:'jsonp',就可以发起一个跨域请求。

1)前端代码

 

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8"  language="java" %>
<html>
<head><title>跨域测试</title><script src="js/jquery-1.7.2.js"></script><script>$(document).ready(function () {$("#btn").click(function () {$.ajax({url: "http://localhost:9090/student",type: "GET",dataType: "jsonp", //指定服务器返回的数据类型success: function (data) {var result = JSON.stringify(data); //json对象转成字符串$("#text").val(result);}});});});</script>
</head>
<body><input id="btn" type="button" value="跨域获取数据" /><textarea id="text" style="width: 400px; height: 100px;"></textarea>
</body>
</html>

2)效果:

3)说明:

jsonp指定服务器返回的数据类型为jsonp格式。从请求的url上可以看到,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数。

jquery配置jsonp后会随机生成回调函数,当返回jsonp的数据后,执行该回调函数,只不过默认jquery会将这个执行动作映射到success中。

2、指定回调函数:

可以通过jsonpCallback属性指定函数的名称,然后显示的将指定的jsonp回到函数写到<script>下(默认属于window对象),或window对象里。

我们都知道,ajax执行成功后会调用success函数,那上面那种指定了jsonp后,会不会调用success呢?答案是会,而且是先执行jsonp的回调函数,再执行ajax的success函数,例如:

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8"  language="java" %>
<html>
<head><title>跨域测试</title><script src="js/jquery-1.7.2.js"></script><script>function showData (data) {console.info("调用showData");var result = JSON.stringify(data);$("#text").val(result);}$(document).ready(function () {
//            window.showData = function  (data) {
//                console.info("调用showData");
//                var result = JSON.stringify(data);
//                $("#text").val(result);
//            }$("#btn").click(function () {$.ajax({url: "http://localhost:9090/student",type: "GET",dataType: "jsonp",  //指定服务器返回的数据类型jsonpCallback: "showData",  //指定回调函数名称success: function (data) {console.info("调用success");}});});});</script>
</head>
<body><input id="btn" type="button" value="跨域获取数据" /><textarea id="text" style="width: 400px; height: 100px;"></textarea>
</body>
</html>

 

效果:

3、指定回调函数的参数名:

我们可以通过jsonp属性,来指定回调函数的参数名称,默认是callback。

1)前端代码:

 

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8"  language="java" %>
<html>
<head><title>跨域测试</title><script src="js/jquery-1.7.2.js"></script><script>function showData (data) {console.info("调用showData");var result = JSON.stringify(data);$("#text").val(result);}$(document).ready(function () {$("#btn").click(function () {$.ajax({url: "http://localhost:9090/student",type: "GET",dataType: "jsonp",  //指定服务器返回的数据类型jsonp: "theFunction",   //指定参数名称jsonpCallback: "showData",  //指定回调函数名称success: function (data) {console.info("调用success");}});});});</script>
</head>
<body><input id="btn" type="button" value="跨域获取数据" /><textarea id="text" style="width: 400px; height: 100px;"></textarea>
</body>
</html>

2)后端代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//数据List<Student> studentList = getStudentList();JSONArray jsonArray = JSONArray.fromObject(studentList);String result = jsonArray.toString();//前端传过来的回调函数名称String callback = request.getParameter("theFunction");//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了result = callback + "(" + result + ")";response.getWriter().write(result);
}

效果:

4、看看jquery的jsonp是否支持POST方式:

jsonp方式不支持POST方式跨域请求,就算这里指定成POST方式,也会自动转为GET方式;而后端如果设置成POST方式了,那就请求不了了。

jsonp的实现方式其实就是<script>脚本请求地址的方式一样,只是ajax的jsonp对其做了封装,所以可想而知,jsonp是不支持POST方式的。

参考:

https://www.cnblogs.com/chiangchou/p/jsonp.html

 

http://www.lryc.cn/news/2417821.html

相关文章:

  • 【802.11】MCS简介
  • sql语句中distinct的用法
  • Netcat使用学习
  • Jfinal 框架简单入门
  • ftp客户端使用详细说明【linux和windows】
  • STM32F103C8t6驱动MPU6050+HMC5883L+BMP280进行三轴姿态解算
  • JS 中 String 的字符串截取 substr 和 substring 区别的快速记忆方法
  • Ubuntu——apt-get问题
  • 电子工程师必备网址
  • VNC Server远程桌面配置详解
  • 探秘Magnetissimo:自托管的磁力链接搜索引擎
  • react-native基本介绍
  • Attributes(特性)与 Properties(属性)的区别
  • 架构设计(1)-谈谈架构
  • 12 个超好用的免费在线工具建议收藏!(非常详细)从零基础入门到精通,看完这一篇就够了
  • HTTP部分详细讲解以及代码实现(二)
  • epoll原理详解及epoll反应堆模型
  • NLP深入学习——分词(Segmentation )
  • 算法 001. 辗转相除法(欧几里得算法)求最大公约数
  • 视图的基本操作
  • Linux ps命令详解
  • 关于.NET、ASP.NET和ASP
  • Gson的用法详解_Gson如何进行进行序列化和反序列化
  • python的符号lt和gt怎么输入_lt;lt;Python基础教程gt;gt;学习笔记 | 第04章 | 字典...
  • 科普:SMP系统是什么
  • RISC-V CPU+GPU+AI,Imagination创新解决方案带来了哪些惊喜?
  • WebShell
  • SpringSecurity(安全)基础
  • Oracle数据库CDB与PDB
  • ubuntu搜狗输入法