美文网首页
AJAX跨域总结

AJAX跨域总结

作者: 前端_吴英杰 | 来源:发表于2019-06-12 15:31 被阅读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);
    
    

    相关文章

      网友评论

          本文标题:AJAX跨域总结

          本文链接:https://www.haomeiwen.com/subject/pxrffctx.html