一.AJAX是个啥?
1.1 概述
- 说到AJAX,不得不提到一门编程语言----JavaScript诞生于1995年。起初JS的主要目的是处理以前由服务器端负责的一些表单验证。
- 当时走在技术革新最前沿的Netscape(网景)公司,决定着手开发一种客户端语言,当时就职于Netscape公司的布兰登·艾奇开始着手计划将1995年2月发布的LiveScript同时在浏览器和服务器中使用。为了赶在发布日期前完成LiveScript的开发,Netscape与Sun公司成立了一个开发联盟。而此时,Netscape为了搭上媒体热炒Java的顺风车,临时把LiveScript改名为JavaScript
- 所以从本质上来说JavaScript和Java没什么关系。
- AJAX不是一门编程语言,只是一种技术。它和JS有关,也就是说它的代码运行在客户端(因为JS运行在浏览器),而不是服务端。
- AJAX的全称是Asynchronous JavaScript And XML(异步的JS和XML)
1.2 同步和异步
- 关于“同步”与“异步”,目前可以粗浅地理解为:
- 同步:我填完所有表单后,点击“提交”按钮,所有内容才会一起发给服务器!
- 异步:我刚填完“账号”,点击填写“密码”时,页面就让JS拿着“账号”去让服务器校验了。那么我们填写“密码”时就知道刚才填写的“账号”是不是重复/错误的.
1.3 JS实现异步请求原理
- 简单说一下JS实现异步请求的原理:原先JS的请求由JS引擎负责,同步请求依赖JS引擎。当JS发起一个请求后,如果没有收到服务端响应,它是不能做任何事的,处于等待状态,效率很低。而异步请求是由JS委托AJAX引擎(XMLHttpRequest对象)发起的。请求交给AJAX引擎后,JS引擎就可以抽身做别的事,等到AJAX引擎拿到响应给它后,它再渲染数据显示即可!(老板让秘书去买咖啡,自己继续工作)
- 到这里,我们虽然还没有深入了解AJAX具体如何落实到代码上实现异步请求,但也算有了初步印象。
二.JSON是个啥?
2.1 概述
- 先来绕个弯。还记得在学习JavaSE的IO流时,我们曾经学过序列化流吗?分为序列化流和反序列化流。通过这两种流可以实现对象序列化和反序列化。
- 那么何谓对象序列化? 对象序列化是将对象状态转化为可保持或传输的过程。一般的格式是与平台无关的二进制流。可以将这种二进制流持久保存在磁盘上,也可以通过网络将这种二进制流传输到另一个网络节点。
- 首先,我们要明白,对象一般只在内存中“存活”。我们在程序中new了一个对象,当我们关闭电脑时,只要内存一断电,对象就会消失。如果希望下次打开时还能再现这个对象,必须在关机前将此对象从内存中取出保存在硬盘中,也就是持久化。 而所谓的对象序列化,可以有两种用途,其中一种便是将对象通过二进制流在硬盘中持久化(作为文件)。
- 序列化的另一种用途,则是用作不同工程间的远程通讯。对于一般的SSM应用(单一系统),是不需要将对象序列化的。但一旦涉及远程调用,或者分布式系统,一个系统调用另一个系统的服务时,POJO对象必须支持序列化。这样,在一个系统中序列化后,经过网络传输到达另一个系统时,可以通过反序列重构对象,使得在这个系统也可以使用这个对象。怎么做到让对象序列化?只要让POJO类实现Serializable接口就可。
public class User implements Serializable{}
- 为什么我之前创建POJO类时不用implements Serializable接口?因为以前做的项目,都是单系统,也就是部署在单一服务器,所有的调用都是在这个服务器上的。
- 所谓的序列化,实质上是将内存中的对象变为二进制数据(流)传到遥远的另一台服务器,在该服务器上再由二进制数据转为内存中的对象。典型应用是分布式系统。
-
分布式则是一个服务器的系统调用另一个服务器的系统,不同电脑间,我必须把我的Java对象序列化成二进制数据通过一根网线连到另一台电脑去。关于分布式,可以参考传智的第二个大项目,电商项目
-
大家有没有想过,Java希望别人能用自己的对象,搞了个序列化,难道我JS就不能有这需求吗?我希望后端能用我的JS对象!
-
好吧,这纯粹是瞎几把扯。后端是不可能直接用前端的对象的。但是,这个设想还是不错的。我可以通过双方约定的某种数据格式,把JS对象按此格式传到后端,后端再通过某种方式把这个格式的数据解析成Java对象。JS对象→某种格式传输→Java对象,通过这个过程,也相当于在后端使用JS对象了。当然啦,严格意义上Java后台是不可能使用JS对象的。
-
现在问题在于,所谓的“某种格式”到底是哪种格式呢?
-
我们在学习JavaWeb时,曾经用xml文件充当过“数据库”。
- 这说明XML是可以用来表示对象的。这也是为什么当初AJAX会选择XML作为数据交换格式。但是由于JS本身对JSON支持很好(JSON就是JS的人),在JS前端(主场作战)比XML在解析方面更有优势,轻量且效率高。比如你要取person的age,在把JSON串转为JS对象后,可以直接person.age得到!所以在前后端交换数据方面,JSON毫无疑问是最佳选择。
- JSON作为一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
- 也就是说,不管你后台用Java/PHP/C#,都可以用JSON交互数据。而且不止web,Android和IOS也可通过JSON和后端交换数据。因为JSON是一种文本格式,任何语言都有字符串类型。
- 但XML作为配置文件的首选标记语言,在自己的领域又甩JSON一条街。因为JSON表示嵌套逻辑关系时显得很凌乱,要不断地在一个值里面再塞入另一个值。不如XML直观。
-
虽然上面说了一大堆,但是可能部分初学者心里还是有很多疑问。没关系,这一小节会继续展开。
-
JSON的英文全称是JavaScript Object Notation,也就是JS对象标记法。
-
很多朋友可能会和我一样被这个概念搞得稀里糊涂。比如你们在看视频时,会经常听到“JSON是一种数据交换格式”,然后恍然大悟:哦,JSON是一种格式呀。但是看着看着,又听老师说:好,来看一下,这个就是JSON对象。不是说JSON是一种数据交换格式吗?怎么格式还有对象?
-
视频中你会看到老师介绍下面的内容:
【JSON对象】
var person = {"name":"zhangsan","sex":"男","age":24}//json对象
alert(person.name);//zhangsan
alert(typeof person);//object
- 这特么不是JS的字面量对象吗?
【JS对象:字面量表示】
var person = {
name:"小明",
age:20,
sayHi:function(){
console.log("haha");
},
eat:function(){
console.log("heihei");
}
}
注:字面量对象的键加不加双引号都是可以的。
- 所以,所谓的JSON对象和JS对象有啥关系啊?
- 其实,按我的理解,压根就没有什么JSON对象!JSON从始至终只是一种数据交换格式,它是一套规范。它的载体是字符串,而不是什么对象。为什么JSON格式会选择字符串作为表现的载体?因为字符串在某种意义上是通用的。不管是JS,还是Java/PHP/C#,都是支持字符串的。用对象则不合适,JS有JS对象,Java有Java对象…如果是字符串就很好办,大家都有这个类型。而且各个语言都提供了解析JSON字符串到自己对象的方法。
- 后端传给前端的JSON串在前端解析后可能是数组或者JS对象。解析后得到的对象往往被人们称为JSON对象(如果是数组,也是JSON对象数组,即元素是JSON对象)。
- 前端传给后端的JSON串则转化为对应后端语言的对象,比如Java的类对象。
- 但我们要清楚,其实,JSON对象就是JS对象的子集而已
JSON,载体是字符串,可以用字符串表示对象/数组
JSON串表示对象,解析为对象
JSON串表示数组,解析为数组
-
现在网上的培训视频,说法还是比较乱的。反正大家心里要清楚,JSON一定是一种文本,有自己的特定格式。JSON对象其实就是一种JS对象。
-
JSON对象:符合JSON格式的JS对象
var person = {"name":"zhangsan","sex":"男","age":"24"}//json对象
alert(person.name);//zhangsan
alert(typeof person);//object
-
上面的person对象之所以被称为JSON对象,只是因为这个JS对象符合JSON格式。相比来说,JSON的语法要比JS更严格。但是要注意,有些情况下有人会把JS对象也叫做JSON对象,而且代码执行时也能成功。虽然不是很规范,但是你要能听得懂。而且我们要尽量遵守规范。
-
JSON字符串:符合JSON格式的字符串
我们常说的JavaScript中的字符串是单引号或者双引号引起来的。
var person = '{"name":"zhangsan","sex":"男","age":"24"}';//json字符串
alert(person);//{"name":"zhangsan","sex":"男","age":"24"}
alert(typeof person);//string
- 从第三行代码可以看出person本质是个字符串,只是这个字符串符合JSON格式,所以称为JSON字符串。
- 那么JSON格式有什么要求呢?以下是我能找到的格式要求:
- 对象表示为键值对,键必须加双引号
- 值不能是方法函数,不能是undefined/NaN
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
- 上面的JSON对象和JSON字符串都符合上述规范,所以原本普通的JS对象和字符串被称为JSON对象和JSON字符串。可以这么说:JSON的语法比JS对象语法更为严格,可以认为是JS对象语法的子集。
-
结论:
-
JSON是一种数据格式,载体是字符串,因为字符串是通用的
-
广义上,JSON对象是语法更为严格的JS对象
-
JSON串必须符合JSON格式
-
另外,在实际使用AJAX时,data参数值的键加不加双引号都是可以的。(参见下一节的代码格式)
-
三.AJAX与JSON的代码格式
- 既然要用ajax异步请求,那么代码格式是怎样的呢?
前端表单
ajax-key/value格式,其中第一、第二种格式是JS对象(你也可以认为是JSON对象),但这种请求方式,其实在后端看来都是key/value形式的
ajax-JSON格式。JSON的载体是字符串,此时要指定contentType:application/json;charset=utf-8,以告诉后端程序我传的是JSON格式,方便后端应对
-
总结起来就是:
- 请求时有两种选择:key/value格式 or JSON串
- 请求时key/value格式比JSON串常用,因为要用JSON串的话,在前端还要把对象转成串,麻烦
- 响应时都返回JSON串。ajax中dataType:"json"的意思是:指定按什么格式解析返回值。因为返回的是JSON串,自然要按JSON解析,否则会出错。
-
大家会发现,我们在上面讲了半天的JSON,其实到头来,就是两种:
- 请求
- JSON串(不常用)
- key/value(JSON对象/JS对象/参数拼接)(常用)
- 响应
- JSON串(常用)
- 请求
-
上面的图只画了表单和对应的几种ajax格式,都是讲前端如何发送,没有说后端如何处理。
-
其实后端的转化主要涉及
- 接收前端请求:(JSON串/key-value格式)→Java对象
- 响应:Java对象→JSON串
接收key/value格式的请求大家都很熟悉了,就是根据键取值,而且在SpringMVC中都是自动封装到形参里的。就不说了。
- 如何接收JSON串呢?在SpringMVC框架中,提供了@RequestBody注解来将JSON格式的请求参数自动封装成Java对象。
- 也就是说不论前端传key/value格式还是JSON串,都能转为Java对象。那么一系列处理后,如何转为JSON串返回呢?在SpringMVC框架中,还提供了@ResponseBody注解来将Java对象转为JSON串返回给前端。
SpringMVC之所以能完成自动转化,主要是依靠JackSon第三方jar包。也就是说,如果没有SpringMVC,我们也可以引入JackSon帮我们转换格式。- 特别注意下Controller里的方法,加不加@ResponseBody的区别(以return "index"为例):
- 不加注解,会把return的字符串解析为视图地址,跳转到对应页面
- 加了注解,不跳转页面,会把return的字符串当做数据返回
如果是key/value格式,就不用加@RequestBody,SpringMVC会自动把参数封装到形参对象中
留疑:
- 关于什么远程调用序列化以及json的理解
- 对于ajax方法中,data参数类型可以是哪几种,有何区别
引用原文