AJAX

一、概述

AJAX,Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。它并不是新的编程语言,而是一种用于创建快速动态网页的技术。

此处的异步与同步分别指,在客户端和服务器端相互通信的基础上,

  • 同步:客户端必须等待服务器端的响应,在等待的期间客户端不能做其他操作;
  • 异步:客户端无需等待服务器端的响应,在服务器处理请求的过程中,客户端可进行其他的操作。

AJAX ,故其最大的优点为,不重新加载整个页面的情况下,可与服务器进行少量数据交换并更新部分网页内容。AJAX,不需要任何浏览器插件,但需用户允许 JavaScript 在浏览器上执行。

AJAX,是基于现有的 Internet 标准,并且联合使用它们:

  • XMLHttpRequest 对象(异步的与服务器交换数据)
  • JavaScript / DOM(信息显示/交互)
  • CSS(给数据定义格式)
  • XML(作为转换数据的格式)

二、原生的JS实现方式

1. 创建核心对象(固定格式):

所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。IE5 和 IE6 使用 ActiveXObject

1
2
3
4
5
6
7
8
9
var xmlhttp;
if (window.XMLHttpRequest){
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xmlhttp=new XMLHttpRequest();
}
else{
// IE6, IE5 浏览器执行代码
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}

2. 建立连接:

1
open(method, url, async)

XMLHttpRequest 的方法)其三种参数:

  • method:请求的类型
    • POST:请求参数需在**send()**方法中定义
    • GET:请求参数在 URL 后边拼接。send() 方法为空参
  • url:文件在服务器上的位置
  • async:若值为 true,则异步;若值为 false,则同步,此时 JavaScript 会等到服务器响应就绪才继续执行(若服务器繁忙或缓慢,应用程序会挂起或停止)

举例如下:

1
xmlhttp.open("GET", "ajaxServlet?username=Tom", true);

3. 发送请求:

1
xmlhttp.send(string);

其中 string 参数仅用于 POST 请求,GET 请求无需传参。

4. 接收并处理来自服务器的响应结果:(固定格式)

当服务器响应成功时,可用XMLHttpRequest 对象的属性来获得字符串形式的响应数据:

1
xmlhttp.responseText

其固定格式如下:

1
2
3
4
5
6
7
8
xmlhttp.onreadystatechange=function(){ //当readyState改变时,就会触发
//判断readyState就绪状态是否为4,判断status响应状态码是否为200
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//获取服务器的响应结果
var responseText = xmlhttp.responseText;
//do something...
}
}
属性描述
onreadystatechange存储函数对象(或函数名),每当 readyState 属性
改变时,就会调用该函数。
readyState存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
0: 请求未初始化;1: 服务器连接已建立;2: 请求
已接收;3: 请求处理中;4: 请求已完成,且响应已就绪
status200: “OK”;404: 未找到页面

综上,完整的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function  fun() { //定义方法
//发送异步请求
//1.创建核心对象
var xmlhttp;
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}

//2. 建立连接
xmlhttp.open("GET","ajaxServlet?username=tom",true);

//3.发送请求
xmlhttp.send();

//4.接受并处理来自服务器的响应结果
//(当服务器响应成功后再获取)获取方式 :xmlhttp.responseText
//当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange。
xmlhttp.onreadystatechange=function(){
//判断readyState就绪状态是否为4,判断status响应状态码是否为200
if (xmlhttp.readyState==4 && xmlhttp.status==200){
var responseText = xmlhttp.responseText; //获取服务器的响应结果
//....
}
}
}

三、jQuery实现方式

jQuery 提供了三个简便的方法,来发送异步请求。

方法一

$.ajax({键值对1, 键值对2, ... })

举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
$.ajax({
url:"ajaxServlet" , //请求路径
type:"POST", //请求方式
data:{"username":"Luffy", "age":20}, //请求参数(JSON形式)
success:function(date){
//.....
}, //响应成功后的回调函数
error:function(){
//.....
}, //若请求响应出现错误,会执行回调函数
dataType:"text" //设置接受到的响应数据的格式
});

方法二

$.get(url, [data], [callback], [type]):发送 GET 请求

  • url:请求路径
  • data:请求参数
  • callback:回调函数
  • type:响应结果的类型

举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<script>
//定义方法
function fun() { //发送异步请求,其中含有username参数
$.get("ajaxServlet",{username:"rose"},function (data) {
alert(data);
/*打印ajaxServlet传入的响应信息:
response.getWriter().write("hello : " + username);
*/
},"text");
}
</script>
</head>
<body>
<input type="button" value="发送异步请求" onclick="fun();">
<input> <!--输入框-->
</body>
</html>

方法三

$.post(url, [data], [callback], [type]):发送 POST 请求

JSON

一、概述

JSON(JavaScript Object Notation,JavaScript 对象表示法)是用于将结构化数据表示为 JavaScript 对象的标准格式。

它通常用于在网站上表示和传输数据(例如从服务器向客户端发送一些数据,因此可以将其显示在网页上)。JSON 解析器和 JSON 库支持许多不同的编程语言。

它可以作为一个对象或者字符串存在,又可以被储存在它自己的文件中,一个文本文件,拓展名为:.json。其 MIME 类型为 application/json

和 XML 相比,JSON 具有自我描述性。但不同之处在于,JSON 更短,且读写的速度更快。

二、语法

1. 语法规则

  • 数据在 键值对 中,其书写格式为:key : value。比如:"name":"Luffy"

  • 数据由逗号分隔,取值类型可以:

    • 数字(整数或浮点数)
    • 字符串(在双引号中)
    • 布尔值(truefalse
    • 数组
    • 对象
    • null
  • 字符串和属性名称周围使用双引号 ""

  • 大括号 {} 保存对象

    1
    2
    3
    4
    5
    var person = {
    "name":"Luffy",
    "age":20,
    "adult":true
    }
  • 中括号 [] 保存数组,数组可以包含多个对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var persons = [
    {"name":"Luffy", "age":20, "adult":true},
    {"name":"Nami", "age":19, "adult":true},
    {"name":"Zoro", "age":25, "adult":true}
    ];
    var school = {
    "persons":[
    {"name":"Luffy", "age":20, "adult":true},
    {"name":"Nami", "age":19, "adult":true},
    {"name":"Zoro", "age":25, "adult":true}
    ]
    };

2. 获取数据

(一)json对象.键名,如:

1
2
var person = {"name":"Luffy", "age":20, "adult":true};
var name = person.name;

(二)json对象["键名"]

1
var name = person["name"];

(三)数组对象[索引]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var school = {
"persons":[
{"name":"Luffy", "age":20, "adult":true},
{"name":"Nami", "age":19, "adult":true},
{"name":"Zoro", "age":25, "adult":true}
]
};
var name = school.persons[2].name;

var persons = [
{"name":"Luffy", "age":20, "adult":true},
{"name":"Nami", "age":19, "adult":true},
{"name":"Zoro", "age":25, "adult":true}
];
var name2 = persons[1].name;

(四)遍历:举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var person = {"name":"Luffy", "age":20, "adult":true};
for(var key in person){
alert(key + ":" + person[key]);
//注意,不能用 person.key,因为此处的key是字符串类型,就好比person."name",显然不对。
};

var persons = [
{"name":"Luffy", "age":20, "adult":true},
{"name":"Nami", "age":19, "adult":true},
{"name":"Zoro", "age":25, "adult":true}
];
for(var i = 0; i < persons.length; i++){
var pe = persons[i];
for(var key in pe){
alert(key + ":" + pe[key]);
}
}

三、JSON数据和Java对象的相互转换

1. JSON解析器

常见的解析器:Jsonlib,Gson,fastjson,jackson

2. 导入 jackson 相关 jar 包

3. JSON 转为 Java 对象

(一)导入 jackson 的相关 jar 包后,创建 Jackson 核心对象 ObjectMapper

(二)调用 ObjectMapper 的相关方法进行转换:

  • readValue(json字符串数据, Class)
1
2
3
String jsonStr = "{\"name\":\"Luffy\", \"age\":20, \"adult\":true}";
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue(json, Person.class); //JSON转换为Person对象

4. Java 对象转换 JSON

(一)导入 jackson 的相关 jar 包后,创建 Jackson 核心对象 ObjectMapper

1
ObjectMapper mapper = new ObjectMapper();

(二)调用 ObjectMapper 的相关方法进行转换:

转换方法:

  • writeValue(参数1, obj)

    • File:将 obj 对象转换为 JSON 字符串,并保存到指定的文件中;

    • Writer:将 obj 对象转换为 JSON 字符串,并将 JSON 数据填充到字符输出流中;

    • OutputStream:将 obj 对象转换为 JSON 字符串,并将 JSON 数据填充到字节输出流中。(常用于设置响应消息的输出流)

  • writeValueAsString(obj):将对象转为 JSON 字符串

    传入的 obj 可以是 List 或者 Map 等对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1.创建Person对象(Java对象)
Person p = new Person();
p.setName("Luffy");
p.setAge(20);
p.setAdult(true);
//2.创建Jackson的核心对象:ObjectMapper
ObjectMapper mapper = new ObjectMapper();
//3.转换Java对象为JSON
//3.1 转换为 JSON 字符串
String jsonStr = mapper.writeValueAsString(p);
System.out.println(jsonStr);
//3.2 写出到 D://233.txt 文件中
mapper.writeValue(new File("D://233.txt"), p);
//3.3 将Java对象转换为JSON字符串,并将JSON数据填充到字节输出流
mapper.writeValue(new FileWriter("D://233.txt"), p);

注解:

  • @JsonIgnore:排除被注解的属性,该属性将来不会被转换为 JSON 对象中的一个属性。
  • @JsonFormat:属性值格式化
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person{
private String name;
private int age;
private boolean adult;

@JsonIgnore
private double score;

@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthday;

//....
}

案例:校验用户名是否存在

客户端要想将服务器响应的数据作为JSON数据来使用,有两种解决方案:

  • $.get(type):将最后一个参数 type 指定为 "json"

  • 在服务器端设置 MIME 类型,即

    1
    response.setContenType("application/json;charset=utf-8");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<script>
$(function(){ //(入口)当页面加载完成后
$("#username").blur(function () { //绑定blur事件(鼠标焦点移开)
var username = $(this).val(); //获取username文本输入框的值
//发送AJAX请求,其中请求包含username数据
$.get("findUserServlet", {username:username}, function (data) { //回调函数,检查响应信息
var span = $("#legality_username");
/* *响应中的JSON数据为:
{"isExist":true, "msg":"此用户名已被使用,请更换一个"}
或者
{"isExist":false, "msg":"用户名可用"}
*/
if(data.isExist){
span.css("color", "#e74c3c");
}
else {
span.css("color", "#52c41a");
}
span.html(data.msg);
});
})
})
</script>
</head>
<body>
<form>
<input type = "text" id = "username" name = "username" placeholder="请输入您的用户名">
<span id = "legality_username"></span> <!--用于显示提示信息-->
<br>
<input type = "password" name = "password" placeholder="请输入您的密码">
<br>
<input type = "submit" value = "注册">
<br>
</form>
</body>
</html>

findUserServlet.java 文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package top.JoyDee.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@WebServlet("/findUserServlet")
public class findUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
response.setContentType("application/json;charset=utf-8"); //设置响应数据格式为json,编码为utf-8!!
Map<String, Object> mymap = new HashMap<String, Object>();
if("Luffy".equals(username)){ //注意,此处做了简化,本应在数据库中查询username是否已存在。
mymap.put("isExist", true); //调用Map方法
mymap.put("msg", "此用户名已被使用,请更换一个");
}
else { //未使用过的用户名
mymap.put("isExist", false);
mymap.put("msg", "用户名可用");
}
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getWriter(), mymap); //将JSON数据转化为字符串,并将其设置到响应消息的输出流中。
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}