JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的
<script>
元素是一个例外。利用<script>
元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
Jsonp原理(可以先看 Demo)
首先在客户端注册一个callback,然后把callback的名字传给服务器。此时,服务器先生成 json 数据,然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp。最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里。(动态执行回调函数)
Demo 演示
一、服务端:建立 web 工程 test_jsonp_server
服务端监听在 8080 端口。
源码下载地址:https://gitee.com/liupeifeng3514/test_jsonp_server
Servlet
package com.lpf.jsonp;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestJsonpDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
public TestJsonpDemo() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 回调函数名
String callBack = request.getParameter("callback");
// json数据
String jsonData = "{\"name\":\"挖坑埋你\"}";
// jsonp格式的数据
String jsonp = callBack + "(" + jsonData + ")";
// 设置头信息
response.setHeader("Content-type", "application/json;charset=utf-8");
// 输出jsonp格式的数据
response.getWriter().println(jsonp);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
web.xml
<servlet>
<servlet-name>TestJsonpDemo</servlet-name>
<servlet-class>com.lpf.jsonp.TestJsonpDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestJsonpDemo</servlet-name>
<url-pattern>/testJsonpDemo</url-pattern>
</servlet-mapping>
二、客户端:建立 web 工程 test_jsonp_client
客户端监听在 8081 端口。
源码下载地址:https://gitee.com/liupeifeng3514/test_jsonp_client
index_jsonp.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 实例</title>
</head>
<body>
<div id="divCustomers"></div>
<script src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
function callbackFunction(data) {
document.getElementById('divCustomers').innerHTML = data.name;
}
</script>
<script type="text/javascript" src="http://127.0.0.1:8080/test_jsonp_server/testJsonpDemo?callback=callbackFunction"></script>
</body>
</html>
index_no_jsonp.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 实例</title>
</head>
<body>
<div id="divCustomers"></div>
<script src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$.ajax({
url:"http://127.0.0.1:8080/test_jsonp_server/testJsonpDemo?callback=callbackFunction",
success:function(result) {
document.getElementById('divCustomers').innerHTML = data.name;
},
timeout:3000
});
</script>
</body>
</html>
三、运行,验证
跨域不只是指域名(IP)不同,端口号不同也是跨域(即使域名、IP都相同,但端口号不同)
1、跨域失败
可以看到服务端正确响应了,也返回了正确的数据,但浏览器禁止对返回的数据进行处理。
2、跨域成功
页面正确显示了服务端返回的数据。
参考文章:前端必备HTTP技能之同源策略详解