文章目录
前言
想必大家在入门Vue3.0,又学习了J2EE中Servlet相关知识,了解了诸如web响应和请求,Cookie,Session,servletContext后,一定很想知道不刷新页面下页面的局部刷新是怎么实现的,没错他就是我们今天要介绍的主角——ajax!
1. ajax简介
Ajax即Asynchronous Javascript And XML(异步JavaScript和XML)在 2005年被Jesse James Garrett提出的新术语,用来描述一种使用现有技术集合的‘新’方法,包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest。使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作。
简单讲:
- Asynchronous Javascript And XML(异步JavaScript和XML)
- Ajax可以在不刷新页面的前提下,进行页面局部更新
- Ajax是前端开发的必备技能,也是主流的开发模式
1.1 运行原理
Ajax运行原理如下:
- 用户与Web页面交互时,触发JavaScript代码;
- JavaScript代码通过XMLHttpRequest对象向服务器发送请求,同时指定回调函数;
- 服务器接收请求后,进行处理并将数据以XML或JSON格式返回给JavaScript代码;
- JavaScript代码接收到服务器返回数据后,执行相应的回调函数,将数据进行处理并显示到页面上,而不需要刷新整个页面。
核心思想是通过JavaScript实现异步请求和相应的回调函数,使得Web应用程序能够动态地更新界面,提高用户体验。Ajax的优点包括能够减少页面的刷新次数、减轻服务器和带宽负载、提高用户交互体验等。
1.2 使用示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input id="btnLoad" type="button" value="加载" />
<div id="divContent"></div>
<script>
document.getElementById("btnLoad").onclick=function () {
//1.创建XmlHttpRequest对象
var xmlhttp;
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
}else{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.发送Ajax请求
xmlhttp.open("GET","/content");
xmlhttp.send();
//3.处理服务器响应
xmlhttp.onreadystatechange=function (){
if(xmlhttp.readyState==4 && xmlhttp.status==200){
let responseText = xmlhttp.responseText;
document.getElementById("divContent").innerHTML=
document.getElementById("divContent").innerHTML+"<br/>"+responseText;
}
}
}
</script>
</body>
</html>
在这个例子中,当按钮 “加载” 被点击时,点击事件触发了一个匿名函数,该函数首先创建一个 XMLHttpRequest 对象,然后使用 open() 方法指定请求的 URL 和 HTTP 方法(这里使用 GET 方法),最后使用 send() 方法发送请求。
在服务器响应之后,处理函数(onreadystatechange)会被调用。在此过程中,我们使用 readyState 属性检查请求的状态,当状态为 4 时表示请求已完成,同时使用 status 属性检查响应的状态码是否为 200(这表示成功)。如果都成功了,我们就可以获取到来自服务器的响应文本,并将其添加到页面的 div 元素中。
这个代码段演示了如何使用 JavaScript 和 XMLHttpRequest 对象创建 AJAX 请求来通过异步方式从服务器获取数据。
2. ajax相关工具
2.1 json
- JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。
- 采用完全独立于编程语言的文本格式来存储和表示数据。
- 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
- 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
看个示例,这个 JSON 数据包含了两个评论,每个评论有一个唯一的 ID,评论人的名字,评论内容,评论时间,以及若干个回复(replies),每个回复也有一个唯一的 ID,回复人的名字,回复内容和回复时间。
这种 JSON 数据结构可以被用于构建一个评论区的前端页面,包括评论列表,评论详情和回复列表。在前端页面上,我们可以通过遍历 comments 数组来展示所有评论,同时在每个评论下面展示该评论的回复列表。
{
"comments": [
{
"id": 1,
"name": "小明",
"content": "这篇文章写得很棒,我学到了很多。",
"time": "2023-07-20 10:00:00",
"replies": [
{
"id": 11,
"name": "小红",
"content": "同感!楼主写得真好。",
"time": "2023-07-21 12:00:00"
},
{
"id": 12,
"name": "小芳",
"content": "我也觉得很有用,学习了不少知识。",
"time": "2023-07-22 13:00:00"
}
]
},
{
"id": 2,
"name": "张三",
"content": "我有几个问题不太清楚,希望有大佬帮忙解答。",
"time": "2023-07-20 09:00:00",
"replies": [
{
"id": 21,
"name": "李四",
"content": "你可以把问题列出来,我们一起来研究一下。",
"time": "2023-07-21 10:00:00"
},
{
"id": 22,
"name": "王五",
"content": "我也有同样的问题,希望能得到答案。",
"time": "2023-07-22 11:00:00"
}
]
}
]
}
2.2 jackson
Jackson是一个Java库,用于在Java对象(POJO)和JSON对象之间进行转换和序列化/反序列化。它可以将Java对象转换为JSON格式的字符串,也可以将JSON格式的字符串转换为Java对象。此外,Jackson还提供了其他功能,如支持XML和CSV格式的转换以及对Java对象的验证和格式化。
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonExample {
public static void main(String[] args) throws Exception {
// 创建一个ObjectMapper对象,用于序列化和反序列化JSON
ObjectMapper mapper = new ObjectMapper();
// 将一个Java对象序列化成JSON字符串
User user = new User("Tom", 23);
String json = mapper.writeValueAsString(user);
System.out.println(json);
// 将一个JSON字符串反序列化成Java对象
User user2 = mapper.readValue(json, User.class);
System.out.println(user2.getName() + ", " + user2.getAge());
}
// 一个简单的Java Bean类
static class User {
private String name;
private int age;
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
}
上述示例中,我们创建了一个ObjectMapper对象,用于序列化和反序列化JSON。然后我们定义了一个User类,它是一个简单的Java Bean,包含了name和age两个属性。接着,我们将一个User对象序列化成JSON字符串,并将其打印出来。然后,我们将这个JSON字符串反序列化成另一个User对象,并打印出它的name和age属性。
Jackson的核心功能就是在Java对象和JSON之间进行序列化和反序列化,它为我们提供了非常方便的API,使得我们可以轻松地将Java对象转换成JSON格式,或者将JSON字符串转换成Java对象。同时,Jackson还提供了一些高级特性,例如格式化输出、支持多态类型、支持自定义序列化和反序列化等,使得我们能够满足更多复杂的需求。
2.3 axios
Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
import axios from 'axios';
// 发送 GET 请求
axios.get('/api/data')
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.error(error);
});
// 发送 POST 请求
axios.post('/api/data', {
name: 'John',
age: 30
})
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.error(error);
});
上述示例,它使用Axios发送GET和POST请求。当请求成功时,响应的数据将打印到控制台上,否则将会捕获错误并将其打印到控制台上。
3. 项目实战——多级联动菜单
3.1 项目需求
- 实现多级联动菜单
- 使用axios来发送请求
- 使用JSON格式来传输数据
- 使用Servlet来处理请求
- 使用Jackson来将对象转换为JSON格式
- 后台数据可以直接创建模拟对象
3.2 项目开发
前端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>多级联动菜单</title>
</head>
<body>
<select id="select1"></select>
<select id="select2"></select>
<select id="select3"></select>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
let data = []; // 存储所有数据
// 获取数据
axios.get('http://localhost:8080/MenuServlet')
.then(function (response) {
data = response.data;
initSelect1();
});
// 初始化第一级下拉框
function initSelect1() {
let select1 = document.getElementById("select1");
select1.innerHTML = "";
for (let i = 0; i < data.length; i++) {
let option = document.createElement("option");
option.text = data[i].name;
option.value = i;
select1.add(option);
}
initSelect2();
}
// 初始化第二级下拉框
function initSelect2() {
let select1 = document.getElementById("select1");
let select2 = document.getElementById("select2");
select2.innerHTML = "";
let index = select1.selectedIndex;
if (index < 0) {
return;
}
let subMenu = data[index].subMenu;
for (let i = 0; i < subMenu.length; i++) {
let option = document.createElement("option");
option.text = subMenu[i].name;
option.value = i;
select2.add(option);
}
initSelect3();
}
// 初始化第三级下拉框
function initSelect3() {
let select2 = document.getElementById("select2");
let select3 = document.getElementById("select3");
select3.innerHTML = "";
let index1 = document.getElementById("select1").selectedIndex;
let index2 = select2.selectedIndex;
if (index2 < 0) {
return;
}
let subSubMenu = data[index1].subMenu[index2].subSubMenu;
for (let i = 0; i < subSubMenu.length; i++) {
let option = document.createElement("option");
option.text = subSubMenu[i].name;
option.value = i;
select3.add(option);
}
}
// 监听下拉框变化事件
document.getElementById("select1").addEventListener("change", function () {
initSelect2();
});
document.getElementById("select2").addEventListener("change", function () {
initSelect3();
});
</script>
</body>
</html>
后端代码:
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
public class MenuServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<MenuItem> data = new ArrayList<>();
MenuItem menu1 = new MenuItem("菜单1");
menu1.addSubMenu(new SubMenuItem("子菜单1-1"));
menu1.addSubMenu(new SubMenuItem("子菜单1-2"));
menu1.addSubMenu(new SubMenuItem("子菜单1-3"));
data.add(menu1);
MenuItem menu2 = new MenuItem("菜单2");
menu2.addSubMenu(new SubMenuItem("子菜单2-1"));
menu2.addSubMenu(new SubMenuItem("子菜单2-2"));
menu2.addSubMenu(new SubMenuItem("子菜单2-3"));
data.add(menu2);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(data);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(json);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
菜单项类:
public class MenuItem {
private String name;
private List<SubMenuItem> subMenu;
public MenuItem(String name) {
this.name = name;
this.subMenu = new ArrayList<>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<SubMenuItem> getSubMenu() {
return subMenu;
}
public void setSubMenu(List<SubMenuItem> subMenu) {
this.subMenu = subMenu;
}
public void addSubMenu(SubMenuItem subMenu) {
this.subMenu.add(subMenu);
}
}
子菜单项类:
public class SubMenuItem {
private String name;
private List<SubSubMenu> subSubMenu;
public SubMenuItem(String name) {
this.name = name;
this.subSubMenu = new ArrayList<>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<SubSubMenu> getSubSubMenu() {
return subSubMenu;
}
public void setSubSubMenu(List<SubSubMenu> subSubMenu) {
this.subSubMenu = subSubMenu;
}
public void addSubSubMenu(SubSubMenu subSubMenu) {
this.subSubMenu.add(subSubMenu);
}
}
子子菜单项类:
public class SubSubMenu {
private String name;
public SubSubMenu(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
运行项目后,就可以看到一个多级联动菜单了。
以上便是本文全部内容啦,希望能够带来帮助!