网站广告费一般多少钱/北京网站建设公司
文章目录
- 1,前言
- 2,什么是多层次树结构?
- 3,异步加载的意义
- 4,技术选型与实现思路
- 5,具体案例
- 5.1,项目结构
- 5.2,项目配置(pom.xml)
- 5.3,配置文件(application.yml)
- 5.4,实体类与Mapper接口
- 5.5,Service层
- 5.6,controller
- 5.7,前端页面与异步加载实现
- 5.8,数据库结构
1,前言
在使用 Spring Boot 和 MyBatis-Plus 实现多层次树结构的异步加载策略时,理解其基本原理和技术背景是至关重要的。本文将详细探讨如何通过 Spring Boot 的 RESTful API 和 MyBatis-Plus 的强大功能实现多层次树结构的异步加载,并展示如何使用 Thymeleaf、Bootstrap 和 JavaScript 实现前端的动态渲染。
2,什么是多层次树结构?
多层次树结构是许多应用场景中的常见需求,尤其是在分类管理、组织结构、权限管理等场景中。例如,电商平台中的商品分类可以有多个层级,从根类别到具体商品的详细分类,形成一个递归的树形结构。为了有效管理和展示这些数据,通常需要对其进行异步加载,即在用户需要时才加载具体的层级数据,而不是一次性加载所有数据。这不仅能够减少初始数据加载的时间,还可以提高用户体验。
3,异步加载的意义
在处理大型树结构时,性能是一个非常重要的考量因素。一次性加载所有层级的数据不仅可能会导致数据传输过大,还会引发前端页面的性能问题。异步加载策略通过在用户展开某个节点时,动态加载该节点下的子节点数据,有效地减少了数据传输量,提高了页面响应速度。这种方法尤其适用于需要处理大量数据并且层级较多的场景。
4,技术选型与实现思路
为了实现上述功能,我们将采用 Spring Boot 构建后端 API,使用 MyBatis-Plus 处理数据库操作,并通过前端的 Thymeleaf 模板、Bootstrap 进行 UI 展示。具体实现步骤包括:
- 数据库设计: 创建一个 category 表,包含 id、parent_id、name 等字段,用于存储分类的层次结构。
- 后端实现: 使用 Spring Boot 构建 RESTful API,通过 MyBatis-Plus 进行数据查询。后端 API 将支持根据 parent_id 查询子节点数据,提供给前端进行异步加载。
- 前端实现: 使用 Thymeleaf 模板引擎生成 HTML 页面,并通过 Bootstrap 提供的组件美化页面。通过 JavaScript 实现异步加载功能,当用户点击某个分类节点时,发送请求加载其子分类数据,并动态渲染到页面上。
- 代码示例与配置: 文章中将提供完整的代码示例,包括 Spring Boot 项目配置、MyBatis-Plus 的 Mapper 和 Service 实现,以及前端 HTML、JavaScript 代码,帮助开发者快速理解和实现多层次树结构的异步加载。本篇文章将深入讲解如何使用 Spring Boot3.3 和 MyBatis-Plus 联合实现多层次树结构的异步加载,并提供完整的代码示例。
5,具体案例
本章节将深入讲解如何使用 Spring Boot3.3 和 MyBatis-Plus 联合实现多层次树结构的异步加载,并提供完整的代码示例。运行效果:
5.1,项目结构
我们将构建一个Spring Boot项目,使用MyBatis-Plus进行数据库操作,并结合Thymeleaf模板引擎在前端展示树结构。以下是项目的基本结构:
springboot-tree-async
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com.icoderoad.treeasync
│ │ │ ├── controller
│ │ │ ├── entity
│ │ │ ├── mapper
│ │ │ ├── service
│ │ │ └── serviceImpl
│ │ ├── resources
│ │ │ ├── templates
│ │ │ ├── application.yml
│ └── test
│ └── java
│ └── com.icoderoad.treeasync
└── pom.xml
5.2,项目配置(pom.xml)
首先,我们需要配置pom.xml,包括Spring Boot和MyBatis-Plus的依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.icoderoad</groupId><artifactId>treeasync</artifactId><version>0.0.1-SNAPSHOT</version><name>treeasync</name><description>Demo project for Spring Boot</description><properties><java.version>17</java.version><mybatis-plus-boot-starter.version>3.5.7</mybatis-plus-boot-starter.version><mybatis-spring.version>3.0.3</mybatis-spring.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis-plus-boot-starter.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>${mybatis-spring.version}</version></dependency><!-- 数据库驱动依赖 --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
5.3,配置文件(application.yml)
接下来,我们配置application.yml,指定数据源及MyBatis-Plus的配置。
spring:datasource:url: jdbc:mysql://localhost:3306/tree_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:mapper-locations: classpath:/mapper/*.xmlglobal-config:db-config:id-type: auto
5.4,实体类与Mapper接口
我们使用一个简单的Category实体来表示树结构中的节点:
package com.icoderoad.treeasync.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName("category")
public class Category {@TableId(type = IdType.AUTO)private Long id;private Long parentId;private String name;
}
CategoryMapper接口定义了数据库操作:
package com.icoderoad.treeasync.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.icoderoad.treeasync.entity.Category;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface CategoryMapper extends BaseMapper<Category> {
}
5.5,Service层
在Service层,我们实现了获取树结构节点的逻辑:
package com.icoderoad.treeasync.service;import com.icoderoad.treeasync.entity.Category;
import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;public interface CategoryService extends IService<Category> {List<Category> getChildren(Long parentId);
}package com.icoderoad.treeasync.service.impl;import com.icoderoad.treeasync.entity.Category;
import com.icoderoad.treeasync.mapper.CategoryMapper;
import com.icoderoad.treeasync.service.CategoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {@Overridepublic List<Category> getChildren(Long parentId) {return lambdaQuery().eq(Category::getParentId, parentId).list();}
}
5.6,controller
controller用来处理前端的异步请求:
package com.icoderoad.treeasync.controller;import com.icoderoad.treeasync.entity.Category;
import com.icoderoad.treeasync.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;@GetMapping("/children/{parentId}")public List<Category> getChildren(@PathVariable Long parentId) {return categoryService.getChildren(parentId);}
}
5.7,前端页面与异步加载实现
前端使用Thymeleaf模板结合Bootstrap和JavaScript实现树结构的展示与异步加载:在 src/main/resources/templates 目录下创建 index.html 模板文件。
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>分类树结构</title><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.10.5/font/bootstrap-icons.min.css"><style>.tree-item {cursor: pointer;padding-left: 1rem;}.tree-icon {margin-right: 0.5rem;}</style>
</head>
<body>
<div class="container"><h2 class="my-4">分类树结构</h2><ul id="categoryTree" class="list-group"><!-- 根节点会从服务器加载并插入到这里 --></ul>
</div><script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script>$(document).ready(function () {// 加载根节点loadTreeNodes(0, $('#categoryTree'));// 动态加载节点function loadTreeNodes(parentId, ulElement) {$.ajax({url: '/category/children/' + parentId,method: 'GET',success: function (data) {$.each(data, function (index, category) {const li = $('<li>').addClass('list-group-item tree-item');const icon = $('<i>').addClass('bi bi-chevron-right tree-icon');const span = $('<span>').text(category.name);li.append(icon).append(span).data('id', category.id);ulElement.append(li);// 点击展开或折叠li.on('click', function (e) {e.stopPropagation();const iconElement = $(this).find('.tree-icon');const childrenUl = $(this).find('ul');if (childrenUl.length === 0) {// 加载子节点const newUl = $('<ul>').addClass('list-group ml-3');loadTreeNodes($(this).data('id'), newUl);$(this).append(newUl);iconElement.removeClass('bi-chevron-right').addClass('bi-chevron-down');} else {// 切换展开/折叠childrenUl.toggle();iconElement.toggleClass('bi-chevron-right bi-chevron-down');}});});}});}});
</script>
</body>
</html>
5.8,数据库结构
数据库表category的SQL DDL语句如下:
CREATE TABLE `category` (`id` bigint NOT NULL AUTO_INCREMENT,`parent_id` bigint DEFAULT NULL,`name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
初始化分类表数据:
-- 插入第一层数据(根节点)
INSERT INTO category (parent_id, name) VALUES (0, '电子产品');
INSERT INTO category (parent_id, name) VALUES (0, '家用电器');
INSERT INTO category (parent_id, name) VALUES (0, '时尚服饰');-- 插入第二层数据
INSERT INTO category (parent_id, name) VALUES (1, '手机');
INSERT INTO category (parent_id, name) VALUES (1, '笔记本电脑');
INSERT INTO category (parent_id, name) VALUES (2, '冰箱');
INSERT INTO category (parent_id, name) VALUES (2, '洗衣机');
INSERT INTO category (parent_id, name) VALUES (3, '男装');
INSERT INTO category (parent_id, name) VALUES (3, '女装');-- 插入第三层数据
INSERT INTO category (parent_id, name) VALUES (4, '智能手机');
INSERT INTO category (parent_id, name) VALUES (4, '功能手机');
INSERT INTO category (parent_id, name) VALUES (5, '游戏笔记本');
INSERT INTO category (parent_id, name) VALUES (5, '超极本');
INSERT INTO category (parent_id, name) VALUES (6, '双门冰箱');
INSERT INTO category (parent_id, name) VALUES (6, '单门冰箱');
INSERT INTO category (parent_id, name) VALUES (7, '滚筒洗衣机');
INSERT INTO category (parent_id, name) VALUES (7, '波轮洗衣机');
INSERT INTO category (parent_id, name) VALUES (8, '休闲装');
INSERT INTO category (parent_id, name) VALUES (8, '正装');
INSERT INTO category (parent_id, name) VALUES (9, '连衣裙');
INSERT INTO category (parent_id, name) VALUES (9, '上衣');-- 插入第四层数据
INSERT INTO category (parent_id, name) VALUES (10, '安卓手机');
INSERT INTO category (parent_id, name) VALUES (10, '苹果手机');
INSERT INTO category (parent_id, name) VALUES (13, '变形笔记本');
INSERT INTO category (parent_id, name) VALUES (13, '传统笔记本');
INSERT INTO category (parent_id, name) VALUES (17, '办公室连衣裙');
INSERT INTO category (parent_id, name) VALUES (17, '休闲连衣裙');
通过一个简单的分类树示例展示了如何在前端逐步加载节点,避免一次性加载大量数据带来的性能问题。
相关文章:

Spring Boot 整合MyBatis-Plus 实现多层次树结构的异步加载功能
文章目录 1,前言2,什么是多层次树结构?3,异步加载的意义4,技术选型与实现思路5,具体案例5.1,项目结构5.2,项目配置(pom.xml)5.3,配置文件…...

网络工程师指南:防火墙配置与管理命令大全,零基础入门到精通,收藏这一篇就够了
本指南详细介绍了防火墙的配置与管理命令,涵盖了防火墙的工作原理、常见配置命令、安全策略与访问控制、日志管理与故障排查,并通过实战案例展示了如何有效防御网络攻击。通过学习本指南,网络工程师能够系统掌握防火墙的配置与管理技能&#…...

英特尔终于找到了Raptor Lake处理器崩溃与不稳定问题的根源
技术背景 在过去的几个月里,一些用户报告称他们的第13代和第14代Intel Core“Raptor Lake”处理器遇到了系统崩溃和不稳定的情况。这些问题最初在2024年7月底被英特尔识别出来,并且初步的诊断显示,这些问题与微码有关,该微码使CP…...

Shp2pb:Shapefile转Protocol Buffers的高效工具
Shp2pb是一个实用工具,专门用于将Shapefile(shp)格式转换为Protocol Buffers(protobuf)文件。这对于以更高效、更紧凑的方式处理地理数据特别有用。以下是关于如何安装和使用Shp2pb工具的详细说明,以及一个…...

Elasticsearch使用Easy-Es + RestHighLevelClient实现深度分页跳页
注意!!!博主只在测试环境试了一下,没有发到生产环境跑。因为代码还没写完客户说不用弄了( •̩̩̩̩_•̩̩̩̩ ) 也好,少个功能少点BUG 使用from size的时候发现存在max_result_window10000的限制&…...

基于ASRPRO的语音应答
做这个的起因是为了送女朋友,而且这东西本身很简单,所以在闲暇之余尝试了一下。 这个工程很简单,只通过对ASRPRO进行编程即可。 先看效果。(没有展示所有效果,后续会列出来所有对话触发) 语音助手示例1 语音助手示例2 代码部分使用天文Block编辑,找了一圈好像只…...

3D看车汽车案例,车模一键换皮肤,开关车门,轴距,电池功能
3D 汽车案例 网址: http://car.douchuanwei.com/...

数据结构-4.栈与队列
本篇博客给大家带来的是栈和队列的知识点, 其中包括两道面试OJ题 用队列实现栈 和 用栈实现队列. 文章专栏: Java-数据结构 若有问题 评论区见 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条, 如果分享不成功, 那我就会回你一下,那样你就分享成功啦. 你们的…...

芝士AI写作有什么特色? 大模型支撑,智能改写续写,让写作更轻松
又到了一年的毕业季,大学四年眨眼间匆匆就过去了,毕业,求职,考研,工作,升学,但是在这之前,我们必须要完成论文的写作,这也是每一位大学生都必须要面对~ 芝士AI官网&…...

【计网】从零开始学习http协议 --- http的请求与应答
如果你不能飞,那就跑; 如果跑不动,那就走; 实在走不了,那就爬。 无论做什么,你都要勇往直前。 --- 马丁路德金 --- 从零开始学习http协议 1 什么是http协议2 认识URL3 http的请求和应答3.1 服务端设计…...

记录linux环境下搭建本地MQTT服务器实现mqtt的ssl加密通讯
1、ubuntu安装mosquitto sudo apt-get update//安装服务端 sudo apt-get install mosquitto//安装客户端 sudo apt-get install mosquitto-clients 2、安装openssl 3、mqtts/tls加密传输 mosquitto原生支持了TLS加密,TLS(传输层安全)是SSL&…...

基于python+django+vue的电影数据分析及可视化系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…...

HJ50-四则运算:栈的运用、中缀表达式转后缀表达式并计算结果
文章目录 题目一、分析1.1表达式预处理1.2中缀表达式转后缀1.3 后缀表达式计算结果 二、答案 题目 一、分析 通过利用栈将中缀表达式转换为后缀表达式,在根据后缀表达式计算运算结果。由于包含负数操作数的情况,并且操作数位数不固定为1,因此…...

C++编程:实现简单的高精度时间日志记录小程序
0. 概述 为了检查是否存在系统时间跳变,本文使用C实现了一个简单的高精度时间日志记录小程序。该程序能够每隔指定时间(默认40毫秒)记录一次系统时间到文件中,并具备以下功能: 自定义时间间隔和文件名:通…...

QQ机器人搭建
使用QQ官方机器人Python SDK和三方框架搭建QQ群聊机器人 文章目录 使用QQ官方机器人Python SDK和三方框架搭建QQ群聊机器人前言编写机器人代码机器人监听群聊进行文字回复机器人监听群聊进行图片回复机器人监听群聊进行文件发送机器人监听群聊进行视频发送机器人监听群聊进行语…...

flink设置保存点和恢复保存点
增加了hdfs package com.qyt;import org.apache.flink.api.java.functions.KeySelector; import org.apache.flink.api.java.tuple.Tuple2;import org.apache.flink.runtime.state.storage.FileSystemCheckpointStorage;import org.apache.flink.streaming.api.datastream.Dat…...

使用python获取百度一下,热搜TOP数据详情
一、查找对应链接 # 警告:以下代码仅供学习和交流使用,严禁用于任何违法活动。 # 本代码旨在帮助理解和学习编程概念,不得用于侵犯他人权益或违反法律法规的行为。 1、打开百度页面 百度一下,你就知道 2、点击F12 或 右键鼠标…...

Go conc库学习与使用
文章目录 主要功能和特点conc 的安装典型使用场景示例代码并行执行多个 Goroutines错误处理限制并发 Goroutines 数量使用 context.Context 进行任务控制 常见问题1. **任务中发生 panic**原因:解决方法: 2. **conc.Group 重复调用 Wait()**原因…...

大模型prompt先关
对于未出现的任务,prompt编写技巧: 1、假设你是资深的摘要生成专家,根据提供的内容,总结对应的摘要信息。请生成一个指令,指令中带有一个使用例子。直接提供给大型模型以执行此任务。 2、基于大模型提供的内容再进行二…...

尚品汇-自动化部署-Jenkins的安装与环境配置(五十六)
目录: 自动化持续集成 (1)环境准备 (2)初始化 Jenkins 插件和管理员用户 (3)工作流程 (4)配置 Jenkins 构建工具 自动化持续集成 互联网软件的开发和发布…...

【尚跑】2024铜川红色照金半程马拉松赛,大爬坡152安全完赛
1、赛事背景 2024年9月22日8点,2024铜川红色照金半程马拉松赛于照金1933广场鸣枪起跑! 起跑仪式上,6000位选手们合唱《歌唱祖国》,熟悉的旋律响彻陕甘边革命根据地照金纪念馆前,激昂的歌声凝聚心中不变的热爱。随着国…...

WPS中让两列数据合并的方法
有这样一个需求,就是把A列数据和B列数据进行合并(空单元格略过)具体实现效果如图下: 该如何操作呢? 首先在新的一列第一个单元格中输入公式"A1&B1" 然后回车,就出现了两列单元格数据合并的效…...

使用yum为centos系统安装软件以及使用(包含阿里云yum源配置)
centos系统配置阿里云yum源 因为centos7官方停止维护,自带yum源用不了了,所以可以更换成阿里云yum源 方法: 使用root权限执行以下语句 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo CentOS…...

《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析
目录 一、透视变换 1、什么是透视变换 2、操作步骤 1)选择透视变换的源图像和目标图像 2)确定透视变换所需的关键点 3)计算透视变换的变换矩阵 4)对源图像进行透视变换 5)对变换后的图像进行插值处理 二、轮廓检测…...

Linux 线程互斥
前言 对于初学线程的伙伴来讲,多线程并发访问导致的数据不一致问题,总是让人陷入怀疑,很多人只是给你说加锁!但没有人告诉你为什么?本篇博客将详解! 目录 前言 一、线程互斥 • 为什么票会出现负数的情…...

【Redis 源码】6AOF持久化
1 AOF功能说明 aof.c 文件是 Redis 中负责 AOF(Append-Only File)持久化的核心文件。AOF 持久化通过记录服务器接收到的每个写命令来实现数据的持久化。这样,在 Redis 重启时,可以通过重放这些命令来恢复数据。 2 AOF相关配置 a…...

6.MySQL基本查询
目录 表的增删查改Insert(插入)插入替换插入替换2 Retrieve(查找)SELECT 列全列查找指定列查询查询字段为表达式为查询结果指定别名结果去重 WHERE 条件order by子句筛选分页结果 Update(更新)delete&#…...

Linux字符设备驱动开发
Linux 字符设备驱动开发是内核模块开发中的一个重要部分,主要用于处理字节流数据设备(如串口、键盘、鼠标等)。字符设备驱动的核心任务是定义如何与用户空间程序交互,通常通过一组文件操作函数进行。这些函数会映射到 open、read、…...

HTML5+JavaScript绘制闪烁的网格错觉
HTML5JavaScript绘制闪烁的网格错觉 闪烁的网格错觉(scintillating grid illusion)是一种视觉错觉,通过简单的黑白方格网格和少量的精心设计,能够使人眼前出现动态变化的效果。 闪烁的栅格错觉,是一种经典的视觉错觉…...

每日OJ题_牛客_拼三角_枚举/DFS_C++_Java
目录 牛客_拼三角_枚举/DFS 题目解析 C代码1 C代码2 Java代码 牛客_拼三角_枚举/DFS 拼三角_枚举/DFS 题目解析 简单枚举,不过有很多种枚举方法,这里直接用简单粗暴的枚举方式。 C代码1 #include <iostream> #include <algorithm> …...