Asynchronous JavaScript and XML
异步的js和xml
创建异步请求
let request
//1)此函数用来创建异步请求
function create(){
//创建一个异步请求
/*
* 这种创建方式是level2版本的创建方式,如果要针对ie6 7 8 等老旧浏览器
* 则应该使用level1版本
*
* if(window.XMLHttpRequest){
* request = new XMLHttpRequest()
* }else{
* request = new ActiveXObject("Microsoft.XMLHttp")
* }
*
* 同步请求:
* HttpServletRequest
* ServletRequest
* */
request = new XMLHttpRequest()
}
创建函数用来发送请求
//2)此函数用来给服务器发送请求,一般称之为主函数(非官方)
function checkName(value){
//A:创建异步请求
create()
//B:给服务器发送异步请求
/*
* request.open(type,url,async)
*
* url:表示发送异步请求的目的地(拦截地址)
* 如果是get,则从此处传递值
* 本例:
* 'check?key=value&key2=value2'
* type:请求类型 post get
* async:表示是否使用异步,默认true使用,更改为false则使用同步,当响应返回之前
* 浏览器锁死,用户无法进行任何操作
* */
request.open('post','check',true)
//C:如果使用POST则需要书写此句,表示使用字符流进行值的传递,GET自动字符流不需要书写
request.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
//D:声明回调函数
//注意这里函数名可以随意书写,但是没有括号,如果存在括号则表示调用,没有括号表示声明
//调用立刻执行,而声名需要前面的条件满足才可以
request.onreadystatechange = callback
//E:设置传递的参数,注意POST从此处传递值,GET不从此处传值,也必须书写,填写null
//request.send('etoak='+value)
request.send(`etoak=${value}`)
}
书写回调函数接受响应信息
readyState状态
readyState值 | 状态 | 补充描述 |
---|---|---|
0 | 链接尚未初始化 | 调用request.oprn() |
1 | 链接初始化 | 请求已经准备好 |
2 | 请求正在处理 | 服务器正在处理请求时会做出一个相应,readyState=2时,响应收不提供一个关于响应的信息,并提供一个状态码 |
3 | 得到服务器的响应 | 这个阶段数据下载到请求对象,但是响应数据还没有准备好,不能使用 |
4 | 服务器响应准备就绪 | 现在服务器处理完请求数据可以使用了 |
status状态
状态码 | 描述 |
---|---|
1xx | 消息 |
2xx | 成功 |
3xx | 重定向 |
4xx | 请求错误404 405 |
5xx | 服务端异常 500 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7WBX7wxj-1594441116061)(D:\Study\Yitu\前端\AJAX\AjaxDaysOfficial\attachment\ajax回调函数.jpg)]
//3)回调函数,接受服务器处理完的响应信息
function callback(){
//首先判断服务器发送数据是否完整
if(request.readyState==4){
//完整的返回的数据没有报错
if(request.status==200){
//接受返回的字符串
let value = request.responseText
//拿取span元素
let nodeSpan = document.getElementById('name_msg')
//拿取submit表单元素
let nodeSub = document.getElementById('sub')
if(value=='bingo'){
//设置错误提示信息
nodeSpan.innerHTML = '<img src="image/wrong.png">用户姓名已经被占用'
//设置样式
nodeSpan.style.color = 'red'
//禁用提交按钮
nodeSub.disabled = true
return;
}
nodeSpan.innerHTML = '<img src="image/right.png">用户姓名可以使用'
nodeSpan.style.color = 'green'
nodeSub.disabled = false
}
}
}
@WebServlet("/check")
public class CheckName extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* Ajax支持三种数据的输出
* 1)字符串 text/plain
* 2)xml text/xml
* 3)json application/json
* 所以在这里不管怎么书写也不能书写text/html,因为根本不支持html
* */
response.setContentType("text/plain;charset=utf-8");
request.setCharacterEncoding("utf-8");
//拿取要输出的字符流
PrintWriter out = response.getWriter();
//接受提交过来的用户名
String name = request.getParameter("etoak");
//模拟数据库查询
if(name.equalsIgnoreCase("elena")){
/*
* 返回字符串
* out.print(要返回的数据)
* 只支持 字符串 json xml
* 注意不能使用println()否则会自动添加\n
* */
out.print("bingo");
out.close();
return;
}
out.print("suc");
out.close();
}
注意点
Ajax支持三种数据的输出
1)字符串 text/plain
2)xml text/xml
3)json application/json
所以在这里不管怎么书写也不能书写text/html,因为根本不支持html
request.setRequestHeader(‘Content-Type’,‘application/x-www-form-urlencoded’)
如果写错了会有500错误,提示response.send()这里报错,如果这里出错就找设置编码的
JavaScript Object Notation
2004年诞生,2006年加入ajax技术体系,是一种轻量级的数据交换格式,成功的取代了xml,用来封装批量数据,不需要再次构建一个document对象,由于其普遍性被称之为Java的第十种常用数据类型
JSON可以同时在Java端和Js中使用
JSON其实就是一种特定格式的字符串,可以直接被打印
JSON属于第三方技术,使用时需要导入jar包
JSON存在三种封装格式,可以将数据封装为标准的JSON格式
{key1:value1,key2:value2,key3:value3,keyN:valueN}
key:必须是字符串
value: 八种基本数据类型、null、String、自定义数类型、JSON
注意不能直接放置java.util.Date
//1:可以封装任意数据,封装之后呈现Map格式的JSON
String str = "etoak";
int i = 3;
boolean flag = true;
String[] strAr = {"济南","杭州","青岛"};
JSONObject jo = new JSONObject();
jo.put("key1",str);
jo.put("key2",i);
jo.put("key3",flag);
jo.put("key4",strAr);
//{"key1":"etoak","key2":3,"key3":true,"key4":["济南","杭州","青岛"]}
/*
* 这种封装方式可以封装任意数据类型,但是会导致JSON复杂度增高
* 存在了一些不必要的数据
* */
System.out.println(jo);
JSONObject jo2 = new JSONObject();
jo2.put("boy",new Boy(1,"张三","[email protected]","33333"));
//{"boy":{"phone":"33333","name":"张三","id":1,"email":"[email protected]"}}
System.out.println(jo2);
//------------------------------------------------------------------------------
//2:专门封装Map和自定义数据类型,封装之后呈现Map类型的JSON
Map<Integer,String> map = new HashMap<>();
map.put(1,"Java");
map.put(2,"Javascript");
map.put(3,"C");
map.put(4,"C++");
map.put(5,"Python");
JSONObject js = JSONObject.fromObject(map);
//{"1":"Java","2":"Javascript","3":"C","4":"C++","5":"Python"}
System.out.println(js);
Boy bo = new Boy(2,"elena","[email protected]","55555");
JSONObject js2 = JSONObject.fromObject(bo);
//{"phone":"55555","name":"elena","id":2,"email":"[email protected]"}
System.out.println(js2);
//可以对自定义数据类型中的属性进行有选择的封装
JsonConfig jf = new JsonConfig();
//设置不需要封装的字段
jf.setExcludes(new String[]{"id","phone"});
//注意这里设置了两个参数
JSONObject js3 = JSONObject.fromObject(bo,jf);
//{"name":"elena","email":"[email protected]"}
System.out.println(js3);
[value1,value2,value3,valueN]
value: 八种基本数据类型、null、String、自定义数类型、JSON
注意不能直接放置java.util.Date
//3:专门封装Set List 和 数组,封装之后呈现数组格式的json
JSONArray ja1 = JSONArray.fromObject(strAr);
//["济南","杭州","青岛"]
System.out.println(ja1);
List<String> list = new ArrayList<String>();
list.add("jQuery");
list.add("ExtJs");
list.add("Vue");
list.add("Angular");
list.add("React");
JSONArray ja2 = JSONArray.fromObject(list);
//["jQuery","ExtJs","Vue","Angular","React"]
System.out.println(ja2);
Set<String> set = new HashSet<String>();
set.add("山东鲁能");
set.add("上海申花");
set.add("北京国安");
set.add("上海上港");
JSONArray ja3 = JSONArray.fromObject(set);
//["北京国安","上海申花","山东鲁能","上海上港"]
System.out.println(ja3);
1.直接添加
//{"key1":"etoak","key2":3,"key3":true,"key4":["济南","杭州","青岛"]}
/*
* 这种封装方式可以封装任意数据类型,但是会导致JSON复杂度增高
* 存在了一些不必要的数据
* */
JSONObject jo = new JSONObject();
jo.put("key1",str);
jo.put("key2",i);
jo.put("key3",flag);
jo.put("key4",strAr);
//2:专门封装Map和自定义数据类型,封装之后呈现Map类型的JSON
Map<Integer,String> map = new HashMap<>();
map.put(1,"Java");
map.put(2,"Javascript");
map.put(3,"C");
map.put(4,"C++");
map.put(5,"Python");
JSONObject js = JSONObject.fromObject(map);
List<String> list = new ArrayList<String>();
Collections.addAll(list,"Jquery","EasyUI","LayUI");
JSONArray ja = JSONArray.fromObject(list);
三种封装方式
- 封装任意数据类型,封装之后呈现Map格式的JSON
- 封装Map和自定义数据类型,封装之后呈现Map格式的JSON,并且可以针对性封装
- 封装数组 List 和 Set,封装之后呈现数组类型的JSON,也可以针对向的封装
强调:不能直接封装java.util.Date
JSON格式返回回来仅仅呗看做一个普通的字符串
从服务器返回的是一个标准的JSON格式的字符串,js并不能识别json
而仅仅将其作为字符串处理,我们现有的字符串技术无法很方便的拿取内部封装的信息
Json提供了一个转换器,可以将字符串中的键转换为js对象的属性名,将值转换为js对象的属性值
{“etoak”:[{“name”:“山东”,“id”:1},{“name”:“湖北”,“id”:2},{“name”:“上海”,“id”:3},{“name”:“广东”,“id”:4},{“name”:“香港”,“id”:5},{“name”:“台湾”,“id”:6}]}
这个json被转换为一个js对象
转换成对象之后,可以根据
属性值 = 对象.属性名 来拿取封装的数据
//获取到JSON以后需要进行转换才能转换成JSON格式
let text = request.responseText
let json = JSON.parse(text)
实现省份的选择
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>3)级联title>
head>
<body onload="showProvince()">
请选择省份(直辖市,区划):
<select name="province" id="province" onchange="showCity(this.value)">
<option value="0">请选择省份option>
select>
请选择城市(区划):
<select name="city" id="city">
<option value="0">请选择城市option>
select>
<script>
let request
function create(){
request = new XMLHttpRequest()
}
function showProvince(){
create()
request.open('post','show_province',true)
request.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
request.onreadystatechange = ()=>{
if(request.readyState==4){
if(request.status==200){
//注意JSON格式仅仅被看做一个普通的字符串
let text = request.responseText
console.log(text)
//alert(text)
/*
* 从服务器返回的是一个标准的JSON格式的字符串,js并不能识别json
* 而仅仅将其作为字符串处理,我们现有的字符串技术无法很方便的拿取内部封装的信息
* Json提供了一个转换器,可以将字符串中的键转换为js对象的属性名,将值转换为
* js对象的属性值
* {"etoak":[{"name":"山东","id":1},{"name":"湖北","id":2},{"name":"上海","id":3},{"name":"广东","id":4},{"name":"香港","id":5},{"name":"台湾","id":6}]}
* 这个json被转换为一个js对象
* 转换成对象之后,可以根据
* 属性值 = 对象.属性名 来拿取封装的数据
* */
let obj = JSON.parse(text)
//alert(obj)
//[{"name":"山东","id":1},{"name":"湖北","id":2},{"name":"上海","id":3},{"name":"广东","id":4},{"name":"香港","id":5},{"name":"台湾","id":6}]
let ar = obj.etoak
//拿取省份下拉列表框
let dom_select = document.getElementById('province')
for(let i = 0;i<ar.length;i++){
// {"name":"山东","id":1}
let province = ar[i]
let id = province.id
let name = province.name
//将拿取的id和name放置进下拉列表框
/*
* 等号左边:
* 小写o,带s,中括号内为索引值从0开始注意,这里从1开始表示
* 默认的第0个保留
* 等号右边j:
* 大写O,不带s,小括号内为要添加的option的内容
* new Option(页面显示的值,value值)
* */
dom_select.options[i+1] = new Option(name,id)
}
}
}
}
request.send(null)
}
function showCity(pid){
create()
request.open('post','show_city',true)
request.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
request.onreadystatechange = ()=>{
if(request.readyState==4){
if(request.status==200){
let text = request.responseText
console.log(text)
let ar = JSON.parse(text)
//拿取city下拉列表框
let dom_select = document.getElementById('city')
//首先删除城市下拉列表框中原先存在的option
while(dom_select.length>1){
//item():括号中放置的是索引值,从0开始,这里是1表示删除第一个,保留第0个
dom_select.removeChild(dom_select.item(1))
}
for(let i = 0;i<ar.length;i++){
let city = ar[i]
let id = city.id
let name = city.name
dom_select.options[i+1] = new Option(name,id)
}
}
}
}
request.send(`pid=${pid}`)
}
script>
body>
html>