AJAX&JSON

AJAX

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

AJAX,Asynchronous JavaScript and XML, 异步的JavaScript和Xml,是一种用于创建快速动态网页的技。AJAX 通过在后台与服务器进行少量数据交换,使网页实现异步更新。这意味着**可以在不重载整个页面的情况下,对网页的某些部分进行更新。**而传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个页面。

菜鸟教程

AJAX 教程

概念: ASynchronous JavaScript And XML,异步的JavaScript 和 XML

异步和同步:

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

1.同步和异步

AJAX实现

  • 原生js实现(了解)
  • jQuery实现

原生js实现

原生js实现jQuery了解即可

视频讲解

jQuery实现

jQuery实现ajax

  • $.ajax()
  • $.get()
  • $.post()

$.ajax()

语法:$.ajax({键值对});

键值对有12种,具体可见:jQuery实现ajax

首先在web包下创建ajax01.html文件代码如下:

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery实现ajax</title>
<script src="../js/jquery-3.5.1.min.js"></script>
<script>
// 定义方法
function fun() {
// 使用$.ajax()发送异步请求
$.ajax({
url:"../ajaxServlet", // 请求路径 (这里使用相对路径方式)
type:"post", // 请求方式(默认GET)
data:{"username":"tom","age":18}, // 发送到服务器的数据。将自动转换为请求字符串格式。
success:function (data) { // 请求成功后的回调函数。
alert("响应成功:"+data)
},
error:function () { // 请求失败时调用此函数
alert("出错了...")
}
})
}
</script>
</head>
<body>
<input type="button" value="发送异步请求" onclick="fun()">
<input>
</body>
</html>

然后在src下的servlet包下创建AjaxServlet,代码如下:

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
package servlet;

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;

@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求参数
String username = request.getParameter("username");

//处理业务逻辑。耗时
try {
Thread.sleep(2000); // 2s
} catch (InterruptedException e) {
e.printStackTrace();
}
//2.打印username
System.out.println(username);

//3.响应
response.getWriter().write("hello : " + username);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

在浏览器中访问:http://localhost:8080/json/jQuery/ajax01.html

结果如下:

$.get()

$.get():发送GET请求

语法:语法:$.get(url, [data], [callback], [type])

参数:

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

例子:AjaxServlet同上,创建ajax02.html代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery实现ajax</title>
<script src="../js/jquery-3.5.1.min.js"></script>
<script>
// 定义方法
function fun() {
// 使用$.get()发送异步请求
$.get("../ajaxServlet",{"username":"tom","age":18},function (data) { // 请求成功后的回调函数。
alert("响应成功:"+data)
})

}
</script>
</head>
<body>
<input type="button" value="发送异步请求" onclick="fun()">
<input>
</body>
</html>

在浏览器中访问:http://localhost:8080/json/jQuery/ajax02.html

结果同上。且可以看到请求方式是GET

$.get()方法,请求方式为GET

$.post()

$.post()和​$.get()使用方法一模一样,只是请求方式变成了post

$.post()方法,请求方式为POST


JSON

JSON: JavaScript Object Notation(JavaScript 对象表示法)

JSON 是存储和交换文本信息的语法,类似 XML。

JSON 比 XML 更小、更快,更易解析。

菜鸟教程

JSON教程

Jackson 序列化和反序列化

例子,一个JSON实例为:

1
2
3
4
5
6
7
{
"sites": [
{ "name":"菜鸟教程" , "url":"www.runoob.com" },
{ "name":"google" , "url":"www.google.com" },
{ "name":"微博" , "url":"www.weibo.com" }
]
}

概念:JavaScript Object Notation,JavaScript对象表示法

比如说,在Java中我们封装数据的形式是这样:

1
2
3
4
Person p = new Person();
p.setName("张三");
p.setAge(23);
p.setGender("男");

而在js中则可以这样封装:

1
var p = {"name":"张三","age":23,"gender":"男"};

很容易看出来JavaScript对象表示法来封装数据要方便的多。

  • json现在多用于存储和交换文本信息的语法
  • 进行数据的传输
  • JSON 比 XML 更小、更快,更易解析

JSON语法

JSON语法

JSON基本规则

数据存储在名称/值对中,即json数据是由键值对构成的

相关规则:

  • 键用引号(单双都行)引起来,也可以不使用引号
  • 值的取值类型有:
    1. 数字(整数或浮点数)
    2. 字符串(在双引号中)
    3. 逻辑值(true 或 false)
    4. 数组(在方括号[]中),比如说:{"persons":[{},{}]}
    5. json对象(在花括号{}中),比如说: {"address":{"province":"陕西"....}}
    6. null
  • 数据由逗号,分隔:多个键值对由逗号,分隔
  • 花括号保存对象:使用{}定义json 格式
  • 方括号[]用于保存数组

例子:在html文件中定义json:

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
    <script>
// 定义json
// 1.基本json
var person = {"name":"rick","age":58,"isMan":true};
// alert(person)
// 2.嵌套格式 json中嵌套数组
var persons = {
"person": [
{
"name": "rick",
"age": 58,
"isMan": true
},
{
"name": "tom",
"age": 18,
"isMan": true
},
{
"name": "jerry",
"age": 19,
"isMan": false
}
]
}
// 3.嵌套格式 数组中嵌套json
var arr = [{
"name": "rick",
"age": 58,
"isMan": true
}, {
"name": "rick",
"age": 58,
"isMan": true
}, {
"name": "rick",
"age": 58,
"isMan": true
}]
</script>

JSON获取数据

获取json的方式有:

  • json对象.键名
  • json对象["键名"]
  • 数组对象[索引]
  • 遍历
    • 普通for循环
    • 增强for循环(for in)

例子:关于前三钟的例字:

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
43
44
45
46
47
<script>
// 定义json
// 1.基本json
var person = {"name":"rick","age":58,"isMan":true};
// 获取数据
var name = person.name; // 获取name
alert(name)
var age = person["age"]; // 获取age
alert(age)
// 2.嵌套格式 json中嵌套数组
var persons = {
"person": [
{
"name": "rick",
"age": 58,
"isMan": true
},
{
"name": "tom",
"age": 18,
"isMan": true
},
{
"name": "jerry",
"age": 19,
"isMan": false
}
]
}
// 获取数组
var name2 = persons.person[1].name; // 获取数组中第二个person的name
alert(name2)
// 3.嵌套格式 数组中嵌套json
var arr = [{
"name": "rick",
"age": 58,
"isMan": true
}, {
"name": "rick",
"age": 58,
"isMan": true
}, {
"name": "rick",
"age": 58,
"isMan": true
}]
</script>

关于遍历的例子:

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
<script>

var person = {"name":"rick","age":58,"isMan":true};
// 获取person对象中所有的键和值(for in循环)
for(key in person){
//alert(key + ":" + person.key); //这样的方式获取不行。因为相当于 person."name"
alert(key+":"+person[key])
}
var arr = [{
"name": "rick",
"age": 58,
"isMan": true
}, {
"name": "tom",
"age": 18,
"isMan": true
}, {
"name": "jerry",
"age": 19,
"isMan": false
}]
// 获取arr中的所有值(for循环嵌套)
for(var i = 0;i<arr.length;i++){
var perosn = arr[i];
for(key in perosn){
alert(key+":"+perosn[key])
}
}
</script>

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

常用的JSON解析器:

  • Jsonlib
  • Gson
  • Fastjson
  • Jackson

这里我们选择Jackson来学习(springMVC框架内置的json解析器)

JSON数据转换为Java对象

(了解)

步骤:

  1. 导入jackson的相关jar包
  2. 创建Jackson核心对象 ObjectMapper
  3. 调用ObjectMapper的相关方法进行转换
    • readValue(json字符串数据,Class)

例子:

1
2
3
4
5
6
7
8
9
10
11
// JSON数据转换为Java对象
@Test
public void test5() throws IOException {
// 初始化JSON
String JSON = "{\"name\":\"tom\",\"age\":18,\"man\":false}";
// 2.创建Jackson核心对象:ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
// 3.调用ObjectMapper的相关方法进行转换
Person person = objectMapper.readValue(JSON,Person.class);
System.out.println(person); // Person{name='tom', age=18, isMan=false}
}

Java对象转换为JSON数据

步骤:

  1. 导入jackson的相关jar包

    相关jar包

  2. 创建Jackson核心对象:ObjectMapper

  3. 调用ObjectMapper的相关方法进行转换。转换方法有:

    • writeValue(参数1,obj)。其中参数1可以为:
      • File:将obj对象转换为JSON字符串,并保存到指定的文件中
      • Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
      • OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中
    • writeValueAsString(obj):将对象转为json字符串

例子:先创建Person类,代码如下:

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
package domain;

public class Person {
private String name;
private int age;
private Boolean isMan;

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", isMan=" + isMan +
'}';
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public Boolean getMan() {
return isMan;
}

public void setMan(Boolean man) {
isMan = man;
}
}

然后创建测试类JacksonTest代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import domain.Person;
import org.junit.Test;

public class JacksonTest {
// Java对象转换为JSON(结果为JSON格式的字符串)
@Test
public void test1() throws JsonProcessingException {
// 1.创建person对象
Person person = new Person();
person.setName("tom");
person.setAge(18);
person.setMan(false);
// 2.创建Jackson核心对象:ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
// 3.调用ObjectMapper的相关方法进行转换
String json = objectMapper.writeValueAsString(person);
System.out.println(json); // {"name":"tom","age":18,"man":false}
}
}

关于writeValue(参数1,obj)方法的讲解:视频讲解

相关注解

  • @JsonIgnore:转JSON的时候该忽略属性
  • @JsonFormat:属性值的格式化(例如:@JsonFormat(pattern = "yyyy-MM-dd")

视频讲解

Jackson 序列化和反序列化

复杂Java对象转换为JSON

  • List转JSON:数组(如:[{"name":"tom","age":18,"man":false},{"name":"rick","age":58,"man":true},{"name":"Jerry","age":19,"man":true}]
  • Map转JSON:对象(如:{"name":"rick","isMan":false,"age":58}

例子:

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import domain.Person;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;

public class JacksonTest {
// Java对象转换为JSON(结果为JSON格式的字符串)
@Test
public void test1() throws JsonProcessingException {
// 1.创建person对象
Person person = new Person();
person.setName("tom");
person.setAge(18);
person.setMan(false);
// 2.创建Jackson核心对象:ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
// 3.调用ObjectMapper的相关方法进行转换
String json = objectMapper.writeValueAsString(person);
System.out.println(json); // {"name":"tom","age":18,"man":false}
}

@Test
public void test2() throws JsonProcessingException {
// 1.创建person对象
Person person1 = new Person();
person1.setName("tom");
person1.setAge(18);
person1.setMan(false);
Person person2 = new Person();
person2.setName("rick");
person2.setAge(58);
person2.setMan(true);
Person person3 = new Person();
person3.setName("Jerry");
person3.setAge(19);
person3.setMan(true);
// 创建List集合
ArrayList<Person> peoples = new ArrayList<>();
peoples.add(person1);
peoples.add(person2);
peoples.add(person3);

// 2.创建Jackson核心对象:ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
// 3.调用ObjectMapper的相关方法进行转换
String json = objectMapper.writeValueAsString(peoples);
System.out.println(json); // [{"name":"tom","age":18,"man":false},{"name":"rick","age":58,"man":true},{"name":"Jerry","age":19,"man":true}]
}

@Test
public void test3() throws JsonProcessingException {
// 1.创建person对象
HashMap<String, Object> personHashMap = new HashMap<>();
personHashMap.put("name","rick");
personHashMap.put("age",58);
personHashMap.put("isMan",false);
// 2.创建Jackson核心对象:ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
// 3.调用ObjectMapper的相关方法进行转换
String json = objectMapper.writeValueAsString(personHashMap);
System.out.println(json); // {"name":"rick","isMan":false,"age":58}
}

}

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

分析:

视频讲解

代码实现,实现创建前端html页面,代码如下:

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
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
<script src="js/jquery-3.5.1.min.js"></script>


<script>
//在页面加载完成后
$(function () {
//给username绑定blur事件(失焦点时间)
$("#username").blur(function () {
//获取username文本输入框的值
var username = $(this).val();
//发送ajax请求
$.get("find",{username:username},function (data) {
//期望服务器响应回的数据格式:{"userExsit":true,"msg":"此用户名太受欢迎,请更换一个"}
// {"userExsit":false,"msg":"用户名可用"}
// alert(data);
var span = $("#s_username");
//判断userExsit键的值是否是true
if(data.userExsit){ //用户名存在
span.css("color","red");
span.html(data.msg);
}else{ //用户名不存在
span.css("color","green");
span.html(data.msg);
}
},"json"); // 指定ajax传输类型为json

});
});

</script>
</head>
<body>

<form>
<input type="text" id="username" name="username" placeholder="请输入用户名">
<span id="s_username"></span>
<br>
<input type="password" name="password" placeholder="请输入密码"><br>
<input type="submit" value="注册"><br>
</form>

</body>
</html>

然后创建findUserServlet,代码如下:

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
package 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;

@WebServlet("/find")
public class findUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 解决中文乱码
response.setContentType("text/html;charset=utf-8");
// 1.获取用户名
String username = request.getParameter("username");
// 2.调用service层判断用户名是否存在(service再到dao层)
HashMap<String, Object> hashMap = new HashMap<>();
// 这里为了简化代码,判断逻辑写在这里
if ("tom".equals(username)){ // 存在
hashMap.put("userExsit",true);
hashMap.put("msg","此用户名太受欢迎,请更换一个");
}else { //不存在
hashMap.put("userExsit",false);
hashMap.put("msg","用户名可用");
}
// hashMap转为JSON,并传递给客户端
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(response.getWriter(),hashMap); // 将obj对象转换为JSON字符串,并将json数据填充到字符输出流中

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

在浏览器中访问:http://localhost:8080/json/regist.html

结果如下:

注意点:

服务器响应的数据,在客户端使用时,要想当做json数据格式使用。有两种方式:

  • $.get(type):将最后一个参数type指定为"json"
  • 在服务器端设置MIME类型:response.setContentType("application/json;charset=utf-8");