为什么要使用 Ajax 跨域?
Ajax的默认行为是同域请求,因为浏览器的同源政策限制了浏览器只在同协议、同域名、同端口下的Web服务器间进行信息的交换,如果是异域名请求时就会存在跨域问题。
那么,什么是跨域?
跨域是指访问的域名、协议、端口三者之间任意一个不同,都可以视为跨域。如果是同域请求时,Ajax能够无障碍工作,但如果跨域请求将导致请求中断等错误。跨域请求是如何处理的呢?这种情况下,我们可以使用 JSONP 技术实现 Ajax 跨域。
接下来,我们来详解 Ajax 跨域( JSONP )调用 Java 后台:
1.首先,客户端需要发送一个含有 Callback 函数名参数的 HTTP GET 请求到服务器端,因为服务器端得到请求过后需要将响应结果组装为一个 JavaScript 方法调用。这个callback函数是客户端提供的,而服务器需要将回调函数以字符串形式作为响应参数的一部分返回。
举例:客户端JS代码
<script>
function jsonpCallback(result) {
console.log("输出结果:",result);
}
window.onload = function() {
var script = document.createElement('script');
script.src = 'http://localhost:8080/jsonp?callback=jsonpCallback';
document.getElementsByTagName('head')[0].appendChild(script);
}
</script>
这段JavaScript代码实现了使用JSONP从后台请求数据,其中回调函数为jsonpCallback。 后台的地址为http://localhost:8080/jsonp。
2.其次,服务器端需要解析出这个参数值,将callback参数值即客户端提供的回调函数名称加入到响应结果字符串之中,返回给客户端即可。
举例:后台JAVA代码
@RequestMapping(value = "/jsonp", method = {RequestMethod.GET})
public @ResponseBody String jsonp(HttpServletRequest request) {
System.out.println("Hello jsonp");
String result = "{\"name\":\"zhangsan\",\"gender\":\"male\",\"age\":20}";
String callback = request.getParameter("callback");
result = callback + "(" + result + ")";
System.out.println(callback);
return result;
}
当客户端请求这个地址时,会触发backendAPI() 方法的调用。该方法以文本格式返回一个包含JSON数据的Unicode字符串,函数执行结束之后,回调函数会被调用,参数 result 会被传入回调函数中。
这里我们假设后台返回的数据如下:{"name":"zhangsan","gender":"male","age":20}
回调函数将会被解析为:
jsonpCallback({"name":"zhangsan","gender":"male","age":20});
最终客户端处理回调函数处理响应的数据。
上述就是使用JSONP实现Ajax跨域请求的完整攻略,通过jsonpCallback函数将JSON对象回调到客户端。
示例:
我们以访问百度搜索接口来演示jsonp的使用。
客户端JS代码
function success(data) {
console.log(data.s);
}
var wd = encodeURI("微博");
var src = "https://www.baidu.com/su?wd=" + wd + "&cb=success";
var script = document.createElement("script");
script.src = src;
document.head.appendChild(script);
上述JS代码模拟了一次百度搜索,其中执行JSON回调函数的成功地址是:https://www.baidu.com/su?wd=微博&cb=success。注意,success为回调函数。
后台JAVA代码
@RequestMapping(value = "/su", method = {RequestMethod.GET})
public @ResponseBody String su(HttpServletRequest request) {
String wd = request.getParameter("wd");
String callback = request.getParameter("cb");
String result = "{\"q\": [\"新浪微博\", \"腾讯微博\", \"微博图片\", \"微博网页版\",\"微博直播\"]}";
result = callback + "(" + result + ")";
return result;
}
该方法以文本格式返回一个包含JSON数据的Unicode字符串,最终回调函数会被解析为:
success({"q": ["新浪微博", "腾讯微博", "微博图片", "微博网页版","微博直播"]});
客户端通过回调函数中处理获得返回的数据。
示例2:
我们在服务器端模拟一下
后台JAVA代码
@RequestMapping(value = "/get", method = {RequestMethod.GET})
public @ResponseBody String get(HttpServletRequest request) {
String callback = request.getParameter("cb");
String result = "{\"name\":\"jack\", \"age\":20 ,\"from\":\"server\"}";
result = callback + "(" + result + ")";
return result;
}
这里我们假设后台返回的数据为:{"name":"jack","age":20,"from":"server"}
回调函数将会被解析为:
testCallback({"name":"jack","age":20,"from":"server"});
最终客户端是这样处理回调函数的:
function testCallback(data) {
console.log(data);
}
var src = "http://localhost:8080/get?name=jack&cb=testCallback";
var script = document.createElement("script");
script.src = src;
document.head.appendChild(script);
上述代码将执行testCallback函数,参数为传入的数据。
通过使用JSONP,我们可以在同一个页面上实现来自跨域站点的数据请求和响应,因为 JSONP 是一种跨域解决方案,即可以无限制地从不同的域名请求数据,这是由于它是使用