加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ajax跨域

发布时间:2020-12-15 21:40:13 所属栏目:百科 来源:网络整理
导读:出于安全方面的考虑,Web浏览器中JavaScript无法访问其他服务器上的资源,这个限制仅在Web浏览器中有效。而跨域就是通过某些手段来绕过这个限制,实现不同服务器之间通信的效果。ajax跨域可以通过jsonp、cros或者服务端代理实现。 jsonp jsonp利用script标签

出于安全方面的考虑,Web浏览器中JavaScript无法访问其他服务器上的资源,这个限制仅在Web浏览器中有效。而跨域就是通过某些手段来绕过这个限制,实现不同服务器之间通信的效果。ajax跨域可以通过jsonp、cros或者服务端代理实现。

jsonp

jsonp利用<script>标签不受限制访问其他服务器资源的特点,通过<script>的src发送跨域访问的url以及参数。jsonp需要对服务端返回的数据格式做修改,服务端返回的数据应该是一个可执行的JavaScript代码。
如果json数据格式如下

{"sex": "男","name": "小明","age": 20}

那么jsonp格式应该如下

callback({"sex": "男","age": 20});

其中callback是回调函数,一般由jsonp客户端提供。jQuery提供了jsonp请求,下面用jsonp获取京东的订单列表数据。

$.ajax({
    url: 'http://order.jd.com/lazy/getOrderListCountJson.action',// jsonp路径
    data: {},// 参数 
    //jsonp: 'callback',// 服务端接收回调函数的参数,默认是callback
    //jsonpCallback: '',// 回调函数名称,如果不指定jQuery自动生成
    dataType: 'jsonp'         // 请求类型
}).done(function(json){
    // 请求成功处理
    console.dir(json);
}).fail(function(){
    // 请求失败处理
});

如图所示,jsonp请求属于script请求。

jsonp结果如下

cors

CORS(Cross-Origin Resource Sharing)定义一种跨域访问的机制,可以让AJAX实现跨域访问。实现此功能非常简单,只需服务器添加响应标头Access-Control-Allow-Origin。目前大部分的PC浏览器和几乎所有的移动浏览器都支持CROS。

浏览器 CROS支持情况
IE 从IE8开始支持,其中IE8/IE9部分支持,IE10/IE11完全支持。
Firefox Firefox 3.5+ 开始支持
Chrome Chrome 3+ 开始支持
Opera Opera 12+ 开始支持
Safair Safair 4+ 开始支持

服务端代码

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSON;

@Controller
@RequestMapping("/test")
public class TestController {

    /** * 返回json * * @param response */
    @RequestMapping("/json.do")
    public void json(HttpServletResponse response) {
        response.setContentType("text/plain");
        response.setCharacterEncoding("utf-8");

        // 添加响应头,支持跨域ajax请求
        response.setHeader("Access-Control-Allow-Origin","*");

        // 构造json
        Map<String,Object> json = new HashMap<String,Object>();
        json.put("date",new Date());
        json.put("name","小明");
        json.put("age",18);

        try {
            // 这里用FastJSON生成JSON字符串
            response.getWriter().write(JSON.toJSONString(json));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

页面代码

$.ajax({
    url: 'http://localhost:8280/logweb/test/json.do',dataType: 'json',success: function(json){
        console.dir(json);
    },error: function(){
    }
});

如图所示,从CSDN页面发起ajax跨域请求。




如果服务端没有设置响应头Access-Control-Allow-Origin,浏览器会有如下错误提示。

服务端代理

服务端不受跨域请求的限制,可以在服务端代理ajax请求。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;

/** * ajax请求代理 * 用Apache HttpClient模拟发送请求 * 所有请求都以POST方式提交 */
@WebServlet("/ajax/proxy/servlet")
public class AjaxProxyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    // ajax请求的实际url名称
    private final String destUrlParamName = "destUrl";
    // 编码
    private final String encoding = "utf-8";

    protected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
        // 获取请求参数
        List<NameValuePair> params = getParameters(request);

        // ajax请求的实际url
        String destUrl = request.getParameter(destUrlParamName);         
        HttpPost httppost = new HttpPost(destUrl);

        CloseableHttpClient httpclient = HttpClients.createDefault();
        UrlEncodedFormEntity formEntity;

        try{
            // 设置请求参数
            formEntity = new UrlEncodedFormEntity(params,encoding);
            httppost.setEntity(formEntity);

            CloseableHttpResponse httppostResponse = httpclient.execute(httppost);

            try{
                HttpEntity httpEntity = httppostResponse.getEntity();
                InputStream httpis = httpEntity.getContent();
                OutputStream os = response.getOutputStream();
                int len = 0;
                byte[] buffer = new byte[1024];

                while((len = httpis.read(buffer)) != -1){
                    os.write(buffer,0,len);
                }

                os.flush();
            }finally{
                httppostResponse.close();
            }

        }catch(Exception e){
            e.printStackTrace();
        }

    }

    /** * 获取ajax请求参数 * @param request * @return 返回参数对数组 */
    private List<NameValuePair> getParameters(HttpServletRequest request){
        Enumeration<String> paramNames = request.getParameterNames();
        List<NameValuePair> params = new ArrayList<NameValuePair>();

        while(paramNames.hasMoreElements()){
            String name = paramNames.nextElement();

            // 判断,如果参数是ajax请求的目标路径,则忽略
            if(!destUrlParamName.equals(name)){
                params.add(new BasicNameValuePair(name,request.getParameter(name)));
            }
        }

        return params;
    }

}

ajax跨域请求代码

/** * ajax代理请求 * @param options ajax配置参数,请参考$.ajax()的配置 */
function ajaxProxy(options){
    // ajax代理的url
    var proxyUrl = 'http://localhost:8280/logweb/ajax/proxy/servlet',destUrl = options.url;

    // 把代理url和实际url替换
    options.url = proxyUrl;

    if(!options.data){
        options.data = {};
    }

    // 把实际url放到参数destUrl中,传递给服务端发送代理请求
    options.data.destUrl = destUrl; 
    options.type = 'post';
    return $.ajax(options);
}

下面用ajax代理请求博客园的分页数据

ajaxProxy({
    url: 'http://www.cnblogs.com/mvc/AggSite/PostList.aspx',// 博客园分页url
    dataType: 'html',// 数据格式是html
    data: {
        CategoryId: 808,CategoryType: "SiteHome",ItemListActionName: "PostList",PageIndex: 2,ParentCategoryId: 0
    },success: function(html){
        console.dir(html);

        //把html直接输出到页面
        $('body').html(html);
    },error: function(){
        console.dir(arguments);
    }
});

请求参数如图所示

执行结果如图所示

总结

优点 缺点
jsonp 不存在兼容性问题,大部分js库都支持jsonp。 通过script发送请求,url长度有限制,不能发送超过2048字节的请求。服务端需要提供专门的jsonp接口。
cros Web端和服务端基本上不用做代码修改。 不能完全兼容所有浏览器。
ajax代理 不存在兼容性问题 相对于jsonp和cros,性能可能较差。服务端需要提供专门的代理。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读