ajax前台后台跨域请求处理方式

最近一直在搞公众号前台开发,遇到了ajax跨域请求的问题,像地区的省-市-县三级联动、汽车品牌-车系-车款的三级联动查询等都需要调用外部接口(其他工程项目的接口)完成。下面就分享一下个人解决跨域请求的方案,当然是在后台程序猿大哥的帮助下,我才弄明白了其中的渊源,赶紧记录下来慢慢积累,也希望对大家能有所帮助,还请积极提出意见或建议。

跨域请求需要借助后台代码接收callback回调函数,对json数据进行进一步处理;前台再用ajax请求向服务器发送callback参数,并指定数据格式为jsonp。

一、后台对跨域请求进行处理

1.CarBrandController.java(汽车品牌接口java文件),这里列出的方法主要用来根据不同的level值查询对应的品牌、车系、车款,在这里对跨域请求做一个接收回调函数的处理,如果返回的callback为null,则不是跨域请求,不需要做特殊处理,直接打印json接口数据即可;如果返回的callback不为null,则表示跨域请求,这时要对json数据做一个特殊处理,即在json数据的外层加一对小括号包起来,具体请看HttpAdapter.java文件中的printlnJSONObject方法。

public void json(HttpServletRequest request,HttpServletResponse response){
  Map<String,Object>map=new HashMap<String, Object>();
  String id = request.getParameter("id");      //接收ajax请求带过来的id
  String level = request.getParameter("level");   //接收ajax请求带过来的level
  String callback=request.getParameter("callback"); //接收ajax请求带过来的callback参数
  if ("1".equals(level)) {             //如果level是'1',则查询第一级目录内容
    map.put("results", this.carBrandService.findByAttr(null, "first_letter asc")); //调用查询方法,结果放入map
  } else if ("2".equals(level)) {          //如果level是'2',则查询第二级目录内容
    map.put("results", this.carSerieService.findByAttr("parent_id="+id, "first_letter asc"));//调用查询方法,结果放入map
  } else if ("3".equals(level)) {          //如果level是'3',则查询第三极目录内容
    map.put("results", this.carModelYearService.findByAttr("parent_id="+id, "jian_pin desc"));//调用查询方法,结果放入map
  }
  map.put("level",level);
  if (null==callback) {               //如果接收的callback值为null,则是不跨域的请求,输出json对象
    HttpAdapter.printlnObject(response, map);
  }else{                      //如果接收的callback值不为null,则是跨域请求,输出跨域的json对象
  HttpAdapter.printlnJSONPObject(response, map, callback);
  }
} 

2.HttpAdapter.java(输出对象的java文件),printlnObject方法打印正常json字符串;printlnJSONObject方法对json字符串进行了特殊处理。

/**
 * 打印对象
 * @param response
 * @param object
*/
public static void printlnObject(HttpServletResponse response,Object object){
  PrintWriter writer=getWriter(response);
  writer.println(JSON.toJSONString(object));
}
/**
 * 打印跨域对象
 * @param response
 * @param object
*/
public static void printlnJSONPObject(HttpServletResponse response,Object object,String callback){
  PrintWriter writer=getWriter(response);
  writer.println(callback+"("+JSON.toJSONString(object)+")");
} 

二、前台ajax跨域请求数据

写法1:向服务器发送一个参数callback=?,同时指定dataType为'jsonp'的格式,跨域请求时指定的数据格式必须是jsonp的形式。

function loadData(obj,level,id,value){
  $.ajax({
    url:'http://192.168.1.106:8086/carBrand/json.html?level='+level+'&id='+id+'&callback=?',   //将callback写在请求url后面作为参数携带
    type:'GET',
    async:false,
    dataType:'jsonp',
    success:function(data){
      console.log(data);
      //其他处理(动态添加数据元素)
  });
}   

写法2:callback不需要写在url中,但是要指定jsonp参数为'callback',并给jsonpCallback参数一个值。

function loadData(obj,level,id,value){
  $.ajax({
    url:'http://192.168.1.106:8086/carBrand/json.html?level='+level+'&id='+id,
    type:'GET',
    dataType:'jsonp',
    jsonp: 'callback',          //将callback写在jsonp里作为参数连同请求一起发送
    jsonpCallback:'jsonpCallback1',
    success:function(data){
    console.log(data);
}); }

以上两种写法的含义是一样的,只是写法不同罢了。

接下来补充一下jsonp的工作原理。

三、jsonp跨域的原理解析

jsonp的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。这样说来,这种跨域方式其实与ajax XmlHttpRequest协议无关了.

JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求,我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。这种跨域的通讯方式称为JSONP。

jsonCallback 函数jsonp1236827957501(....): 是浏览器客户端注册的,获取跨域服务器上的json数据后,回调的函数

Jsonp原理:

首先在客户端注册一个callback (如:'jsoncallback'), 然后把callback的名字(如:jsonp1236827957501)传给服务器。注意:服务端得到callback的数值后,要用jsonp1236827957501(......)把将要输出的json内容包括起来,此时,服务器生成 json 数据才能被客户端正确接收。

然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 'jsoncallback'的值 jsonp1236827957501 .

最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。

客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时javascript文档数据,作为参数,
传入到了客户端预先定义好的 callback 函数(如上例中jquery $.ajax()方法封装的的success: function (json))里.(动态执行回调函数)

可以说jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的(qq空间就是大量采用这种方式来实现跨域数据交换的) .JSONP是一种脚本注入(Script Injection)行为,所以也有一定的安全隐患.

注意,jquey是不支持post方式跨域的.

您可能感兴趣的文章:

  • 详解自定义ajax支持跨域组件封装
  • vue-cli开发时,关于ajax跨域的解决方法(推荐)
  • ajax跨域获取网站json数据的实例
  • 原生JS实现ajax与ajax的跨域请求实例
  • 浅谈jquery中ajax跨域提交的时候会有2次请求的问题
  • 原生JS实现Ajax跨域请求flask响应内容
  • Springmvc ajax跨域请求处理方法实例详解
  • 原生js的ajax和解决跨域的jsonp(实例讲解)
  • 基于CORS实现WebApi Ajax 跨域请求解决方法
  • Ajax如何进行跨域请求?Ajax跨域请求的原理
  • AJAX跨域请求数据的四种方法(实例讲解)
  • 详解ajax跨域问题解决方案
(0)

相关推荐

  • 详解自定义ajax支持跨域组件封装

    Class.create()分析 仿prototype创建类继承 var Class = { create: function () { var c = function () { this.request.apply(this, arguments); } for (var i = 0, il = arguments.length, it; i < il; i++) { it = arguments[i]; if (it == null) continue; Object.extend(c.p

  • 基于CORS实现WebApi Ajax 跨域请求解决方法

    概述 ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.但是在使用API的时候总会遇到跨域请求的问题,特别各种APP万花齐放的今天,API的跨域请求是不能避免的. 在默认情况下,为了防止CSRF跨站的伪造攻击(或者是 javascript的同源策略(Same-Origin Policy)),一个网页从另外一个域获取数据时就会收到限制.有一些方法可以突破这个限制,那就是大家熟知的JSONP, 当然这只是众多

  • 原生JS实现Ajax跨域请求flask响应内容

    Ajax方法好,网站感觉跟高大上,但由于Js的局限,跨域Ajax无法实现,这里,讲一下解决办法,前提是需要能够自己可以控制flask端的响应. 主要技术: 修改服务器相应的相应头,使其可以相应任意域名.and设置响应头,使其能够相应POST方法. 实现代码: 这里先放flask代码: from flask import make_response @app.route('/test',methods=['get','post']) def Test(): if request.method=='

  • 浅谈jquery中ajax跨域提交的时候会有2次请求的问题

    我们平时在同域中请求页面什么的时候不会有这种情况,这种情况大多发生在移动端的跨域请求中发生的. 解决方法就是在服务端中加一层过滤HTTP请求的类型,把OPTION等不用的类型过滤掉.就是当请求为非 HTTP中的 GET 和 POST的时候就不执行下面的代码,这样就可以只执行一次请求了. 在ASP.NET中我们用 Request.ServerVariables["REQUEST_METHOD"] == "POST" 或者 Request.ServerVariables

  • 原生js的ajax和解决跨域的jsonp(实例讲解)

    最近慢慢感觉,学再多框架,库,都不如老老实实先把基础弄扎实了. 不说废话,先上一个用ajax请求下本地的一个.txt文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script> window.onload =function(){ var oBtn = d

  • 原生JS实现ajax与ajax的跨域请求实例

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

  • Ajax如何进行跨域请求?Ajax跨域请求的原理

    本文实例为大家分享了Ajax跨域请求的具体实现过程,供大家参考,具体内容如下 下面我们在本地建两个站点演示一下 第一步首先我们在本地搭建好一个Apache服务器:下载地址: 第二步服务器配置好以后,在本地配置好两个虚拟的域名: 第三步我们在C盘建一个文件夹命名为"HTML5": 第四步找到Apache虚拟主机的配置文件,然后打开配置文件 第五步在第三步建的HTML5文件夹下分别建一个文件夹a和文件夹b; 第六步修改Apache虚拟主机的配置文件,如图 第七步修改一下host文件,添加a

  • Springmvc ajax跨域请求处理方法实例详解

    上次给一个网站写网站  前后端分离 最后跪在ajax跨域上面了  自己在网上找了个方法  亲试可用  记录一下 写一个类  继承HandlerInterceptorAdapter package com.util; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.handler.Ha

  • ajax跨域获取网站json数据的实例

    由于自己的公司的项目需要调用视频地址 1:当为链接时:直接在播放器用数据库查找的地址 2:当为外部链接时:直接用window.location.href('数据库查找的地址') 3:当为H5链接时:使用<ifram src="数据库查找的地址">播放 4:当为其余网站链接时,要去第三方网站读取json信息然后把json数据作为url放在播放器中 当为4时,我使用json时会出格式错误 当用jsonp解决跨域问题时,会出现返回格式接收不到 所以我用 public static

  • vue-cli开发时,关于ajax跨域的解决方法(推荐)

    目的:使用vue-cli构建的项目,在开发时,想要访问后台接口获取数据,这时就会出现跨域问题. 在config/index.js中进行如下配置 [即在进行ajax请求时,地址中任何以/api开头的请求地址都被解析为目标地址,target就是你想要的后台接口地址] proxyTable: { '/api': { target: 'https://188.188.18.8', changeOrigin: true, pathRewrite: { '^/api': " } } } "` vu

  • 详解ajax跨域问题解决方案

    今天来记录一下关于ajax跨域的一些问题.以备不时之需. 跨域 同源策略限制 同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性.也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同.这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作. 解决方式 通常来说,比较通用的有如下两种方式,一种是从服务器端下手,另一种则是从客户端的角度出发.二者各有利弊,具体要使用哪种方式还需要具体的分析. 服务器设置响应头 服务器代理 客户端采用脚本回调机制. 方式一 Access-C

  • AJAX跨域请求数据的四种方法(实例讲解)

    由于浏览器的同源策略 ajax请求不可以接收到请求响应回来的数据 请求数据需要调用浏览器的内置构造函数 XMLHttpRequest() 进行 实例对象 var xhr = new XMLHttpRequest(); 注意点 在IE8之前支持的 ActiveXobject("Microsoft.XMLHTTP");  记住要进行兼容处理哦  在这里我就不写了 通过该对象进行获取 获取数据的四种状态  xhr.readyState 该属性保存着请求数据的几种状态 1.xhr.open(请

随机推荐