JavaWeb 数据交换与异步请求:JSON 与 Ajax 技术解析
介绍 JavaWeb 中的数据交换与异步请求技术。首先讲解 JSON 格式、快速入门及对象字符串转换,演示 Java 中使用 Gson 库进行对象映射。其次阐述 Ajax 原理,对比原生 JavaScript 与 JQuery 的 Ajax 请求实现方式。最后简要说明 ThreadLocal 在线程数据共享与安全中的应用。旨在帮助开发者掌握前后端数据交互核心技能。

介绍 JavaWeb 中的数据交换与异步请求技术。首先讲解 JSON 格式、快速入门及对象字符串转换,演示 Java 中使用 Gson 库进行对象映射。其次阐述 Ajax 原理,对比原生 JavaScript 与 JQuery 的 Ajax 请求实现方式。最后简要说明 ThreadLocal 在线程数据共享与安全中的应用。旨在帮助开发者掌握前后端数据交互核心技能。



var 变量名 = {
"k1": value, // Number 类型
"k2": "value", // 字符串类型
"k3": [], // 数组类型
"k4": {}, // json 对象类型
"k5": [{},{}] // json 数组
};
: 表示,"名称":值,注意名称是字符串,因此要用双引号引起来。, 分隔。"名称 1":值,"名称 2":值{} 表示。{"名称 1":值,"名称 2":值}[] 表示。[{"名称 1":值,"名称 2":值}, {"名称 1":"名称 2":值}]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, // Number
"key3": [1, "hello", 2.3], // 数组
"key4": {"age":12,"name":"jack"}, // json 对象
"key5": [ // json 数组
{"k1":10,"k2":"milan"},
{"k3":30,"k4":"smith"}
]
};
//访问 json 的属性
console.log("key1= "+ myJson.key1);
// 访问 json 的数组属性
console.log("key3[1]= "+ myJson.key3[1]); // hello
// 访问 key4 的 name 属性
console.log("name= "+ myJson.key4.name); // jack
// 访问 key5 json 数组的第一个元素
console.log("myJson.key5[0]= "+ myJson.key5[0]); // [object, object]
console.(+ myJson.[].);
</script>
</head>
<body>
<h1>json 快速入门案例</h1>
</body>
</html>
JSON.stringify(json) 功能:将一个 json 对象转换成为 json 字符串。JSON.parse(jsonString) 功能:将一个 json 字符串转换成为 json 对象。代码演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSON 对象和字符串对象转换</title>
<script type="text/javascript">
// 一个 json 对象
var jsonObj = {
"name": "韩顺平教育",
age: 10
};
//JSON 是一个 build-in 对象,内建对象,有方法可以使用
console.log(JSON);
// 把 json 对象转换成为字符串对象
var jsonStr = JSON.stringify(jsonObj);
console.log(jsonStr);
// 把 json 对象的字符串,转换成为 json 对象
var jsonObj2 = JSON.parse(jsonStr);
console.log(jsonObj2);
</script>
</head>
<body>
<h1>JSON 对象和字符串对象转换</h1>
</body>
</html>
JSON.stringify(jsonObject) 会返回对应 string,并不会影响原来 json 对象。JSON.parse(string) 函数会返回对应的 json 对象,并不会影响原来 string。' ' 表示字符串。
例如 var json_person = {"name": "jack", "age": 100};
也可以写成 var json_person = {'name': 'jack', 'age': 100};"",否则会报错。
例如:var str_dog = "{'name':'小黄狗', 'age': 4}"; 转 json 就会报错。JSON.stringify(jsonObject) 返回的字符串,都是 "" 表示的字符串,所以在语法格式正确的情况下,是可以重新转成 json 对象的。gson.jar。
//创建一个 gson 对象,当做工具对象使用
Gson gson = new Gson();
//演示 javabean 和 json 字符串的转换
Book book = new Book(100, "零基础学 Java");
//1. 演示把 javaBean -> json 字符串
String strBook = gson.toJson(book);
System.out.println("strBook=" + strBook);
//2. json 字符串->javabean
Book book2 = gson.fromJson(strBook, Book.class);
System.out.println("book2=" + book2);
解读 (1)
strBook就是 json 字符串 (2)Book.class指定将 json 字符串转成 Book 对象 (3) 底层是反射机制
//1. 演示把 list 对象 -> json 字符串
List<Book> bookList = new ArrayList<>();
bookList.add(new Book(200, "天龙八部"));
bookList.add(new Book(300, "三国演义"));
//因为把对象,集合转成字符串,相对比较简单
//底层只需要遍历,按照 json 格式拼接返回即可
String strBookList = gson.toJson(bookList);
System.out.println("strBookList= " + strBookList);
因为把对象,集合转成字符串,相对比较简单,底层只需要遍历,按照 json 格式拼接返回即可。
(1) 如果需要把 json 字符串 转成 集合这样复杂的类型,需要使用 gson 提供的一个类。
(2) TypeToken,是一个自定义泛型类,然后通过 TypeToken 来指定我们需要转换成的类型。
Type type = new TypeToken<List<Book>>(){}.getType();
List<Book> bookList2 = gson.fromJson(strBookList, type);
System.out.println("bookList2= " + bookList2);
(1) 返回类型的完整路径
java.util.List<com.hspedu.json.Book>(2) gson 的设计者,需要得到类型的完整路径,然后进行底层反射 (3) 所以 gson 设计者就提供 TypeToken,来搞定。
== 使用 TypeToken,为什么要加 {} == 首先我们看一下 TypeToken 的源码。
package com.google.gson.reflect;
public class TypeToken<T> {
final Class<? super T> rawType;
final Type type;
final int hashCode;
protected TypeToken() {
this.type = getSuperclassTypeParameter(this.getClass());
this.rawType = Types.getRawType(this.type);
this.hashCode = this.type.hashCode();
}
}
(1) 如果我们
new TypeToken<List<Book>>()错误提示'TypeToken()' has protected access in 'com.google.gson.reflect.TypeToken'(2) 因为 TypeToken 的无参构造器是 protected,而new TypeToken<List<Book>>()就是调用其无参构造器 (3) 根据 java 基础,如果一个方法是 protected,而且不在同一个包,是不能直接访问的,因此报错 (4) 为什么new TypeToken<List<Book>>(){}使用就可以,这里就涉及到匿名内部类的知识。 (5) 当new TypeToken<List<Book>>(){}其实这个类型就不是 TypeToken 而是一个匿名内部类 (子类),继承 (6) 而且这个匿名内部类是有自己的无参构造器 (隐式),根据 java 基础规则,当执行子类的无参构造器时,默认 super();
//把 map 对象->json 字符串
Map<String, Book> bookMap = new HashMap<>();
bookMap.put("k1", new Book(400, "射雕英雄传"));
bookMap.put("k2", new Book(500, "西游记"));
String strBookMap = gson.toJson(bookMap);
System.out.println("strBookMap=" + strBookMap);
// 把 json 字符串 -> map 对象
// new TypeToken<Map<String, Book>>() {}.getType()=> java.util.Map<java....String,com.hspedu.json.Book>
Map<String, Book> bookMap2 = gson.fromJson(strBookMap, new TypeToken<Map<String, Book>>(){}.getType());
Ajax 经典应用场景

参考在线文档:https://www.w3school.com.cn/js/js_ajax_intro.asp
点击验证用户名,使用 ajax 方式,服务端验证该用户名是否已经占用了,如果该用户已经占用,以 json 格式返回该用户信息。
<script type="text/javascript">
window.onload = function(){
var checkButton = document.getElementById("checkButton");
//给 checkButton 绑定 onclick
checkButton.onclick = function(){
//1. 创建 XMLHttpRequest 对象 (!!!) [ajax 引擎对象]
var xhr = new XMLHttpRequest();
// 获取用户填写的用户名
var uname = document.getElementById("uname").value;
//2. 准备发送指定数据 open, send
//(1)"GET" 请求方式可以 GET/POST
//(2)"/ajax/checkUserServlet?username=" + uname 就是 url
//(3)true , 表示异步发送
xhr.open("GET","/ajax/checkUserServlet?uname=" + uname,true);
//在 send 函数调用前,给 XMLHttpRequest 绑定一个事件 onreadystatechange
//该事件表示,可以去指定一个函数,当数据变化,会触发 onreadystatechange
// 每当 xhr 对象 readyState 改变时,就会触发 onreadystatechange 事件
xhr.onreadystatechange = function(){
//如果请求已完成,且响应已就绪,并且状态码是 200
if(xhr.readyState == 4 && xhr.status == 200){
//把返回的 json 数据,显示在 div
document.getElementById(). = xhr.;
responseText = xhr.;
xhr.();
}
}
}
}
</script>
在线文档:https://www.w3school.com.cn/jquery/jquery_ajax_get_post.asp
$.ajax 方法$.ajax 常用参数
url: 请求的地址type: 请求的方式 get 或 postdata: 发送到服务器的数据。将自动转换为请求字符串格式success: 成功的回调函数error: 失败后的回调函数dataType: 返回的数据类型 常用 json 或 text$.get 请求和 $.post 请求$.get 和 $.post 常用参数
url: 请求的 URL 地址data: 请求发送到服务器的数据success: 成功时回调函数type: 返回内容格式,xml, html, script, json, text$.get 和 $.post 底层还是使用 $.ajax() 方法来实现异步请求。$.getJSON$.getJSON 常用参数
url: 请求发送的哪个 URLdata: 请求发送到服务器的数据success: 请求成功时运行的函数$.getJSON 底层使用 $.ajax() 方法来实现异步请求。类图

ThreadLocal<Object> threadLocal = new ThreadLocal<>();
threadLocal.set(dog);
如果希望在同一个线程共享多个对象/数据,就在创建一个 ThreadLocal 对象 //threadLocal2.set(pig);
只要明白这个机制,后面的 set get 全部通透。
public void set(T value) {
//获取当前线程
Thread t = Thread.currentThread();
//获取当前线程的 ThreadLocal.ThreadLocalMap 属性 threadLocals , 类型是 ThreadLocal 的静态内部类
//threadLocals 有一个属性 Entry[], 类型 ThreadLocal.ThreadLocalMap.Entry
//k-> ThreadLocal 对象 v-> 值
ThreadLocalMap map = getMap(t);
if(map != null) map.set(this, value);
else createMap(t, value);
}
说明:
- ThreadLocalMap 对象是和当前 Thread 对象的绑定的属性
- ThreadLocalMap 对象含有 Entry[] table; 这个 Entry(K,V)
- 这个 key 就是 ThreadLocal 对象,V 就是你要放入的对象,比如 dog
- 当执行了 threadLocal.set(dog) 后,内存布局图为 [看图]


这里涉及到的弱引用,涉及到知识点很多,暂不深入。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online