开发者学堂课程【高校精品课-上海交通大学 -互联网应用开发技术:Ajax&JSON 3】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/76/detail/15764
Ajax&JSON 3
内容介绍:
一·举例
二·跨域
三·FetchAPI
四·Body
五·JSON
一、举例
Ajax回顾一下,增加按钮Get Books,点击后会从后台通过Ajax的方式把数据捉回并在前台呈现。
起初没有数据,呈现后看到类似这种法文ér和中文的字符可以正常显示。
为了实现这样的功能,做了一些设置,后台数据本身是从后台的数据库里捉的并有一个OR映射的book
它在映射BOOK这张表。前台发出请求后Servlet在后面专门做这件事情--把数据组装后返回。
Servlet要做的事情是从数据库拿,
在这里写reponse. set ContentType时写charset=UTF-8‘,含义是要显示字符是0~255之间(也就是一个字节能表示的所有字符)。
实际上中文不是这样,在0~255仔细查看,0~127时能看到的东西,128~255看到的像乱码的东西。
汉字是约定由两个128到255之间的字符构成的,如果你不设UTF-8‘的话,那它出来时就会被看成乱码;如果你把它设成UTF-8‘,会把两个字符解释成一个汉字,你才能看到。
除了汉字,像刚才看到的法文里带有像音标符号一样的东西,它也需要这种大于0~127的字符才能正常显示,所以是用UTF-8‘。
在举例中,前台和后台是两个工程,“http:// localhost:3000”来自前端,后端是在“http:// localhost:8080”端口上。因为端口号不一样,所以会被认为是两个不同的圆。
这种跨域访问是不允许的,要在response.setHeader里加“Access-Control-Allow-Origin”来允许跨域访问。含义是前面字段允许跨域访问,后面是允许从哪个域来的东西能访问当前的工程。前端是在“http:// localhost:3000”端口上,允许来自这里的请求访问当前的应用。
这是在解决两个问题,其他没有什么差异。从数据库里找出所有的book,把它组装成JSON的字符串并返回。这里用的是前面导入的fast JSON库里的API。
JSON库有很多种,如果选择不是这种可能不同。最终JSON是一个重文本,无论如何通过response的writer写出一个重文本是表示一个JSON对象的字符串,这样前端就能拿到这个数据。
看到第一个说是JSON的API,第二个是说要解决乱码问题,重设置字符集后写一下浏览器兼容。字符串写完在做序列化时要保证是以浏览器兼容方式写出的。这样,无论是哪个浏览器都可以正常看到值,像法文里带个和中国拼音里的二声相同的符号,不能正确解释。
做完这些事后能看到正确的页面。如何去改造之前大家看到的react举例。
先来看同源的问题不是Java或者前面看到react的框架。实际上,同源的问题是HTTP协议规定:认为跨域的资源共享是要受限的,不是直接能访问。
二、跨域
域是由域名加协议或者端口号合起来定义的。
尽管刚才两个都在本地,看起来主机名一致,但一个是3000端口,一个是8080端口,算两个不同的域。
简单来说,跨域资源共享意味着当一个网站
比如https://domain-a.com网站,通过XML.HttpRequest。去要求获取一个来自于https://domain-b.com/data.json的一个资源时,就不允许它会受限,使用FetchAPI就可以解决这个问题。
但它不是唯一的解决途径,比如用Axios也可以。因为这种东西比较类似,用Fetch就要解决所谓的对资源共享同源策略的控制。
如果网站本身来自domain-a.com,里面的图片来自domain-a.com,属于同一个源可以访问。在加载页面时,页里嵌的图片能访问。有一张图片来自于domain-b.com,这时会发现来自于domain-a.com的请求,要求去捉取domain-b.com的资源,domain-b.com这一端就会对你的请求认为是跨域请求,会做控制。
如果没有任何的特别控制,不做设置的话,它直接不允许。如果在响应里加信息(允许跨域控制),并且指明是domain-a.com,这时domain-a.com就可以拿到domain-b.com的补贴,这是跨域。
同一个圆的前提是协议相同,端口相同,主经营相同。
所以协议http://localhost或者IPlocalhost后面要加端口,因为端口必须要相同,所以3000和8080算两个域,如果不加特殊处理直接就拿不到了。
这里举例,什么算不同的?
相对于http://store.company.com/dir/page.html:这里有个端口(81)是不同的,它告诉你直接拿是failure。你看前面这部分是不同的,所以它也是failure。
再看这里是用S,它要加保护套(所以这个也failure)。上面两个为什么可以?协议都是http://store.company.com端口相同。
比如80没有指令,这两个可以被认为来自于同源,这三个不是同源,会受到跨域控制。跨域是通过Ajax的请求或把Ajax包装API来访问时会进行控制,不允许跨域共享(如果你不加特别特殊的约定)。
在response里设置hide,通过这种方式可以加载些什么,比如用到的字体、WebGL的一些文理,在浏览器里想展示的一些像open gl一样3D效果、用别人写好的一些文理或图片video或CSS,这些来自于另外域,想把它嵌到网页里来等于是对这些东西有一个跨域的访问,看到提供资源的那端允许做这样的事情。
做设置,让每个网站允许你做这样的事情能拿到它,对Ajax或Fetch控制是害怕中间有安全的漏洞,经常使用fetch来捉取数据,
可以用原生的X mail http request大家的X请求,也可以用框架比如iqvery。
fetch是把它包装好,不用去写东西,这是一个比较好的方案。fetch的请求到后台有相应的跨域控制可以拿到数据。
三、FetchAPI
注意不是fetch跨域,是你在后台做允许跨域,然后拿fetch才捉到。在fetch在捉数据时可以设置(无论请求还是响应)具体参数。当做请求或响应发出一个请求得到响应,这就是fetchAPI。
它最简单的形式是在代码里只需要指定url是什么,对什么资源在进行访问,请求发出后,后台就会有相应的东西处理。如果允许跨域,结果返回后就在response里,注意response实际上是有headr、有body的东西。
通过命名函数,让它返回JSON的值是data。拿着它就可以做你想要的事情。代码加了get books,它的fetch在捉向后端发的请求(项目运行起来,后面是server监听url。
对这里发请求后,返回的东西在后台把它组装成JSON。它的含义是要从返回的内容里把JSON拿出来作为匿名函数的返回值,得到 data的值拿出后就已经是JSON了。
通过set state当前的页面的state属性就变成data了。data从执行画绘制Excel时作为initial data属性传进。当前文件的data在最开始举例是前排版数据写死的。现在是空(开始绘制时当然是空)当点增加按钮(get books)后。
点击时调用get books通过fetch获取后台的数据并更新状态被绘制出来,页面就看到加载的所有数据,这是fetch最简单形式。
在fetch里除了指定url,像要到哪一个位置去访问外可以有参数。在大括号里,第一个打星号表示默认值,没做任何的设置,没有任何参数,它默认get。第二个mode要跨域。第三个是返还的结果要不要缓存,还有个默认值detauit是看你乱写也可以强制不缓存或强制缓存中。
去访问时,要用户名和密码证书,默认是同源的证书是个比较复杂的问题,可以忽略。
Headers是发请求后(内容默认),返回来的响应里才会认为这里一定有一个JSON。方法是能把在response里JSON的对象取出来,下面重定向。
比如用户没登录过,如果需要就可以设置,那这里Fetch函数,是API的完整的一个写法,Fetch完后会返回一个值follow。通过定义函数把刚才那些东西都包含在内。
函数有一个参数值url会传递给Fetch,data一开始是空的,data会是你发送的结果里的body,把它转成JSON以后的内容,发送response JSON。
Uploading JSON data
const data = { username: 'example' };
0
fetch('https://example.com/profile',{ method: 'POST',// or'PUT’ headers:{
'Content-Type': 'application/json'},
body: JSON.stringify(data),})
then((response)=> response.json()).then((data) => {
console.log('Success:',data)})
catch((error) => {
console.error('Error:', error);});
所有的破损方法可以按方式来写,只要传一个url、data,发送一个参数up等于42打包到body里,有数据后拿到这边发Fetch出去,拿到response后把包的JSON给它返回,直接在函数调用完后继续就得到包含JSON,直接取出来在data,后面就是你自己的逻辑。
这里比较简单,在前排的浏览器操作直接挡log把图写,如果你要做更复杂的,比如你想去解析JSON的内容,写代码Fetch的PPI,对着它有很多操作,fetch是有两个语言,大家去参考一下。
Fetch API
https://developer.mozilla.org/en-US/docs/Web/API/Fetch-APl
https://www.w3cschool.cn/fetch- api/
fetch完全不是一些功能,另外刚才讲的跨域的方案前后端都要配合看,fetch刚只发一个post请求出去,当然默认get也可以,举例是get。
前端要发JSON对象到后端首先请求是一个post,在body里就要把想发出的JSON放进去,data会转成JSON字符串放到body里,通过post去对着这里发请求时把内容类型设成JSON,对着url发出请求,并且把JSON对象作为请求体的发夹。
服务器端拿到请求后对body进行解析,能知道JSON是什么。发完请求后会得到个响应(认为也是个JSON),所以取出JSON对象,对JSON对象的数据去查看。能得到它,在console里打log。
过程中任何一个地方发生问题,可能会捕获异常,发一个JSON对象给后台。在uplo时,去创建一个新文件发到分析端。可以用put或者post都可以,原理是改写用put,新创建用post。
对着avatar用put方法去发,设置一个body,关键是body里是
then((response) => responsejson()).then((result) => {
console.log('Success:', result);
.catch((error) => {
console.error('Error:', error);
拿到返回的值后,这里不一定非用data,传承关系是会返回一个response(返回对象),付给response去执行箭头函数,把response对象上调JSON函数返回的结果作为返回值,给它返回值后就赋给data(result),会把返回的JSON对象赋给result。
Uploading multiple files
- Files can be uploaded using an HTML<input type="file"multiple/>
input elementFormDataO and fetchO.
const formData=new FormData();
const photos =document.querySelector('input[type="file"][multiple]');
formData.append('title', 'My Vegas Vacation'); for (leti =0;i< photos.files.length;i++){
formData.append(photosphotos.files[i]);
fetch('https://example.com/posts',{
method: 'POST' body: formData})
then((response)=> responsejson())
then((result) => { console.log('Success:', result); }).catch((error) => {console.error('Error:', error);});
代码跟刚才没区别,关键上面是个body,很显然,一个文件的内容发到后台去,传多个文件在后面再加一个model,要在body的对象里做循环,把所有对象给它追加进来,其他的文件是一样的。
比如Fetch它可以跨域,也可以是同源,如果当前工程在 localhost3000端口,其实是想去捉这样一张图片回来,捉完后知道结果会放到response,如果不是说明错误,,抛个error;如果是OK,直接返回它里面捉第一个二进制的对象(ban banary)。
图片的内容return后附给blob获取source属于你自己的控制了解。上面关键是response回来后实际上是有状态的,可以去检查它是不是OK的状态。
在header里放一个定义的对象(请求放一些自己定义的东西),等于你定制一个镜头对象,request是未来在Fetch时当参数传给它就去,request就相当于你前面写的内容(Url等等这些内容都在)。这对圆括号里所有东西。
定义好一个request后,直接在fetch里就传request调用完后返回,直接拿内容做处理。看到response对象,第一个是不是OK,这表示得到它的结果是不是OK,实际上是它的状态包含两部分:一部分就是数字表示,HP的返回码404、505都属于这一类;第二个是状态表示的含义,去捉取你的内容会得到OK。在进行处理时可以针对状态去处理。
四、Body
body在请求里(在body)放东西(可以是JSON,也可以是别的),比如定义表格数据,form是你在url页面里定义一个form。Form里可能有一些input内容,给它打包后变成一个formbody。
因为要下订单肯定要post过去,信息过去很阻碍这两个位置。举例注意统一在后台解决跨域的问题,如果把这句话注销掉,你运行举例在前台页面里打开浏览器的控制台,就会发错误信息出去。
Fetch要受到跨域的控制,但在后台又没有任何的跨域允许操作。前台就得到异常,这是后台的程序,两个工程的结构解决跨域问题。
一个工程、两个工程有什么问题,跨域问题肯定是存在的。写对方的一个表,把这一段定义成一个常量后不断的去引用它,但是不管怎样要写绝对地址。
还有一种做法是一个工程是个外部的应用,不存在跨域问题,在前端的页面里像在访问时都用相对中心,表示整个应用的根部之或是要访问的应用相对不进来。
前后端分离或合在一起有优点、有缺点。分离的好处是接下来会看到微信、react native、corolova(开发移动端的应用框架)、hutter等等,用这些或用原生的android、Java去开发前端,用的后台都是同一个后端。用前端、后端、前端后端分离可以写成这样。
当然还包括reat/uue写的页面端或没有写的页面端,前后端分离后,后端是在复用,然后放到一起不存在话语,但总是会扩充话语,不可能把所有东西打到一个工程。一个优选做前后端分离来实现刚才说的一些逻辑。
五、JSON
JSON is a text-based data exchange format derived from
JavaScript that is used in web services and other connected applications.
JSON defines only two data structures: objects and arrays
- An object is a set of name-value pairsand an array is a list of values.
-JSON defines six data types: string,number,object,array true,false and null
四种编程中,在Java和javascript里涉及到如何组装一个锥子、怎么解析锥子。JSON的库非常多,尤其在后台Java这端,代码也可能出现至少有两种:一种是fastJSON,另一种是其他的。
看到举例,用这些库的API微有差异,前端也是一样。
涉及对JSON的组装和解析,组装是有Java对象或是一组Java数据把它从Java的语言变成一个纯文本的JSON对象。反过来你从JSON对象里知道描述的一些信息和Java是一对,这是解析过程。
对javascript也是一样,之所以这么复杂,是因为JSON是文本,html 、CSS、JSON、xml是纯文本讲究格式不同。大家都说中文,你说古文,我说现代文;他说诗歌,我说元曲。
JSON是Javascript定义纯文本的数据描述方式,JSON里有两种数据结构:一种是JSON对象,是earthquake的对象标记法motation。比如Javascript对象标记法notation是用just read描述对象的方法,首先定义一种主语结构是对象;第二类东西叫数组。定义数组的目的只是为了让这种定义变成嵌套。
A数组有个属性叫a是一种对象,对象里又是B包含bc、c,b数据。以此产生复杂的对象,层次性的像递归一样的嵌套方式。定义出复杂的定义对象。
对象是一组间值对,其中值本身又是一组对象,构成一个数组。纯文本表达的能力比较有限,值是字符串、数字不存在区别,三个或一个字符的区别。不能再区分整数、浮点数的概念。
对象是文本,定义比如大括号开始表达真假。有一个特殊的空,这就是它的六种数据类型。它的含义是拿文字符来描述所有的东西,一种对象在大括号里是一些名、值对。
The following example shows JSON data for a sample object
that contains name-value pairs.
{
"firstName": "Duke",
"lastName": "Java",
"age": 18;
"streetAddress": "100 Internet Dr",
"city": "JavaTown",
"state": "JA",
"postalCode": "12345",
"phoneNumbers": [
{ "Mobile":"111-111-1111" }{ "Home":"222-222-2222"}
】
}
名字一般来说是字符串,双引号影响值引起字符串(也可以是数字),数字就没有影响。冒号是名字对的间隔,每个名字对间逗号隔开。
唯一的phonenumbers是数组用方括号来描述的。
数组概念是本身是一组键值对,电话号码是一个数组,包括手机和家庭电话。
这是一个完整的JSON对象,是JSON的描述方式。Ajax时X的含义是XML。
发XML HTTP Request出去,想象一下,如果用XML方式描述数据有一个叫做person的标签在最外面,里面有first name。简单一点,First name,duke ,lastname,Java,lastname,以此类推,phone number会有mobile、homenumber。
比较XML和JSON的描述方式可以看到,首先XML和JSON都是层次的一个结构,告诉你这些字在第一层。Phone number是数据在里缩进第二层。
和这道理相似,在person里其他东西都在一层里,phone number的mobile和home都在缩进去的一层,可以描述层次的一个结构。通过阶段的person或大括号是完整的单一对象。最大差异是XML在描述数据的冗余比较多。
比如开始标签和结束标签,但在JSON里只是name描述,按照XML格式的数据量一定比看到JSON的描述量要多,有差异。
它描述相同的概念、描述相同的数据,这边数据少,为什么不用这边?Ajax的x是指XML。理论上在最前面画的Ajax图(Ajax最初出现时的图)。
在服务器端和客户端间传递的X、JSON是原因,JSON的数据压缩到极致表示数据的语义不能再压缩,再压缩要借助一个工具,比如摩根士塔利的数据交换有一个叫fix协是拍照感。
比如有交所和上交所间的交换数据交换用一种代码。举例,比如用600102表示某个股票,价格是12.03,然后600510,它的价格是多少?看到它更简单,需要辅助工具是600102表示五粮液,是3/12下来后要再处理下。
但用这种方式描述时看到在网络上传递的数据量已经极简,这种大规模交易的系统强调网络上传递的数据效率较好。JSON和SML的差异是传输数据量少。
使用JSON处理看结构,首先对象放在大括号里,然后每个键值位的后面都用逗号隔开(最后一个可以不写),键值对的键值冒号隔开,名字是字符串,值是六种数据类型的一种。
如果值是一个数组,用方括号表示,数组的定义比如C++或Java,数组有点差异。C+++Y是同类型,至少都有一个公共的负类(它们可以都转型成负类的类型看待能放弃)。
两个名词对应间没有必然联系,可以放它的数据类型的字串(数字和number)都可以。
结构像SML是数形的结构,定义对象、数组后的好处是对象里包含其他的对象或数组。
JSON对象里from numbers包含另外一个或两个JSON对象本身也是完整的对象。
这是它的基本语法。使用它时,请求要在这里使用它在request或response里设置一下request或response的内容是JSON类型,剩下是怎么去组装或生成以及解析JSON。