JavaWeb-ajax实战入门

前言

想必大家在入门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 运行原理

User Browser Server 发送 AJAX 请求 发送 AJAX 请求 返回数据 显示数据 User Browser Server

Ajax运行原理如下:

  1. 用户与Web页面交互时,触发JavaScript代码;
  2. JavaScript代码通过XMLHttpRequest对象向服务器发送请求,同时指定回调函数;
  3. 服务器接收请求后,进行处理并将数据以XML或JSON格式返回给JavaScript代码;
  4. 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 项目需求

  1. 实现多级联动菜单
  2. 使用axios来发送请求
  3. 使用JSON格式来传输数据
  4. 使用Servlet来处理请求
  5. 使用Jackson来将对象转换为JSON格式
  6. 后台数据可以直接创建模拟对象

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

}

运行项目后,就可以看到一个多级联动菜单了。


以上便是本文全部内容啦,希望能够带来帮助!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JournE-Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值