整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Ajax跨域教程-动脑学院(一)

Ajax跨域教程-动脑学院(一)

<script src="https://lf6-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>

由于上传头条的视频不清晰,需要高清视频可以加Q:1587389342,需要源码也可以加Q领取。

知识点:

B/S:客户端主动去请求(request)而服务器被动响应(response)

AJAX的概念,即“Asynchronous Javascript And XML”

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面或者使用iframe。

本地环境和服务器环境

AJAX写法

浏览器兼容

if(window.ActiveXObject){

//ActiveX是浏览器的插件

xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");//IE 678 OPEAR OLD

}else if(window.XMLHttpRequest){

xmlHttp=new XMLHttpRequest();//NEW

}

状态码

readyState

存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。

0: 请求未初始化

1: 服务器连接已建立

2: 请求已接收

3: 请求处理中

4: 请求已完成,且响应已就绪

status

200: "OK"

404: 未找到页面

为什么响应有文本和XML格式

因为当下最流行的数据交互格式,一种是json(responseText),另外一种是XML(responseXML)

* JSON.parse(xmlHttp.responseText)

NodeJs搭建服务器环境

安装node(建议不要更改安装目录)

打开cmd输入node -v查看版本,如果查看得到代表安装成功

输入命令npm i -g express

输入命令npm i -g expre-generator

在桌面创建一个server

打开cmd命令行,cd 桌面的server目录,回车

进入server目录,输入express server

再进入server/server目录,输入npm install

讲代码复制到public目录下

通过npm start启动服务器

最后打开浏览器在地址栏输入http://localhost:3000/ajax.html

跨域JSONP

什么是域 id地址加上端口号(例:http://192.168.0.146:3000/)

什么是JSONP

本质跟AJAX没有任何关系

另外一种服务器和非服务器资源之间的潜规则

结论:script标签的src属性是可以实现跨域的

JSONP暴露出来的数据按照我的经验来讲一定不是非常机密的数据

form提交和ajax提交比较

form:全局表单提交,整个页面刷新

* a的href

* window.location.href

ajax:异步局部提交,局部页面刷新

通常提交了数据之后要跳转页面或者刷新整个页面的时候就不用ajax

英文单词:

before[之前]、after[之后]、status[状态]、asynchronous[异步的]、ready[准备好]、request[请求]、response[响应]

作业:

请参考“作业”文件夹下的文档内容,并按时完成。

做一家受人尊敬的企业,做一位受人尊敬的老师。 -by 动脑学院

  • 复现Ajax跨域问题
  • Ajax跨域介绍
  • Ajax跨域解决方案
  • 一. 在服务端添加响应头Access-Control-Allow-Origin
  • 二. 使用JSONP解决
  • 小结

复现Ajax跨域问题

  • 做两个简单的小项目复现Ajax跨域问题. 后端语言使用Java
  • 首先是一个简单的订单系统, 通过访问/loadOrderList, 最终以json串形式返回订单集合. 该项目使用Tomcat发布在7070端口.
@RequestMapping("/loadOrderList")
@ResponseBody
public List<Order> loadOrderList(String uid){
 //模拟订单数据
 Order o1=new Order();
 o1.setId("111");
 o1.setTotal(333.33);
 o1.setDate("2019-4-29");
 Order o2=new Order();
 o2.setId("222");
 o2.setTotal(444.44);
 o2.setDate("2019-5-29");
 Order o3=new Order();
 o3.setId("333");
 o3.setTotal(555.55);
 o3.setDate("2019-6-29");
 List<Order> list=new ArrayList<>();
 list.add(o1);
 list.add(o2);
 list.add(o3);
 return list;
}
  • 在另一个项目中做一个向订单系统发送一个ajax请求, 获取订单集合. 该项目使用Tomcat插件发布在9090端口.
//index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>Title</title>
 <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.js"></script>
 <script type="text/javascript">
 function sendAjax() {
 $.post("http://localhost:7070/order/loadOrderList", "uid=1234", function (data) {
 alert(data);
 });
 }
 </script>
</head>
<body>
 <a href="javascript:sendAjax()">sendAjax</a>
</body>
</html>

  • 点击sendAjax超链接向订单系统发送ajax请求.


  • 通过开发者工具发现虽然服务器以状态码200响应回来, 但是控制台却报错了.



  • 这就是Ajax跨域出错的一种表现, 下面分析原因.

Ajax跨域介绍

  • Ajax跨域问题是由浏览器的同源策略造成的, 首先要理解源这个概念.
  • 我们可以通过协议+域名+端口确定一个源. 在上面的示例中, 你可以把一个项目理解为一个源. Ajax请求可以对源内的资源发起访问, 但是不同源之间进行Ajax就会有问题.
  • 当向不同源的资源发起Ajax请求时, 浏览器会加上Origin字段来标识源
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Length: 8
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Host: localhost:7070
Origin: http://localhost:9090 协议+域名+端口
  • 服务器会根据Origin字段决定是否同意这次请求, 如果Origin指定的源不在许可范围内, 服务器会返回一个不带有Access-Control-Allow-Origin字段的响应. 浏览器解析时发现缺少了这个字段, 就会报错. 这种错误不能通过状态码识别, 因为状态码很有可能就是200(见上面的案例).

Ajax跨域解决方案

  • 下面介绍最常用Ajax跨域解决方案.

一. 在服务端添加响应头Access-Control-Allow-Origin

  • 既然我们已经知道了Ajax跨域失败是因为响应中缺少了响应头Access-Control-Allow-Origin, 那么就想办法加上去.
  • 以Java项目为例, 在后端我们使用CORSFilter过滤器加上该响应头.
  • (假设是Maven项目), 首先在pom.xml中添加坐标
<dependency>
 <groupId>com.thetransactioncompany</groupId>
 <artifactId>cors-filter</artifactId>
 <version>2.5</version>
 <scope>runtime</scope>
</dependency>
  • 然后在web.xml中对过滤器进行配置.
 <filter>
 <filter-name>CORS</filter-name>
 <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
 <init-param>
 <param-name>cors.allowOrigin</param-name><!--这个标签是关键, *代表所有源都能访问-->
 <param-value>*</param-value>
 </init-param>
 <init-param>
 <param-name>cors.supportedMethods</param-name>
 <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
 </init-param>
 <init-param>
 <param-name>cors.supportedHeaders</param-name>
 <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>
 </init-param>
 <init-param>
 <param-name>cors.exposedHeaders</param-name>
 <param-value>Set-Cookie</param-value>
 </init-param>
 <init-param>
 <param-name>cors.supportsCredentials</param-name>
 <param-value>true</param-value>
 </init-param>
 </filter>
 <filter-mapping>
 <filter-name>CORS</filter-name>
 <url-pattern>/*</url-pattern>
 </filter-mapping>

  • 配置后重启订单项目, 再次发起Ajax请求可以看到成功返回数据, 响应头中包含了Access-Control-Allow-Origin, 值为发起Ajax请求的源.



二. 使用JSONP解决

  • 上面直接通过过滤器添加响应头的方法可以说是对症下药, 那么还有没有什么偏方呢?
  • 还真的有. 在jsp文件中经常通过通过<script>标签引入一段js代码, 这段代码通常来源于网络, 也就是不同源. 那么我们不妨通过<srcipt>标签完成Ajax请求, 这样便顺带解决了跨域问题.
  • 下面还是沿用上面的案例进行演示.
  • 我们对发送ajax的jsp进行修改
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>Title</title>
 <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.js"></script>
 <script>
 function doCallBack(data){
 var str=JSON.stringify(data);
 alert(str);
 }
 </script>
</head>
<body>
 <script src="http://localhost:7070/order/loadOrderList3?uid=111&callBack=doCallBack"></script>
</body>
</html>
  • 上面的代码中, 我们首先定义了doCallBack()函数, 它接收一个字符串参数, 并且会把接收到的字符串显示出来.
  • 然后在<body>标签中编写<script>标签, 我们将通过<script>标签请求订单系统, 订单系统将会返回一段js代码, 这段js代码会调用doCallBack()方法.
  • 为了能够拼接出doCallBack(字符串参数...)js代码, 我们在订单系统中作如下操作.
@RequestMapping("/loadOrderList3")
@ResponseBody
public String loadOrderList3(String uid, String callBack){
 //模拟订单数据
 Order o1=new Order();
 o1.setId("111");
 o1.setTotal(333.33);
 o1.setDate("2019-4-29");
 Order o2=new Order();
 o2.setId("222");
 o2.setTotal(444.44);
 o2.setDate("2019-5-29");
 Order o3=new Order();
 o3.setId("333");
 o3.setTotal(555.55);
 o3.setDate("2019-6-29");
 List<Order> list=new ArrayList<>();
 list.add(o1);
 list.add(o2);
 list.add(o3);
 //拼接js代码
 String result=callBack + "(" + JSON.toJSONString(list) + ")";
 return result;
}

  • 这个想法是不是很妙? 明白这个原理之后, 我们可以使用jQuery方便进行JSONP操作, 在上面的代码中我们人为指定了一个名为doCallBack的函数, 而jQuery会随机用时间戳生成一个函数名, 原理和上面是一样的.
  • 所以完成一开时点击超链接发送Ajax请求只需要如下几步.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>Title</title>
 <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.js"></script>
 <script>
 function sendAjax(){
 $.getJSON("http://localhost:7070/order/loadOrderList3?callBack=?","uid=111",
 function (data) {
 var str=JSON.stringify(data);
 alert(str);
 });
 }
 </script>
</head>
<body>
 <a href="javascript:sendAjax()">sendAjax</a>
</body>
</html>

小结

  • 上面两种解决办法在思路上有着本质的不同. 方案一抓住CORS跨域访问问题的本质, 在后端加上响应头解决跨域问题. 方案二JSONP利用的是<script>标签能够跨域获取js代码的特性, 绕过跨域问题.

文来自阿里云云栖社区,未经许可禁止转载。

更多资讯,尽在云栖科技快讯~

来科技快讯看新闻鸭~

快点关注我认识我爱上我啊~~~


摘要: Flask、Python、Django、框架、服务器、客户端、浏览器、交互、WEB、Python前端、CSS、JAVA、HTML、H5、PHP、JavaScript、JQuery、分布式开发

jQuery对AJAX的支持
$.ajax()
语法:
$.ajax({请求参数的json对象});
请求参数对象的属性:
URL:字符串 表示异步请求地址
type:字符串 请求方式 get或post
date:传递到服务端的参数 参数字符串("name=dfh&age15")或json
datetype:响应回来的数据格式
HTML
xml
text
script
json
jsonp:有关跨域的响应了格式
success:
回调函数 响应成功后的回调函数
error:
回调函数 请求或响应失败时的回调函数
beforSend:
回调函数 发送AJAX请求之前的回调函数
如果return False 则终止请求发送

跨域(Cross Domain)
什么是跨域?
HTTP协议中有一个策略 "同源策略"
同源:
多个地址中 相同的协议 相同的域名 相同的端口
在HTTP中 必须是同源地址中 必须是同源地址才能相互
发送请求 非同源拒绝请求(<script>和<img>除外)
非同源的网页相互发送请求的过程就是跨域
跨域只能接受GET请求 不能接受POST请求
跨域解决方案:
通过<script>标记向服务器发送请求
由服务器资源指定前端页面的那个方法来执行响应的数据
jQuery的跨域:
jsonp json with padding
$.ajax({
url:"xxx",
type: "get",
dataType:'jsonp', //指定跨域访问
jsonp: "callback", //定义了callback函数名 以便于callback传递过去的函数名
jsonpCallback:'xxx' //定义了传递过去函数的名字 jsonp的回调函数
});

三种形式的跨域请求