一般使用ajax来访问不同服务器的数据,可行吗?
做个实验:
第一步:在本服务器中使用ajax技术访问本服务器数据
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-
1.4.1/jquery.min.js"></script>
<script type="text/javascript">
//让页面加载完成后执行该函数
$(function(){
$.get("http://manage.jt.com/test.json",function(data){
alert(data.name);
})
})
</script>
</head>
<body>
<h1>JSON跨域请求测试</h1>
</body>
</html>
test.json的内容是:
{"id":"1","name":"tom"}
结论:本地服务器访问本地服务器数据http://manage.jt.com/test.json,可以正常访问。
第二步:Ajax远程服务器调用
说明: 由www.jt.com发起请求,请求manage.jt.com中的test.json数据,测试是否成功!!!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-
1.4.1/jquery.min.js"></script>
<script type="text/javascript">
/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
$(function(){
alert("我执行了AJAX");
//利用jQuery发起AJAX请求
$.get("http://manage.jt.com/test.json",function(data){
alert(data.name);
})
})
</script>
</head>
<body>
<h1>JSON跨域请求测试</h1>
</body>
</html>
访问www.jt.com.test.html
结论:
1.发现由www.jt.com向manage.jt.com发起请求时,并没有获取到结果。
2.浏览器居然访问后台服务器数据成功了状态码200
3.浏览器虽然访问成功,不能获取响应数据.
那这是因为什么原因呢?就是跨域的问题
浏览器—同源策略
说明:浏览器规定当发起请求时,要求 协议名称://域名:端口三项都相同,满足同源策略的规定,浏览器可以正
常解析服务器数据。如果有一项不满足,则违反了浏览器的同源策略,那么浏览器可以正常请求数据,但是不予
解析返回值(处于安全性的考虑)。
利用JSONP实现跨域的基本原理
javaScript中src说明:
浏览器由于同源策略的限定,禁止ajax发起跨域请求.但是javaScript中的src属性可以实现跨域的请求. 浏
览器对于src属 性具有开放策略.(不管)
想法: 能否利用javaScript中的开放策略,实现跨域访问???
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript">
/*自定义回调函数 */
alert("开始跨域访问")
function hello(data){
alert(data.name);
}
</script>
<!--该json一直保存到浏览器中等待调用,但是没有函数名称无法调用 -->
<script type="text/javascript" src="http://manage.jt.com/test.json">
</script>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-
1.4.1/jquery.min.js"></script>
</head>
<body>
<h1>JS跨域问题</h1>
</script>
</body>
</html>
此时在manage.jt.com中的资源需要进行封装
原来的test.json是:
{"id":"1","name":"tom"}
现在的test.json是:(需要的是hello封装json数据后,回调函数function hello(data){}才可以调用资源对象)
hello({"id":"1","name":"tom"})
结果是可以的
跨域原理总结:
1.利用javeScript中的src属性,实现跨域
<script>type="text/javascript"src="http://manage.jt.com/test.json"></script>
2.自定义回调函数
说明:利用src属性引入数据之后,页面要想调用,需要通过函数名称,才能正确调用!
/*自定义回调函数 并且给函数起的名称叫hello */
function hello(data){
alert(data.name);
}
解释: 自定义回调函数的目的就是为远程调用的数据起名.
3.远程调用的返回值经过特殊的格式封装 "callback(JSON)"
callback指定是回调函数的名称.可以灵活改变,此时的资源封装结果是:
hello({"id":"1","name":"tom"})
JSONP介绍
JSONP(JSON with Padding)(JSON胖)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是server1.example.com的服务器沟通,而 HTML 的 元素是一个例外。利用 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。
JSONP原理
ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进
行了调用,这样实现了跨域。
jQuery实现JSONP
页面实现:
jsp页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSONP测试</title>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-
1.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
alert("测试访问开始!!!!!")
$.ajax({
url:"http://manage.jt.com/web/testJSONP",
type:"get", //jsonp只能支持get请求
dataType:"jsonp", //dataType表示返回值类型
//jsonp: "callback", //指定参数名称,也就是封装的函数名默认是callback
//jsonpCallback: "hello", //指定回调函数名称
success:function (data){ //data经过jQuery封装返回就是json串
alert(data.itemId);
alert(data.itemDesc);
}
});
})
</script>
</head>
<body>
<h1>JSON跨域请求测试</h1>
</body>
</html>
说明:启动jt-web服务器,然后打来浏览器,访问:http://www.jt.com/JSONP.html
编辑jt-mange后台服务器
说明:在后台服务器中创建对应的controller资源进行资源调度,从而去处理由前台发起的ajax跨域请求,进行数据的获取,具体代码实现如图所示:
传递一个item对象过去
@RestController
public class JSONPController {
/**
* 需求:跨域访问,获取商品的详情信息
* http://manage.jt.com/web/testJSONP?callback=xxx
* 参数:?callback=xxx
* 返回值语法规定: callback(json数据);
*/
@RequestMapping("/web/testJSONP")
public String testJSONP(String callback) {
ItemDesc itemDesc=new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("JSONP跨域测试");
//将对象转化为JSON
String json = ObjectMapperUtil.toJSON(itemDesc);
//将数据封装
return callback+"("+json+")";
}
}
说明:打开浏览器,输入http://www.jt.com/JSONP.html,开始测试:
结论:利用JSONP进行跨域请求,是可以获取到数据的。
JSONP工具API—JSONPObject
需求:由于使用JSONP进行跨域请求时,需要我们手动进行数据的封装,才可以实现跨域请求。因此为了提高开发效率,我们可以使用工具api简化开发。具体实现如下代码所示:
@RestController
public class JSONPController {
/**
* 1.定义返回值结果 JSONPObject
* 2.实现数据的封装 参数1:回调函数 参数2:后台服务器返回数据
* @param callback
* @return
*/
@RequestMapping("/web/testJSONP")
public JSONPObject jsonp2(String callback) {
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(200L)
.setItemDesc("JSONP调用成功!!!!");
return new JSONPObject(callback, itemDesc);
}
}