java跨域解决思路及实现原理一

最近在做一个项目,过程中碰到了跨域的问题。由于之前没有遇到过,所以一开始并没有把目光锁定在跨域的问题上,由此也浪费了很长时间。在一番折腾之后真相大白的我决定把它给记录下来。


首先问题的起因是这样的。由于是前后台分离的架构模式,我们的后台实现单独部署到了一台服务器上。而前台的开发则在各自的电脑上进行,在数据请求的过程中发现并不能取到数据。在确定了各自代码都没有问题之后,把前端的页面及js搬到了服务器上,没想到竟然请求成功了。下面便不断百度,踏上了解决跨域的道路。


跨域问题来源:


在开发过程中什么样的情况会导致跨域问题的出现。就java而言,有时候需要将前后端分别部署在两台或者更多的服务器上。这样在前后台通信的时候就会出现无法访问的问题。也有很多时候项目之间需要穿插调用,这也是问题所在。


跨域的问题源自浏览器的安全策略,在不进行跨域处理时,即使你项目部署在同一台机器上的同一个Tomcat容器中,只要不是同一个项目(端口不同),通信就无法完成。


总结一下:不同域名或不同端口的情况下互相访问就会出现跨域问题。


跨域问题解决:


跨域问题的决解又分为两大类:一、客户端   二、服务端


当然在这两类的基础上又有很多不同的解决思路。在我的那个项目中最终采用了后台处理的方式。原因就是这种方式的跨域只支持get而不支持post。


客户端决解思路:


尽管最后没有在客户端解决,但事后还是去百度整理了一番。最多的说法就是jsonp,下面来看一下写法:


$.ajax({
type:"get",
url:"http://192.168.7.141:9000/hello",
dataType:"jsonp",
jsonp:"Callback",
data:{},
success:function(data){}
});
这里的ajax请求中比我们平时常用的多了一个参数就是jsonp:"Callback",这一段。解释一下,这是服务端用于接收callback调用的function名的参数。


我相信很多百度结果都是这样的,为了进一步的了解jsonp的原理又去各大论坛转了一圈。最后皇天不负有心人终于让我解除了心中的疑惑。下面从json和jsonp开始讲起:


json是一种基于文本的数据交换方式,或者叫做数据描述格式。它的优点我就不介绍了。下面再来看看jsonp,jsonp是为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。


jsonp实现原理:


了解json和jsonp的区别之后我们来看看这一跨域解决方案的原理以及演变过程。


我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。代码如下:
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
如上所示,即使remote.js文件与页面不在同一服务器上。但是这种方法还是可以成功调用。这就是jsonp的实现原理。


在此基础上做一点小小变化,在该页面中定义一个函数,然后在远程remote.js中传入数据进行调用。页面代码如下:
<script type="text/javascript">
    var localHandler = function(data){
        alert('本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
    };
    </script>
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>


remote.js文件代码如下:
localHandler({"result":"我是远程js带来的数据"});
运行之后,页面中定义的函数成功接收到远程js文件中传入的数据并成功显示。这样跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?


那么如果让服务端提供的js脚本是动态生成的,而调用者只需传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,这样服务器就可以按照客户端的需求来生成js脚本并响应了。下面来看看页面的代码:
 <script type="text/javascript">
    // 得到航班信息查询结果后的回调函数
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
    };
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // 把script标签加入head,此时调用开始
    document.getElementsByTagName('head')[0].appendChild(script); 
    </script>


对于服务端而言,接收到code参数后对数据进行查询,然后根据callback提供的参数创建一个flightHandler函数并把结果封装到该函数里。这样就实现的完整的数据请求并回传的过程。


回到最开始百度搜到的实现方法,jquery在处理jsonp类型的ajax时,自动帮你生成回调函数并把数据取出来供success属性方法来调用。虽然jquery把jsonp归入了ajax,但其实它们真的不是一回事儿。


以上客户端解决跨域问题就已经介绍完毕了。这里再次提点一下,这种方式的跨域只支持get方法,而不支持post方法。


由于内容比较多,我分了两部分进行讲解。下一部分将会对服务端解决跨域做一个解读。同时会讲一下浏览器cookie跨域的解决方案。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值