昨天还没有谈完,今天做一个了解。
首先还是以错误,来讲述。
一、AJax常见错误
Ajax常见的错误,除了昨天列举的之外。还有就是如下状态码:
405,请求类型错误,比如请求是POST,你却用GET,通常出现这种情况是在SpringMVC中的@RequestMapping,有使用SpringMVC经验的小伙伴们都知道,@RequestMapping默认的请求方式为GET。如果你因为复制粘贴没有仔细检查,在调试Ajax的时候就会出现405状态码。当然了,你没有通过Ajax的调试方式,通常就会直接走error,并不会出现405状态码的提示。一般情况下,出现这种问题的概率非常少,因为还有postman。通过postman进行接口测试,一般情况下,如果你的情况不对,直接提示不支持该请求。
415,服务器无法处理请求附带的媒体格式。因为你在Ajax中加入了contentType并指定了媒体格式为application/json;
如果你的参数列表中没有加入@RequestBody就会出现415。
@RequestBody通常用来处理contentType不是默认的application/x-www-form-urlcode编码的内容。比如说application/json和application/xml,一般情况下处理application/json。
例如:
403,这个通常就是你的请求参数与接收参数不一致,比如createDate在前台是String类型,但是后台你却用Date类型接收,就会出现这种问题。
一般情况下,当参数比较多的时候,建议使用对象(参数三个以上,就建议使用对象比较好)。
500,这个通常就是服务端代码有问题了。这个就要根据具体的调试情况来看了。比如空指针或者是类型转换异常等等。
二、如何调试Ajax
比如我通过postman来测试,没有发现问题,并不代表web端异步请求没有问题。比如我在上面说到的Ajax常见错误,这些常见错误,很少能通过postman来发现的。因为开发人员,会因为疏忽大意,懒得测试(单元测试)等可能的意外原因导致问题的出现。又或者是我通过单元测试发现没问题,并不代表web开发请求url或者是安卓那边请求没问题。
比如:
这段代码正常返回的集合数据是不带斜杠的,而web请求却带斜杠。
这是因为String的原因,如果将其返回值换为Object或者并将其toJSONString()改为toJSON()就可以得到正常的json数据而不是带斜杠的字符串数据。
虽然说,带斜杠可以通过jQuery的eval、安卓那边的replace方法解决,但是最好还是不要绕一大圈。
调式的手段,主要是在error的function加上对应的三个参数XMLHttpRequest、textStatus、errorThrown等。
弹出状态码的是XMLHttpRequest.status,正常的状态码应为200。
状态码详解如下:
1**:请求收到,继续处理
2**:操作成功收到,分析、接受
3**:完成此请求必须进一步处理
4**:请求包含一个错误语法或不能完成
5**:服务器执行一个完全有效请求失败
100——客户必须继续发出请求
101——客户要求服务器根据请求转换HTTP协议版本
200——交易成功
201——提示知道新文件的URL
202——接受和处理、但处理未完成
203——返回信息不确定或不完整
204——请求收到,但返回信息为空
205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206——服务器已经完成了部分用户的GET请求
300——请求的资源可在多处得到
301——删除请求数据
302——在其他地址发现了请求数据
303——建议客户访问其他URL或访问方式
304——客户端已经执行了GET,但文件未变化
305——请求的资源必须从服务器指定的地址得到
306——前一版本HTTP中使用的代码,现行版本中不再使用
307——申明请求的资源临时性删除
400——错误请求,如语法错误
401——请求授权失败
402——保留有效ChargeTo头响应
403——请求不允许
404——没有发现文件、查询或URl
405——用户在Request-Line字段定义的方法不允许
406——根据用户发送的Accept拖,请求资源不可访问
407——类似401,用户必须首先在代理服务器上得到授权
408——客户端没有在用户指定的饿时间内完成请求
409——对当前资源状态,请求不能完成
410——服务器上不再有此资源且无进一步的参考地址
411——服务器拒绝用户定义的Content-Length属性请求
412——一个或多个请求头字段在当前请求中错误
413——请求的资源大于服务器允许的大小
414——请求的资源URL长于服务器允许的长度
415——请求资源不支持请求项目格式
416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含If-Range请求头字段
417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求
500——服务器产生内部错误
501——服务器不支持请求的函数
502——服务器暂时不可用,有时是为了防止发生系统过载
503——服务器过载或暂停维修
504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长
505——服务器不支持或拒绝支请求头中指定的HTTP版本
至于XMLHttpRequest.readyState说的是AJax异步请求服务器的过程(一共五个过程):
(0)未初始化
此阶段确认XMLHttpRequest对象是否创建,并为调用open()方法进行未初始化作好准备。值为0表示对象已经存在,否则浏览器会报错--对象不存在。
(1)载入
此阶段对XMLHttpRequest对象进行初始化,即调用open()方法,根据参数(method,url,true)完成对象状态的设置。并调用send()方法开始向服务端发送请求。值为1表示正在向服务端发送请求。
(2)载入完成
此阶段接收服务器端的响应数据。但获得的还只是服务端响应的原始数据,并不能直接在客户端使用。值为2表示已经接收完全部响应数据。并为下一阶段对数据解析作好准备。
(3)交互
此阶段解析接收到的服务器端响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。状态3表示正在解析数据。
(4)完成
此阶段确认全部数据都已经解析为客户端可用的格式,解析已经完成。值为4表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。
概而括之,整个XMLHttpRequest对象的生命周期应该包含如下阶段:
创建-初始化请求-发送请求-接收数据-解析数据-完成
用个例子说明:
比如我给远方的一个朋友打电话,
第一,我必须要有手机,没有手机怎么打电话,对应(0);
第二,我要将我说的第一句话传达给他,这是(1);
第三,我说的话已经传达给他了,这是(2);
第四,他需要理解我话中所表达的意思是什么,这是(3);
第五,他已经理解的我话的意思,这是(4);
也许这个例子表达的不是特别恰当,但是我觉得已经可以比较好的说明异步请求服务的过程和readyState的含义。
三、Ajax中的参数含义(以jQuery中的$.ajax为例)
1.url:
要求为String类型的参数,(默认为当前页地址)发送请求的地址。
2.type:
要求为String类型的参数,请求方式(post或get)默认为get。注意其他http请求方法,例如put和delete也可以使用,但仅部分浏览器支持。
3.timeout:
要求为Number类型的参数,设置请求超时时间(毫秒)。此设置将覆盖$.ajaxSetup()方法的全局设置。
4.async:
要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为false。注意,同步请求将锁住浏览器,用户其他操作必须等待请求完成才可以执行。
5.cache:
要求为Boolean类型的参数,默认为true(当dataType为script时,默认为false),设置为false将不会从浏览器缓存中加载请求信息。
6.data:
要求为Object或String类型的参数,发送到服务器的数据。如果已经不是字符串,将自动转换为字符串格式。get请求中将附加在url后。防止这种自动转换,可以查看 processData(防止自动转换)选项。对象必须为key/value格式,例如{foo1:"bar1",foo2:"bar2"}转换为&foo1=bar1&foo2=bar2。如果是数组,JQuery将自动为不同值对应同一个名称。例如{foo:["bar1","bar2"]}转换为&foo=bar1&foo=bar2。
7.dataType:
要求为String类型的参数,预期服务器返回的数据类型。如果不指定,JQuery将自动根据http包mime信息返回responseXML或responseText,并作为回调函数参数传递。可用的类型如下:
xml:返回XML文档,可用JQuery处理。
html:返回纯文本HTML信息;包含的script标签会在插入DOM时执行。
script:返回纯文本JavaScript代码。不会自动缓存结果。除非设置了cache参数。注意在远程请求时(不在同一个域下),所有post请求都将转为get请求。
json:返回JSON数据。
jsonp:JSONP格式。使用SONP形式调用函数时,例如myurl?callback=?,JQuery将自动替换后一个“?”为正确的函数名,以执行回调函数。
text:返回纯文本字符串。
8.beforeSend:
这个参数主要是为了在向服务器发送请求前,执行一些操作。要求为Function类型的参数,发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次ajax请求。XMLHttpRequest对象是惟一的参数。
function(XMLHttpRequest){
this; //调用本次ajax请求时传递的options参数
}
9.complete:
要求为Function类型的参数,请求完成后调用的回调函数(请求成功或失败时均调用)。参数:XMLHttpRequest对象和一个描述成功请求类型的字符串。
function(XMLHttpRequest, textStatus){
this; //调用本次ajax请求时传递的options参数
}
10.success:
要求为Function类型的参数,请求成功后调用的回调函数,有两个参数。
(1)由服务器返回,并根据dataType参数进行处理后的数据。
(2)描述状态的字符串。
function(data, textStatus){
//data可能是xmlDoc、jsonObj、html、text等等
this; //调用本次ajax请求时传递的options参数
}
11.error:
要求为Function类型的参数,请求失败时被调用的函数。该函数有3个参数,即XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。ajax事件函数如下:
function(XMLHttpRequest, textStatus, errorThrown){
//通常情况下textStatus和errorThrown只有其中一个包含信息
this; //调用本次ajax请求时传递的options参数
}
12.contentType:
要求为String类型的参数,当发送信息至服务器时,内容编码类型默认为"application/x-www-form-urlencoded"。该默认值适合大多数应用场合。
13.dataFilter:
要求为Function类型的参数,给Ajax返回的原始数据进行预处理的函数。提供data和type两个参数。data是Ajax返回的原始数据,type是调用jQuery.ajax时提供的dataType参数。函数返回的值将由jQuery进一步处理。
function(data, type){
//返回处理后的数据
return data;
}
14.dataFilter:
要求为Function类型的参数,给Ajax返回的原始数据进行预处理的函数。提供data和type两个参数。data是Ajax返回的原始数据,type是调用jQuery.ajax时提供的dataType参数。函数返回的值将由jQuery进一步处理。
function(data, type){
//返回处理后的数据
return data;
}
15.global:
要求为Boolean类型的参数,默认为true。表示是否触发全局ajax事件。设置为false将不会触发全局ajax事件,ajaxStart或ajaxStop可用于控制各种ajax事件。
16.ifModified:
要求为Boolean类型的参数,默认为false。仅在服务器数据改变时获取新数据。服务器数据改变判断的依据是Last-Modified头信息。默认值是false,即忽略头信息。
17.jsonp:
要求为String类型的参数,在一个jsonp请求中重写回调函数的名字。该值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,例如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。
18.processData:
要求为Boolean类型的参数,默认为true。默认情况下,发送的数据将被转换为对象(从技术角度来讲并非字符串)以配合默认内容类型"application/x-www-form-urlencoded"。如果要发送DOM树信息或者其他不希望转换的信息,请设置为false。
19.scriptCharset:
要求为String类型的参数,只有当请求时dataType为"jsonp"或者"script",并且type是GET时才会用于强制修改字符集(charset)。通常在本地和远程的内容编码不同时使用。
上述的1,2,6,7,10,11,12是我开发过程中比较常用的。其他的几乎很少用。
四、SSM框架与Ajax三种方式(主要说明参数传递和接收)
第一种,直接在参数列表中写。
优点,直接指明参数类型即可,确保前端和后台的参数类型一致,就可以接收并处理;
缺点,当参数过多时,建议使用对象,不然随着业务改动,可能需要对象参数列表进行修改,导致出现一些不必要的异常,比如415状态码和403状态码异常或者是500状态码异常。
第二种,通过HttpServletRequest
第三种,使用Map
注意,使用Map的话,记得在参数列表中加上@RequestParam,否则会发现参数无法传过来。
这三种如果都用于Ajax异步交互,其本质可以发现都是通过获取键来得到值。
当然了,再本质,就是基于HTTP请求。