幂等性(防重复提交)
yudao-spring-boot-starter-protection (opens new window) 技术组件,由它的 idempotent (opens new window) 包,提供声明式的幂等特性,可防止重复请求。例如说,用户快速的双击了某个按钮,前端没有禁用该按钮,导致发送了两次重复的请求。
12345678// UserController.java@Idempotent(timeout = 10, timeUnit = TimeUnit.SECONDS, message = "正在添加用户中,请勿重复提交")@PostMapping("/user/create")public String createUser(User user){ userService.createUser(user); return "添加成功";}
#1. 实现原理它的实现原理非常简单,针对相同参数的方法,一段时间内,有且仅能执行一次。执行流程如下:
① 在方法执行前,根据参数对应的 Key ...
分布式锁
yudao-spring-boot-starter-protection (opens new window) 技术组件,使用 Redis 实现分布式锁的功能,它有 2 种使用方式:
编程式锁:基于 Redisson (opens new window)框架提供的各种 (opens new window)分布式锁
声明式锁:基于 Lock4j (opens new window)框架的 @Lock4j 注解
Redis 分布式锁的实现原理?
参见 《Redis 实现原理与源码解析系列》 (opens new window)文章。
#1. 编程式锁1234<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId></dependency>
#1.1 Redisson 配置无需配置。因为在 Redis 缓存 中,进行了 Spring Data Redis + Red ...
单元测试
项目使用 Junit5 + Mockito 实现单元测试,提升代码质量、重复测试效率、部署可靠性等。
截止目前,项目已经有 500+ 测试用例。
内容推荐
如果你想系统学习单元测试,可以阅读《有效的单元测试》 (opens new window)这本书,非常适合 Java 工程师。
如果只是想学习 Spring Boot Test 的话,可以阅读 《芋道 Spring Boot 单元测试 Test 入门 》 (opens new window)文章。
#1.测试组件yudao-spring-boot-starter-test (opens new window)是项目提供的测试组件,用于单元测试、集成测试等等。
#1.1 快速测试的基类测试组件提供了 4 种单元测试的基类,通过继承它们,可以快速的构建单元测试的环境。
基类
作用
BaseMockitoUnitTest(opens new window)
纯 Mockito 的单元测试
BaseDbUnitTest(opens new window)
使用内嵌的 H2 数据库的单元测试
BaseRedisUnitTe ...
工具类 Util
本小节,介绍项目中使用到的工具类,避免大家重复造轮子。
#1. Hutool项目使用 Hutool (opens new window)作为主工具库。Hutool 是国产的一个 Java 工具包,它可以帮助我们简化每一行代码,减少每一个方法,让 Java 语言也可以“甜甜的”。
yudao-common (opens new window)模块的 util (opens new window)包作为辅工具库,以 Utils 结尾,补充 Hutool 缺少的工具能力。
友情提示:常用的工具类,使用 ⭐ 标记,需要的时候可以找找有没对应的工具方法。
作用
Hutool
芋道 Utils
数组工具
ArrayUtil(opens new window)
ArrayUtils(opens new window)
⭐ 集合工具
CollUtil(opens new window)
CollectionUtils(opens new window)
⭐ Map 工具
MapUtil(opens new window)
MapUtils(opens new window)
S ...
配置管理
在 [基础设施 -> 配置管理] 菜单,可以查看和管理配置,适合业务上需要动态的管理某个配置。
例如说:创建用户时,需要配置用户的默认密码,这个密码是不会变的,但是有时候需要修改这个默认密码,这个时候就可以通过配置管理来修改。
对应的后端代码是 yudao-module-infra 的 config (opens new window)业务模块。
#1. 配置的表结构infra_config 的表结构如下:
12345678910111213141516CREATE TABLE `infra_config` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键', `group` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '参数分组', `type` tinyint NOT NULL COMMENT '参数类型', `name` varchar(100) ...
异步任务
yudao-spring-boot-starter-job (opens new window) 技术组件,除了提供定时任务的功能,还提供了 Async 异步任务的能力。系统使用异步任务,提升执行效率。例如说:
操作日志模块 (opens new window),异步记录【操作日志】
访问日志模块 (opens new window),异步记录【访问日志】
友情提示:
如果你未学习过 Spring 异步任务,可以后续阅读 《芋道 Spring Boot 异步任务入门 》 (opens new window)文章。
#1. Async 配置在 YudaoAsyncAutoConfiguration (opens new window)配置类,设置使用 TransmittableThreadLocal (opens new window),解决异步执行时上下文传递的问题。如下图所示:
友情提示:
项目使用到 ThreadLocal 的地方,建议都使用 TransmittableThreadLocal 进行替换。
#2. 引入依赖以访问日志模块为例,讲解它如何使用异步任务,实现异步记录 ...
本地缓存
重要说明:
① 由于大家普遍反馈,“本地缓存”学习成本太高,一般 Redis 缓存足够满足大多数场景的性能要求,所以基本使用 Spring Cache + Redis 所替代。
也因此,本章节更多的,是讲解如何在项目中使用本地缓存。如果你不需要本地缓存,可以忽略本章节。
② 项目中还保留了部分地方使用本地缓存,例如说:短信客户端、文件客户端、敏感词等。主要原因是,它们是“有状态”的 Java 对象,无法缓存到 Redis 中。
系统使用本地缓存,提升公用逻辑的执行性能。 例如说:
租户模块 (opens new window)缓存租户信息,每次 RESTful API 校验租户是否禁用、过期时,无需读库。
部门模块 (opens new window)缓存部门信息,每次数据权限校验时,无需读库。
权限模块 (opens new window)缓存权限信息,每次功能权限校验时,无需读库。
#1. 实现原理本地缓存的实现,一共有两步,如下图所示:
项目启动时,初始化缓存:从数据库中读取数据,写入到本地缓存(例如说一个 Map 对象)
数据变化时,实时刷新缓存:(例如说通过管理后台修 ...
Redis 缓存
yudao-spring-boot-starter-redis (opens new window) 技术组件,使用 Redis 实现缓存的功能,它有 2 种使用方式:
编程式缓存:基于 Spring Data Redis 框架的 RedisTemplate 操作模板
声明式缓存:基于 Spring Cache 框架的 @Cacheable 等等注解
#1. 编程式缓存友情提示:
如果你未学习过 Spring Data Redis 框架,可以后续阅读 《芋道 Spring Boot Redis 入门》 (opens new window)文章。
1234<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId></dependency>
由于 Redisson 提供了分布式锁、队列、限流等特性,所以使用它作为 Spring Data Redis 的客户端。
#1 ...
多数据源(读写分离)
yudao-spring-boot-starter-mybatis (opens new window) 技术组件,除了提供 MyBatis 数据库操作,还提供了如下 2 种功能:
数据连接池:基于 Alibaba Druid (opens new window)实现,额外提供监控的能力。
多数据源(读写分离):基于 Dynamic Datasource (opens new window)实现,支持 Druid 连接池,可集成 Seata (opens new window)实现分布式事务。
#1. 数据连接池友情提示:
如果你未学习过 Druid 数据库连接池,可以后续阅读 《芋道 Spring Boot 数据库连接池入门》 (opens new window)文章。
1234<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId></dependency>
#1 ...
MyBatis 联表&分页查询
本文,分享 MyBatis 各种常用操作,不限于链表查询、分页查询等等。
#1. 分页查询在 《MyBatis 数据库》 的「3.4 selectPage」小节,我们使用 MyBatis Plus 实现了分页查询。除了这种方式,我们也可以使用 XML 实现分页查询。
这里,以查询 system_users 表为例,讲解如何使用 XML 实现分页查询。
#1.1 方案一:MyBatis XML这个是 MyBatis 内置的使用方式,步骤如下:
① 创建 AdminUserMapper.xml 文件,编写两个 SQL 查询语句:
1234567891011121314151617181920212223242526272829303132333435363738<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd ...
