先看下直接发起ajax请求会怎么样
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>跨域测试</title>
<script src="js/jquery-3.3.1.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<button type="button" id="btn">跨域获取数据</button>
<textarea id="text" style="width: 400px;height: 100px;">
</textarea>
</body>
<script type="text/javascript">
// https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=电话号码
$.ajax({
url:'https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=电话号码',
type:'GET',
success:function(data){
$(text).val(data.province);
}
});
</script>
</html>
可以看到跨域请求因为浏览器的同源策略被拦截了
jQuery动态创建script标签,发起Ajax请求
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jquery-3.3.1.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<button type="button" id="btn">跨域获取数据</button>
<textarea id="text" style="width: 400px;height: 100px;">
</textarea>
</body>
<script type="text/javascript">
// 'https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=电话号码'
function showData(data){
$("#text").val(data.province);
}
$('#btn').click(function(){
alert("进来没!");
//向头部输入一个脚本,该脚本发起一个跨域请求
var scriptStr = $("<script src='https:\/\/tcc.taobao.com\/cc\/json\/mobile_tel_segment.htm?tel=电话号码&callback=showData' charset='utf-8'><\/script>");
$('body').append(scriptStr);
});
</script>
</html>
后端代码类似于这样的格式:
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();
//将数据转为JSON对象
JSONArray jsonArray = JSONArray.fromObject(studentList);
//将JSON对象转为JSON字符串
String result = jsonArray.toString();
//前端传过来的回调函数名称
String callback = request.getParameter("callback");
//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了
result = callback + "(" + result + ")";
//做出响应
response.getWriter().write(result);
}
jquery的jsonp方式
-
服务端代码不变,js代码如下:最简单的方式,只需配置一个dataType:‘jsonp’,就可以发起一个跨域请求。jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数名称。
-
这里的success就跟上面的showData一样,如果有success函数则默认success()作为回调函数。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jquery-3.3.1.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<button type="button" id="btn">跨域获取数据</button>
<textarea id="text" style="width: 400px;height: 100px;">
</textarea>
</body>
<script type="text/javascript">
// 'https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=电话号码'
$('#btn').click(function(){
$.ajax({
url:"https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=电话号码",
type:"GET",
dataType:"jsonp",
success:function(data){
$('#text').val(data.province);
}
});
});
</script>
</html>
回调函数你可以写到
<script>
下(默认属于window对象),或者指明写到window对象里,看jquery源码,可以看到jsonp调用回调函数时,是调用的window.callback。
看调用结果,发现,请求时带的参数是:callback=showData;调用回调函数的时候,先调用了指定的showData,然后再调用了success。所以,success是返回成功后必定会调用的函数,就看你怎么写了。
jQuery实现JSONP自定义函数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jquery-3.3.1.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<button type="button" id="btn">跨域获取数据</button>
<textarea id="text" style="width: 400px;height: 100px;">
</textarea>
</body>
<script type="text/javascript">
function showData(data) {
console.info("调用showData");
var result = JSON.stringify(data);
$("#text").val(result);
}
$("#btn").click(function() {
$.ajax({
url: "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=电话号码",
type: "GET",
dataType: "jsonp", //指定服务器返回的数据类型
jsonpCallback: "showData", //指定回调函数名称
success: function(data) {
console.info("调用success");
}
});
});
</script>
</html>
更改callback这个名称
前台代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jquery-3.3.1.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<button type="button" id="btn">跨域获取数据</button>
<textarea id="text" style="width: 400px;height: 100px;">
</textarea>
</body>
<script type="text/javascript">
function showData(data) {
console.info("调用showData");
var result = JSON.stringify(data);
$("#text").val(result);
}
$("#btn").click(function() {
$.ajax({
url: "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=电话号码",
type: "GET",
dataType: "jsonp", //指定服务器返回的数据类型
jsonp:"theFunction",//指定参数名称
jsonpCallback: "showData", //指定回调函数名称
success: function(data) {
console.info("调用success");
}
});
});
</script>
</html>
后台代码:
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();
//将数据转为JSON对象
JSONArray jsonArray = JSONArray.fromObject(studentList);
//将JSON对象转为JSON字符串
String result = jsonArray.toString();
//前端传过来的回调函数名称
String theFunction = request.getParameter("theFunction");
//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了
result = theFunction + "(" + result + ")";
//做出响应
response.getWriter().write(result);
}
看一下JSONP是否支持post请求
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/jquery-3.3.1.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<button type="button" id="btn">跨域获取数据</button>
<textarea id="text" style="width: 400px;height: 100px;">
</textarea>
</body>
<script type="text/javascript">
function showData(data) {
console.info("调用showData");
var result = JSON.stringify(data);
$("#text").val(result);
}
$("#btn").click(function() {
$.ajax({
url: "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=电话号码",
type: "POST",
dataType: "jsonp", //指定服务器返回的数据类型
jsonpCallback: "showData", //指定回调函数名称
success: function(data) {
console.info("调用success");
}
});
});
</script>
</html>
电话号码这个接口是支持POST请求的,他的后台可能做了一些处理;如果后台没有做处理,可能出现以下情况: