JavaWeb 核心:JSON 数据交换与 Ajax 异步请求详解
一、数据交换——JSON
1. JSON 简介
JSON(JavaScript Object Notation)是一种轻量级的文本数据交换格式。它独立于编程语言,无论是 Java、PHP、Go 还是其他语言都能轻松解析。JSON 具有自我描述性,结构清晰,非常适合前后端交互。

2. JSON 快速入门
定义格式
var myJson = {
"k1": value, // Number 类型
"k2": "value", // 字符串类型
"k3": [], // 数组类型
"k4": {}, // JSON 对象类型
"k5": [{}, {}] // JSON 数组
};
规则解读
- 键值对:映射用冒号
:表示,"名称": 值。注意键名必须是双引号包裹的字符串。 - 分隔符:并列的数据项之间用逗号
,分隔。 - 集合:对象用大括号
{}包裹,数组用方括号[]包裹。 - 数据类型:支持
string,number,object,array,true,false,null。
案例演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>json 快速入门案例</title>
<script type="text/javascript">
var myJson = {
"key1": "教育",
"key2": 123,
"key3": [1, "hello", 2.3],
"key4": {"age": 12, "name": "jack"},
"key5": [
{"k1": 10, "k2": "milan"},
{"k3": 30, "k4": "smith"}
]
};
console.log("key1= " + myJson.key1);
console.log("key3[1]= " + myJson.key3[1]); // hello
console.log("name= " + myJson.key4.name); // jack
console.log("myJson.key5[0].k2= " + myJson.key5[0].k2); // milan
</script>
</head>
<body>
<h1>json 快速入门案例</h1>
</body>
</html>
3. JSON 对象与字符串转换
在实际开发中,我们常需要在 JSON 对象和字符串之间转换。
JSON.stringify(json): 将 JSON 对象转换为 JSON 字符串(序列化)。JSON.parse(jsonString): 将 JSON 字符串转换为 JSON 对象(反序列化)。
// 一个 json 对象
var jsonObj = {
"name": "韩顺平教育",
age: 10
};
// 把 json 对象转换成为字符串对象
var jsonStr = JSON.stringify(jsonObj);
console.log(jsonStr);
// 把 json 对象的字符串,转换成为 json 对象
var jsonObj2 = JSON.parse(jsonStr);
console.log(jsonObj2);
注意事项:
JSON.stringify()返回字符串,不影响原对象。JSON.parse()返回对象,不影响原字符串。- 定义 JSON 对象时,键名建议使用双引号;但在原生字符串转 JSON 对象时,必须使用双引号,否则可能报错。
4. JSON 在 Java 中使用
Java 处理 JSON 通常引入第三方库,这里以 Google 的 Gson 为例。
应用场景
- JavaBean 对象与 JSON 字符串互转
- List 集合与 JSON 字符串互转
- Map 集合与 JSON 字符串互转

代码演示
1. JavaBean 与 JSON 字符串转换
// 创建一个 gson 对象
Gson gson = new Gson();
// 演示 javabean -> json 字符串
Book book = new Book(100, "零基础学 Java");
String strBook = gson.toJson(book);
System.out.println("strBook=" + strBook);
// 演示 json 字符串 -> javabean
Book book2 = gson.fromJson(strBook, Book.class);
System.out.println("book2=" + book2);
底层通过反射机制实现,Book.class 指定了目标类型。
2. List 对象与 JSON 字符串转换
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(200, "天龙八部"));
bookList.add(new Book(300, "三国演义"));
String strBookList = gson.toJson(bookList);
System.out.println("strBookList=" + strBookList);
对象或集合转字符串相对简单,Gson 内部遍历拼接即可。
3. JSON 字符串转 List 对象
复杂类型转换需要使用 TypeToken 来指定泛型信息。
Type type = new TypeToken<List<Book>>(){}.getType();
List<Book> bookList2 = gson.fromJson(strBookList, type);
System.out.println("bookList2=" + bookList2);
为什么加 {}?
TypeToken 的构造器是 protected 的,不能直接实例化。使用匿名内部类 new TypeToken<>(){} 可以创建子类,利用隐式无参构造器调用父类构造器,从而获取完整的泛型类型路径。
4. Map 对象与 JSON 字符串转换 逻辑与 List 类似。
Map<String, Book> bookMap = new HashMap<>();
bookMap.put("k1", new Book(400, "射雕英雄传"));
bookMap.put("k2", new Book(500, "西游记"));
String strBookMap = gson.toJson(bookMap);
Map<String, Book> bookMap2 = gson.fromJson(
strBookMap,
new TypeToken<Map<String, Book>>(){}.getType()
);
二、异步请求——Ajax
1. 基本介绍
AJAX(Asynchronous Javascript And XML)是一种允许网页无需刷新即可与服务器交换数据的技术。
典型场景:
- 搜索引擎关键字自动提示
- 动态加载数据(树形菜单、联动菜单)
- 表单验证(如用户名是否被占用)
- 局部页面刷新

2. JavaScript 原生 Ajax 请求
原生 Ajax 基于 XMLHttpRequest 对象。
示例:用户名验证
window.onload = function() {
var checkButton = document.getElementById("checkButton");
checkButton.onclick = function() {
// 1. 创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
// 2. 准备发送数据
var uname = document.getElementById("uname").value;
// open(method, url, async)
xhr.open("GET", "/ajax/checkUserServlet?uname=" + uname, true);
// 3. 绑定事件监听
xhr.onreadystatechange = function() {
// readyState == 4 (完成), status == 200 (成功)
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById("div1").innerHTML = xhr.responseText;
}
};
// 4. 发送请求
xhr.send();
};
};
问题分析: 原生写法代码量大,且需处理浏览器兼容性问题。实际工作中更倾向于使用封装好的库。
3. JQuery 的 Ajax 请求
JQuery 简化了 Ajax 操作,提供了 $.ajax, $.get, $.post, $.getJSON 等方法。
常用参数说明:
url: 请求地址type: 请求方式 (get/post)data: 发送的数据success: 成功回调函数error: 失败回调函数dataType: 预期返回数据类型 (json/text/xml)
jQuery 示例:
$.ajax({
url: '/ajax/checkUserServlet',
type: 'GET',
data: {uname: 'test'},
dataType: 'json',
success: function(data) {
console.log('验证结果:', data);
},
error: function(xhr) {
console.error('请求失败');
}
});
三、线程数据共享和安全 - ThreadLocal
1. ThreadLocal 基本介绍
在多线程环境下,ThreadLocal 用于解决线程间的数据隔离问题,确保每个线程拥有独立的变量副本。
核心特性:
- 为当前线程关联一个数据(普通变量、对象等)。
- 类似 Map 存取,Key 是当前线程,Value 是存储的数据。
- 每个 ThreadLocal 实例只能为一个线程关联一个数据。
- 线程销毁后,数据自动释放。

使用示例:
ThreadLocal<Object> threadLocal = new ThreadLocal<>();
threadLocal.set(dog);
若需存储多个对象,需创建多个 ThreadLocal 实例。
2. 源码分析
理解 set 方法有助于掌握其机制。
public void set(T value) {
// 获取当前线程
Thread t = Thread.currentThread();
// 获取当前线程的 ThreadLocal.ThreadLocalMap 属性
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
关键点:
ThreadLocalMap是Thread的内部类,与线程绑定。- Entry 的 Key 是
ThreadLocal对象本身,Value 是存储的值。 - 内存布局上,每个线程都有自己的
ThreadLocalMap,实现了数据隔离。

关于弱引用等细节较为深入,此处暂不展开,但理解上述机制已足够应对大多数并发场景。

