AJAX跨域总结

2019-06-12  本文已影响0人  前端_吴英杰

概述

  什么是ajax

  它是一种用于创建快速动态网页的技术,通过后台与服务器进行少量数据交换(请求后端数据),ajax可以使网页实现异步更新,即在不更新整个网页的情况下,进行部分网页更新,减少用户的等待时间,加快响应。

  AJAX = 异步 JavaScript 和 XML。AJAX 是一种用于创建快速动态网页的技术。

  XmlHttpRequest对象

  XMLHttpRequest 对象所有的是ajax的基础,XMLHttpRequest 用于在后台与服务器的数据交互 目前所有的浏览器都支持XMLHttpRequest。

  1.XmlHttpRequest对象的主要方法
    a. void open(String method,String url,Boolen async) ------------ 用于创建请求
  
       参数:
           method: 请求方式(字符串类型),如:POST、GET、DELETE...
           url:    要请求的地址(字符串类型)
           async:  是否异步(布尔类型),一般填true
 
    b. void send(String body) -------------------------------------- 用于发送请求
 
        参数:
            body: 要发送的数据(字符串类型)
 
    c. void setRequestHeader(String header,String value)-------------用于设置请求头
 
        参数:
            header: 请求头的key(字符串类型)
            vlaue:  请求头的value(字符串类型)
 
    d. String getAllResponseHeaders() -------------------------------获取所有响应头
 
        返回值:
            响应头数据(字符串类型)
 
    e. String getResponseHeader(String header)-----------------------获取响应头中指定header的值
 
        参数:
            header: 响应头的key(字符串类型)
 
        返回值:
            响应头中指定的header对应的值
 
    f. void abort()-------------------------------------------------终止请求

  2.XmlHttpRequest对象的主要属性
    a. Number readyState
         状态值(整数)
         详细:
              0-未初始化,尚未调用open()方法;
              1-启动,调用了open()方法,未调用send()方法;
              2-发送,已经调用了send()方法,未接收到响应;
              3-接收,已经接收到部分响应数据;
              4-完成,已经接收到全部响应数据;
 
    b. Function onreadystatechange
         当readyState的值改变时自动触发执行其对应的函数(回调函数)
 
    c. String responseText
         服务器返回的数据(字符串类型)
 
    d. XmlDocument responseXML
         服务器返回的数据(Xml对象)
 
    e. Number states
         状态码(整数),如:200、404...
 
    f. String statesText
         状态文本(字符串),如:OK、NotFound...

  跨域

  JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。那什么是跨域呢,简单地理解就是因为JavaScript同源策略的限制,a.com域名下的js无法操作b.com或是c.a.com域名下的对象。

  当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”

  跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。

构建原生ajax

注意:

  XmlHttpRequest支持:
    IE7+, Firefox, Chrome, Opera, etc.
    IE6, IE5不支持XmlHttpRequest,所以使用ActiveXObject("Microsoft.XMLHTTP")对象实现。

  第一步:获得XMLHttpRequest对象
  第二步:设置状态监听函数
  第三步:open一个连接,true是异步请求
  第四部:send一个请求,可以发送一个对象和字符串,不需要传递数据发送null
  第五步:在监听函数中,判断readyState=4&&status=200表示请求成功
  第六步:使用responseText、responseXML接受响应数据,并使用原生JS操作DOM进行显示

    var xhr = null;
    if(XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
    // 定义回调函数
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            // 已经接收到全部响应数据,执行以下操作
            var data = xhr.responseText;
            alert(data);
        }
    };
    // 指定连接方式和地址----文件方式//默认异步请求 true
    //xhr.open('get', "/test", true);
    xhr.open('POST', "/test", true);
    // 设置请求头
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
    // 发送请求
    //xhr.send();
    xhr.send('n1=1;n2=2;');

  平时我们用的最多的还是jQuery的ajax,jQuery其实就是一个JavaScript的类库,其将复杂的功能做了上层封装,使得开发者可以在其基础上写更少的代码实现更多的功能(想要了解)。

  其他,类似vue的axios是通过promise实现对ajax技术的一种封装。就像jQuery实现ajax封装一样。(了解axios

ajax的跨域请求

  浏览器同源策略并不是对所有的请求均制约:

    制约: XmlHttpRequest
    无效: img、iframe、script等具有src属性的标签

  那么如有解决跨域请求的问题呢?下面提供了几种方法实现跨域请求。

  1.JSONP

  利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。

  JSONP优点是兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性。

  (1)JSONP的流程

  声明一个回调函数,其函数名(如fn)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)。

  创建一个<script>标签,把那个跨域的API数据接口地址,赋值给script的src,还要在这个地址中向服务器传递该函数名(可以通过问号传参:?callback=fn)。

  服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是fn,它准备好的数据是fn([{"name":"jianshu"}])。

  最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用执行之前声明的回调函数(fn),对返回的数据进行操作。

    <script type="text/javascript">
        function fn(data) {
            alert(data.msg);
        }
    </script>
    <script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=fn"></script>

  其中 fn 是客户端注册的回调的函数,目的获取跨域服务器上的json数据后,对数据进行在处理。
  最后服务器返回给客户端数据的格式为:

    fn({ msg:'this  is  json  data'})

  (2)jQuery的jsonp请求

emsp; JSONP都是GET和异步请求的,不存在其他的请求方式和同步请求,且jQuery默认就会给JSONP的请求清除缓存。

    $.ajax({
        url:"http://crossdomain.com/jsonServerResponse",
        dataType:"jsonp",
        type:"get",//可以省略
        jsonpCallback:"fn",//->自定义传递给服务器的函数名,而不是使用jQuery自动生成的,可省略
        jsonp:"jsonp",//->把传递函数名的那个形参callback变为jsonp,可省略
        success:function (data){
             console.log(data);}
        });

  2.CORS

  1.CORS原理
  整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

  2.CORS优缺点
  CORS要求浏览器(>IE10)和服务器的同时支持,是跨域的根本解决方法,由浏览器自动完成。
  优点在于功能更加强大支持各种HTTP Method,缺点是兼容性不如JSONP。
  只需要在服务器端做一些小小的改造即可:

    header("Access-Control-Allow-Origin:*");
    header("Access-Control-Allow-Methods:POST,GET");

  例如:网站http://localhost:63342/ 页面要请求http://localhost:3000/users/userlist 页面,userlist页面返回json字符串格{name: 'Mr.Cao', gender: 'male', career: 'IT Education'}

  JAVA后台配置

    JAVA后台配置只需要遵循如下步骤即可:
    第一步:获取依赖jar包下载 cors-filter-1.7.jar, java-property-utils-1.9.jar 这两个库文件放到lib目录下。(放到对应项目的webcontent/WEB-INF/lib/下)
    第二步:如果项目用了Maven构建的,请添加如下依赖到pom.xml中:

    <dependency>
        <groupId>com.thetransactioncompany</groupId>
        <artifactId>cors-filter</artifactId>
        <version>[ version ]</version>
    </dependency>

  在响应头上添加Access-Control-Allow-Origin属性,指定同源策略的地址。同源策略默认地址是网页的本身。只要浏览器检测到响应头带上了CORS,并且允许的源包括了本网站,那么就不会拦截请求响应。

  3.使用HTML5中新引进的window.postMessage方法来跨域传送数据

  window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

  调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。

  需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

  上面所说的向其他window对象发送消息,其实就是指一个页面有几个框架的那种情况,因为每一个框架都有一个window对象。在讨论第二种方法的时候,我们说过,不同域的框架间是可以获取到对方的window对象的,而且也可以使用window.postMessage这个方法。下面看一个简单的示例,有两个页面

    //发送信息页面 http://localhost:63342/index.html
    <html lang="en">  
    <head>  
        <meta charset="UTF-8">  
        <title>跨域请求</title>   
    </head>  
    <body>  
        <iframe src="http://localhost:3000/users/reg" id="frm"></iframe>  
        <input type="button" value="OK" onclick="run()">  
    </body>  
    </html>  
    <script>  
       function  run(){  
            var frm=document.getElementById("frm");  
            frm.contentWindow.postMessage("跨域请求信息","http://localhost:3000");  
       }  
    </script>

    //接收信息页面 http://localhost:3000/message.html
    window.addEventListener("message",function(e){  //通过监听message事件,可以监听对方发送的消息。
        console.log(e.data);  
    },false);

上一篇下一篇

猜你喜欢

热点阅读