`
lbyzx123
  • 浏览: 466704 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

js跨域问题解决

 
阅读更多

 

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

下表给出了相对http://store.company.com/dir/page.html同源检测的结果:

 

URL 说明 是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js
同一域名下 允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同文件夹 允许
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同协议 不允许
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip 不允许
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同 不允许
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名 不允许

 

通过jsonp跨域

在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

假定两个应用是同一个ip,只是端口不同,A应用对于8081端口,B应用对于8080端口,A应用访问B应用的数据源。

比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://192.168.1.100:8080/videobrower/video/manage.do?method=getJsonList,那么a.html中的代码就可以这样:
<script>
		function dosomething(jsondata){
			var rows = jsondata;
			for(var i=0;i<rows.length;i++){
				alert('[id:'+rows[i].id+',title:'+rows[i].title+',timelength:'+rows[i].timelength+']');
			}
		}
	</script>
	<script src="http://192.168.1.100:8080/videobrower/video/manage.do?method=getJsonList&callback=dosomething"></script>
我们看到获取数据的地址后面还有一个callback参数,按惯例是用这个参数名,但是你用其他的也一样。当然如果获取数据的jsonp地址页面不是你自己能控制的,就得按照提供数据的那一方的规定格式来操作了。

因为是当做一个js文件来引入的,所以http://192.168.1.100:8080/videobrower/video/manage.do?method=getJsonList返回的必须是一个能执行的js文件,所以这个页面的java代码可能是这样的:
public class VideoManageAction extends DispatchAction {

	public ActionForward getJsonList(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		String callback = request.getParameter("callback");
		List<Video> videos = new ArrayList<Video>();
		videos.add(new Video(78, "喜羊羊与灰太狼全集", 90));
		videos.add(new Video(79, "实拍舰载直升东海救援演习", 20));
		videos.add(new Video(80, "喀麦隆VS荷兰", 30));
		StringBuilder sb = new StringBuilder();
		sb.append('[');
		for (Video video : videos) {
			sb.append("{");
			sb.append("'id':").append(video.getId()).append(',');
			sb.append("'title':'").append(video.getTitle()).append("',");
			sb.append("'timelength':").append(video.getTime());
			sb.append("}");
			sb.append(',');
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append(']');
		request.setAttribute("json", sb.toString());
		request.setAttribute("callback", callback);
		return mapping.findForward("jsonpresult");
	}

}

jsp页面内容如下:(使用el表达式输出后台传过来的数据)
<%@ page language="java" contentType="text/plain; charset=UTF-8" pageEncoding="UTF-8"%>${callback}(${json})
最终那个页面输出的结果是:

dosomething([{'id':78,'title':'喜羊羊与灰太狼全集','timelength':90},{'id':79,'title':'实拍舰载直升东海救援演习','timelength':20},{'id':80,'title':'喀麦隆VS荷兰','timelength':30}])

所以通过http://192.168.1.100:8080/videobrower/video/manage.do?method=getJsonList&callback=dosomething得到的js文件,就是我们之前定义的dosomething函数,并且它的参数就是我们需要的json数据,这样我们就跨域获得了我们需要的数据。

这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了,而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。
<script type="text/javascript" src="jquery.js"></script>
<script>
		function getJsonList(){
			$.getJSON('http://192.168.1.100:8080/videobrower/video/manage.do?method=getJsonList&callback=?',function(jsondata){
					var rows = jsondata;
					for(var i=0;i<rows.length;i++){
						alert('[id:'+rows[i].id+',title:'+rows[i].title+',timelength:'+rows[i].timelength+']');
					}
			});
		}
	</script>

原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数。jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。
jquery对跨域问题的支持:
$.getJSON
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
	$.getJSON("http://crossdomain.com/services.php?callback=?",
	function(result) {
		for(var i in result) {
			alert(i+":"+result[i]);//循环输出a:1,b:2,etc.
		}
	});
</script>

 


$.ajax
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
	$.ajax({
		url:"http://crossdomain.com/services.php",
		dataType:'jsonp',
		data:'',
		jsonp:'callback',
		success:function(result) {
			for(var i in result) {
				alert(i+":"+result[i]);//循环输出a:1,b:2,etc.
			}
		},
		timeout:3000
	});
</script>

$.get
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
	$.get('http://crossdomain.com/services.php?callback=?', {name: encodeURIComponent('tester')}, function (json) { for(var i in json) alert(i+":"+json[i]); }, 'jsonp');
</script>

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics