「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

06-01 1509阅读

🚀 作者主页: 有来技术

🔥 开源项目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template

🌺 仓库主页: GitCode︱ Gitee ︱ Github

💖 欢迎点赞 👍 收藏 ⭐评论 📝 如有错误敬请纠正!

目录

  • 前言
  • 项目介绍
  • 启动项目
    • 克隆代码
    • 配置环境
    • 启动项目
    • 测试启动
    • 切换本地环境
      • 安装 Docker
      • 安装中间件
      • 修改本地配置
        • 配置 MySQL
        • 配置 Redis
        • 配置 MinIO (可选)
        • 配置 Xxl-Job (可选)
        • 操作指南
          • 修改包名
          • 代码生成
            • 创建数据表
            • 启动项目
            • 生成代码
            • 集成代码
            • 功能测试
            • 接口文档
              • 登录接口
              • 设置全局 Token
              • 接口测试
              • 定时任务
                • 修改配置
                • 添加执行器
                • 添加任务
                • 定时任务测试
                • 文件上传
                  • 创建存储桶
                  • 修改应用配置
                  • 文件上传测试
                  • 项目功能
                    • 数据权限
                      • 实现原理
                      • 使用示例
                      • 防重提交
                        • 使用防重提交
                        • 测试防重提交
                        • IP 限流
                          • 配置 QPS
                          • 限流测试
                          • 项目扩展
                            • 多数据源支持
                              • 添加依赖
                              • 配置多数据源
                              • 多数据源测试
                              • 扩展登录方式
                                • 自定义认证 Token
                                • 自定义认证 Provider
                                • Spring Security 配置
                                • 发送验证码
                                • 登录接口
                                • 接口测试
                                • 项目部署
                                  • 安装虚拟机
                                  • 安装 Docker
                                  • 安装中间件
                                    • 上传脚本
                                    • 启动服务
                                    • 验证安装
                                    • 部署应用
                                      • 安装插件
                                      • 配置服务器
                                      • 部署配置
                                      • 一键部署
                                      • 结语

                                        前言

                                        本文档旨在为开发者提供全面的 youlai-boot 项目使用指南,涵盖项目介绍、快速启动、环境配置、功能操作和扩展实现等多方面内容。youlai-boot 是一款基于 Java 17 和 Spring Boot 3 的企业级权限管理系统,集成了多种主流技术栈,适用于复杂的企业业务场景。通过本手册,开发者可以快速上手项目,并深入掌握各模块的实现细节和最佳实践。

                                        项目介绍

                                        youlai-boot 是一个企业级 RBAC 权限管理系统,采用 Java 17、Spring Boot 3、Spring Security 6、MyBatis-Plus、Redis 和 XXL-Job 等主流后端技术栈构建,作为 vue3-element-admin(Web 端)和 vue-uniapp-template(移动端)的后端服务,支持用户、角色、权限、部门、字典、配置等多种功能,满足企业级权限管理需求。

                                        项目特色

                                        • 完善的权限管理:支持精细化的用户、角色、菜单和数据权限控制。
                                        • 高效的开发工具:内置前后端代码生成器,快速搭建业务模块。
                                        • 实时通信支持:基于 WebSocket 实现在线用户统计与消息推送。
                                        • 系统安全机制:提供防重提交、分布式锁等保障数据安全的能力。
                                        • 灵活的定时任务:集成 XXL-Job,支持复杂的任务调度场景。

                                          启动项目

                                          以下是快速启动 youlai-boot 项目 的完整步骤,从克隆项目到运行服务,帮助您快速上手。

                                          克隆代码

                                          打开 IntelliJ IDEA,依次点击:File → New → Project from Version Control

                                          在弹出的窗口中输入项目地址:https://gitee.com/youlaiorg/youlai-boot.git ,然后点击 Clone。

                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                          稍等片刻,等待项目加载完成后,项目结构将如下所示:

                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                          配置环境

                                          启动项目前,需要确保开发环境满足以下条件:已安装并配置 JDK 和 Maven。

                                          配置 JDK

                                          打开项目结构配置面板 File → Project Structure(快捷键 Ctrl + Alt + Shift + S)打开项目结构配置面板,确保 SDK 设置为安装的 JDK 17。

                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                          配置 Maven

                                          打开 IDE 设置面板:File → Settings(快捷键 Ctrl + Alt + S),在 Build, Execution, Deployment → Build Tools → Maven 中,配置 Maven 使用本地安装的版本。

                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                          验证 Maven 配置:打开 IDEA 终端,执行以下命令,确保 Maven 使用的是 JDK 17。

                                          mvn -v
                                          

                                          正确输出示例:

                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                          启动项目

                                          打开项目的主启动类 YouLaiBootApplication。右键点击 main 方法,选择 Debug YouLaiBootApplication.main() 启动项目。

                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                          测试启动

                                          项目启动成功后,可通过访问接口文档验证服务是否正常运行:

                                          访问 Knife4j 接口文档:http://localhost:8989/doc.html

                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                          访问 Swagger 接口文档: http://localhost:8989/swagger-ui.html

                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                          切换本地环境

                                          安装 Docker

                                          项目中的 MySQL、Redis、MinIO 等中间件默认使用线上环境,一般情况下禁止增删改操作。如果需要更好地体验系统,建议在本地搭建 MySQL、Redis 等中间件,并切换到本地环境。

                                          手动搭建 MySQL、Redis 等中间件及初始化数据库脚本可能较为耗时。推荐使用 Docker 和 Docker Compose,通过项目提供的 docker-compose 脚本一键搭建 MySQL、Redis 并初始化数据库。

                                          首先,确保已安装 Docker,安装教程如下:

                                          • Windows 安装 Docker 和 Docker Compose
                                          • Linux (CentOS) 安装 Docker 和 Docker Compose

                                            安装中间件

                                            安装好 Docker 和 Docker Compose 后,查看项目根目录中的 docker-compose.yml 脚本内容。

                                            进入项目目录,运行docker/run.md 完成 MySQL、Redis、MinIO 和 XXL-Job 的安装与配置。

                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                            运行后,打开 Docker Desktop,确认中间件已成功安装:

                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                            使用数据库可视化工具(如 Navicat),可以看到 youlai-boot 数据库已成功创建。这是因为 docker-compose.yml 指定了初始化 SQL 脚本的路径:

                                            - ../sql/mysql8:/docker-entrypoint-initdb.d
                                            

                                            以下是中间件的默认配置。如果端口号与本地应用冲突,请修改 docker-compose.yml 中对应的端口设置:

                                            中间件端口用户名密码控制台
                                            MySQL3306root123456/
                                            Redis6379/123456/
                                            MinIO9000minioadminminioadminhttp://lcalhost:9090
                                            xxl-job-admin8080adminadminhttp://lcalhost:8080

                                            修改本地配置

                                            配置 MySQL

                                            在 application-dev.yml 文件中,将 MySQL 的连接信息替换为本地环境配置,例如数据库地址、用户名和密码。默认端口是 3306,默认用户名和密码是 root/123456,请根据实际情况修改。

                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)


                                            配置 Redis

                                            在 application-dev.yml 文件中,将 Redis 的地址和密码替换为本地环境配置。如果本地 Redis 没有设置密码,直接删除或注释掉 password 配置,避免连接失败。

                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                            配置 MinIO (可选)

                                            如果项目中使用了文件上传服务,请在 application-dev.yml 文件中修改 MinIO 的连接信息为本地环境配置,包括地址、用户名和密码。例如,默认端口为 9000,默认用户名和密码为 minioadmin/minioadmin,请根据实际情况调整。

                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)


                                            配置 Xxl-Job (可选)

                                            如果项目中需要使用 XXL-Job,请在 application-dev.yml 文件中开启配置:

                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                            操作指南

                                            修改包名

                                            默认包名为 com.youlai.boot,如需修改为 com.wuhui.boot,需要做以下改动:

                                            • 修改启动类名称

                                              将启动类从 YoulaiBootApplication 改为 WuhuiBootApplication。

                                            • 修改应用名称

                                              在 application.yml 中将 spring.application.name 的值从 youlai-boot 修改为 wuhui-boot;在 pom.xml 中将 值从 com.youlai 改为 com.wuhui

                                            • 修改接口文档包路径,否则接口文档不显示接口描述

                                              application-*.yml 修改接口文档扫描包路径

                                              「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                            • 代码生成的项目名称

                                              codegen.yml 里修改后端项目名称 codegen.backendAppName 替换 youlai-boot 为 wuhui-boot

                                              代码生成

                                              这里以会员管理模块为例,来讲解如何生成前后端代码以及在项目中新增一个模块时自动生成菜单路由。

                                              创建数据表

                                              在数据库中执行以下 SQL 脚本以创建 会员信息表:

                                              CREATE TABLE `member` (
                                                      `id` int NOT NULL AUTO_INCREMENT COMMENT '会员编号',
                                                      `name` varchar(50)  DEFAULT NULL COMMENT '会员姓名',
                                                      `mobile` varchar(20) DEFAULT NULL COMMENT '会员手机号',
                                                      `gender` tinyint DEFAULT NULL COMMENT '性别',
                                                      `age` int DEFAULT NULL COMMENT '会员年龄',
                                                      `create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间',
                                                      `update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',
                                                      `is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除(1:已删除;0:未删除)',
                                              PRIMARY KEY (`id`)
                                              ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='会员信息表';
                                              

                                              启动项目

                                              • 启动后端项目:youlai-boot。

                                              • 启动前端项目:vue3-element-admin。

                                                • 在启动前端项目之前,需要修改 .env.development 文件中的接口地址为本地开发环境的后端服务地址。

                                                  生成代码

                                                  进入前端页面的代码生成器 在前端项目中找到 代码生成 菜单,选择 member 表,点击生成代码。

                                                  「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                  填写基础配置信息

                                                  • 业务名:会员信息
                                                  • 主包名:com.youlai.boot
                                                  • 模块名:member
                                                  • 实体名:Member
                                                  • 如果需要自动生成会员模块的菜单和按钮权限,请选择对应的上级菜单。

                                                    「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                    配置字段信息

                                                    • 配置筛选、列表和表单的字段。
                                                    • 可选择字段类型,例如文本框、下拉框等。
                                                    • 如果字段需要字典支持,可以配置字典信息。

                                                      「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                      在线预览和下载代码

                                                      • 配置完成后,可以在线预览生成的前后端代码。
                                                      • 下载生成的代码压缩包到本地。

                                                        「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                        集成代码

                                                        下载代码,解压得到前后端代码

                                                        「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                        后端代码集成

                                                        • 解压下载的代码包,将后端代码复制到 youlai-boot 项目对应的目录中。
                                                        • 确保项目重新加载新代码,并进行必要的构建和启动操作。

                                                          「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                          前端代码集成

                                                          • 同样将前端代码复制到前端项目中对应的目录。

                                                            功能测试

                                                            进入 角色管理 模块,为当前用户的角色分配新生成的 会员管理 菜单权限。

                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                            勾选菜单中的 会员信息 选项。完成权限分配后,刷新页面。如果左侧菜单栏未显示 会员信息 菜单,请尝试重新登录。

                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                            进入 会员管理 模块,新增会员信息。

                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                            新增成功后,在会员列表中可以查看到刚添加的会员数据。

                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                            接口文档

                                                            接口文档的访问路径为 应用地址/doc.html。在本地环境中,youai-boot 项目的接口文档地址为:http://localhost:8989/doc.html。

                                                            登录接口

                                                            由于大部分接口需要访问令牌(Token)进行身份认证,登录接口是使用接口文档的基础。通过登录接口获取成功返回的访问令牌后,可以将其设置到接口文档的全局变量中,方便后续接口的测试。

                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                            设置全局 Token

                                                            将登录接口返回的访问令牌设置为全局变量,步骤如下:在接口文档右上角找到全局变量配置选项,输入令牌值后保存。

                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                            接口测试

                                                            设置好全局访问令牌后,打开其他接口时会发现令牌已自动填充,无需手动为每个接口单独设置令牌,极大简化了测试流程。

                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                            定时任务

                                                            在之前的 切换本地环境 和 安装中间件 部分中,我们通过 Docker Compose 一键安装了 XXL-JOB。本节主要介绍如何配置和使用 XXL-JOB。如果您尚未安装 XXL-JOB,或者需要从零开始了解安装过程,请参考这篇文章:Spring Boot 3 整合 XXL-JOB 实现分布式定时任务调度。

                                                            XXL-JOB 包含两个主要角色:调度器 和 执行器。调度器是服务端,用于管理任务调度;执行器是应用端,用于执行任务的具体逻辑。

                                                            • XXL-JOB 控制台地址: http://localhost:8080/xxl-job-admin
                                                            • 用户名/密码: admin/123456

                                                              「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                              修改配置

                                                              XXL-JOB 的定时任务默认是关闭的。请根据下图修改配置:

                                                              1. 将 xxl.job.enabled 设置为 true。
                                                              2. 调整调度中心地址为实际安装地址,其它配置可保持默认。

                                                              「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                              添加执行器

                                                              在 application-dev.yml 中,执行器的应用名称 (xxl.job.executor.appname) 默认配置为:

                                                              xxl-job-executor-${spring.application.name},其中 ${spring.application.name} 会解析为当前应用名称。例如,在 youlai-boot 项目中,appname 将解析为 xxl-job-executor-youlai-boot。

                                                              操作步骤:

                                                              1. 在 XXL-JOB 控制台中,添加执行器,appname 配置为 xxl-job-executor-youlai-boot。

                                                                「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                              2. 因为采用的是自动注册方式,重启 youlai-boot 应用后,再刷新执行器列表,可以看到机器已成功注册。「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                              添加任务

                                                              在 youlai-boot 应用中,添加任务执行逻辑。以下是示例代码:

                                                              package com.youlai.boot.system.handler;
                                                              /**
                                                               * xxl-job 测试示例(Bean模式)
                                                               */
                                                              @Component
                                                              @Slf4j
                                                              public class XxlJobSampleHandler {
                                                                  @XxlJob("demoJobHandler")
                                                                  public void demoJobHandler() {
                                                                      log.info("XXL-JOB, Hello World.");
                                                                  }
                                                                  
                                                              }
                                                              

                                                              配置任务:

                                                              1. 在 XXL-JOB 控制台中,进入“任务管理”页面,选择新增任务。
                                                              2. 选择刚刚创建的 youlai-boot 应用对应的执行器。
                                                              3. 配置 Cron 表达式来设定任务执行时间和频率。
                                                              4. 设置任务模式为 Bean 模式,调用 Spring 容器中的 Bean,其中 Bean 名称为 @XxlJob("demoJobHandler") 中定义的 demoJobHandler。

                                                              「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                              定时任务测试

                                                              任务创建完成后,可以在“操作”列中选择启动进行测试。

                                                              注意事项:

                                                              调度器和执行器需要在网络上互通。如果调度器部署在云服务器上,而执行器运行在本地,则无法正常运行。建议将应用也部署到云服务器。

                                                              「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                              启动任务后,可以查看应用控制台日志,验证任务是否正确执行。

                                                              「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                              文件上传

                                                              youlai-boot 目前支持 MinIO、阿里云以及本地文件存储方式。以下以常用的 MinIO 为例,演示如何进行文件上传。

                                                              创建存储桶

                                                              在上一章节 切换本地环境 和 安装中间件 中,我们已通过 Docker Compose 快速安装了 MinIO。如果尚未安装,可参考:Docker 部署 MinIO 对象存储系统。

                                                              • MinIO 控制台地址:http://localhost:9090/
                                                              • 默认用户名/密码:minioadmin/minioadmin

                                                                登录控制台,访问 http://localhost:9090/buckets/add-bucket 页面,创建一个名为 youlai 的存储桶。

                                                                「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                设置存储桶的访问权限(Access Policy)为 public。

                                                                「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                修改应用配置

                                                                打开项目的 application-dev.yml 文件,配置文件存储相关参数:

                                                                • 指定 oss.type 为 minio
                                                                • 设置服务地址为 http://localhost:9000
                                                                • 使用默认访问凭据:用户名 minioadmin,访问密钥 minioadmin
                                                                • 存储桶名称为 youlai(前文创建的存储桶)

                                                                  配置示例:

                                                                  「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                  文件上传测试

                                                                  启动项目后,访问接口文档 http://localhost:8989/doc.html。选择文件上传接口,上传文件后会返回对应的文件 URL。将返回的 URL 粘贴到浏览器中,即可预览上传的文件。

                                                                  「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                  项目功能

                                                                  数据权限

                                                                  为了实现多租户和权限控制,我们可以通过 MyBatis-Plus 自定义数据权限注解和处理器,动态过滤数据。以下是实现方式:

                                                                  实现原理

                                                                  通过自定义拦截器实现 DataPermissionHandler 接口。在 youlai-boot 中,MyDataPermissionHandler 是其具体实现类,用于在 SQL 执行前动态拼接权限过滤条件。

                                                                  处理逻辑如下:

                                                                  • 获取用户权限范围(如部门或用户)。
                                                                  • 动态生成筛选条件:如部门及以下的 dept_id IN (...) 或个人创建的 create_by = ...。
                                                                  • 将条件追加到原始 SQL 的 WHERE 子句。

                                                                    使用示例

                                                                    在数据持久层的方法中,如果需要实现数据权限控制,可以直接在方法上添加 @DataPermission 注解。

                                                                    UserMapper.java

                                                                    @Mapper
                                                                    public interface UserMapper {
                                                                        @DataPermission(
                                                                            deptAlias = "u", // 部门字段的表别名,用于标记 SQL 中部门字段的来源表
                                                                            deptIdColumnName = "dept_id", // 部门字段的列名,默认为 dept_id
                                                                            userAlias = "u", // 用户字段的表别名,用于标记 SQL 中用户字段的来源表
                                                                            userIdColumnName = "create_by" // 用户字段的列名,默认为 create_by
                                                                        )
                                                                        Page getUserPage(Page page, UserPageQuery queryParams);
                                                                    }
                                                                    

                                                                    UserMapper.xml

                                                                        SELECT
                                                                            u.id,
                                                                            u.username,
                                                                            u.nickname,
                                                                            u.dept_id
                                                                        FROM
                                                                            sys_user u
                                                                        WHERE
                                                                            u.is_deleted = 0
                                                                    
                                                                    

                                                                    动态 SQL 示例:

                                                                    • 权限范围:部门及以下

                                                                      SELECT u.id, u.username, u.nickname, u.dept_id 
                                                                      FROM sys_user u 
                                                                      WHERE u.is_deleted = 0 
                                                                        AND u.dept_id IN (SELECT id FROM sys_dept WHERE id = 3 OR FIND_IN_SET(3, tree_path));
                                                                      

                                                                      其中AND u.dept_id IN (SELECT id FROM sys_dept WHERE id = 3 OR FIND_IN_SET(3, tree_path))是 MyDataPermissionHandler 根据用户权限为“部门及以下”动态追加的筛选条件。

                                                                    • 权限范围:本人创建

                                                                      SELECT u.id, u.username, u.nickname, u.dept_id 
                                                                      FROM sys_user u 
                                                                      WHERE u.is_deleted = 0 
                                                                        AND u.create_by = 2;
                                                                      

                                                                      其中:AND u.create_by = 2是 MyDataPermissionHandler 根据用户权限为“本人创建”动态追加的筛选条件。

                                                                      防重提交

                                                                      为防止用户在短时间内多次提交相同请求,系统提供了防重复提交功能。通过简单的注解配置,即可实现此功能。

                                                                      使用防重提交

                                                                      在需要防重复提交的接口上添加 @RepeatSubmit 注解即可。通过注解参数 expire,可以灵活控制重复提交的时间间隔(单位:秒)。如果不设置,默认时间为 5 秒。

                                                                      示例:

                                                                      @Operation(summary = "新增用户")
                                                                      @PostMapping
                                                                      @RepeatSubmit(expire = 3) // 3 秒内禁止重复提交
                                                                      public Result saveUser(
                                                                          @RequestBody @Valid UserForm userForm
                                                                      ) {
                                                                          // TODO 新增用户逻辑
                                                                          return Result.success();
                                                                      }
                                                                      

                                                                      测试防重提交

                                                                      模拟短时间内的多次请求来验证防重复提交效果。例如,频繁调用新增用户接口。

                                                                      以下是测试请求的效果演示:

                                                                      通过简单配置,即可有效防止重复提交,确保接口的安全性和稳定性。

                                                                      IP 限流

                                                                      为防止接口被恶意刷取,系统内置了 IP 限流机制。当同一 IP 在单位时间内的请求次数超过限制时,系统将对该 IP 进行访问限制。

                                                                      配置 QPS

                                                                      可通过访问管理后台的 系统管理 → 系统配置 菜单设置 QPS 阈值(单位时间最大请求数)。

                                                                      • 若未配置或禁用该选项,则表示关闭 IP 限流功能。

                                                                        「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                        限流测试

                                                                        以下为模拟测试:20 个线程同时发起请求,当 QPS 配置为 10 时,部分请求将因限流而失败。

                                                                        「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                        部分失败的请求如下所示:

                                                                        「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                        项目扩展

                                                                        多数据源支持

                                                                        随着业务的复杂性增加,单一数据源可能无法满足需求,例如读写分离、多租户独立数据库或独立 Schema 模式等。本节介绍如何基于 youlai-boot 使用 dynamic-datasource 轻松实现多数据源支持。详细内容请参考:Spring Boot3 多数据源。https://youlai.blog.csdn.net/article/details/134888348)

                                                                        添加依赖

                                                                        在 pom.xml 中添加如下依赖:

                                                                            com.baomidou
                                                                            dynamic-datasource-spring-boot3-starter
                                                                            4.3.1
                                                                        
                                                                        

                                                                        配置多数据源

                                                                        修改 application-dev.yml 文件,配置主库和从库的数据源:

                                                                        spring:
                                                                          datasource:
                                                                            dynamic:
                                                                              primary: master # 设置默认数据源
                                                                              strict: false # 数据源找不到时是否抛出异常
                                                                              datasource:
                                                                                master: # 主库
                                                                                  type: com.alibaba.druid.pool.DruidDataSource
                                                                                  url: jdbc:mysql://localhost:3306/youlai_boot?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=true
                                                                                  username: root
                                                                                  password: 123456
                                                                                slave: # 从库
                                                                                  type: com.alibaba.druid.pool.DruidDataSource
                                                                                  url: jdbc:mysql://localhost:3306/youlai_boot_salve?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=true
                                                                                  username: root
                                                                                  password: 123456
                                                                        

                                                                        多数据源测试

                                                                        示例代码:

                                                                        • Mapper 层:通过注解 @DS 指定使用的数据源。
                                                                          /**
                                                                           * 主库查询
                                                                           */
                                                                          @DS("master")
                                                                          @Select("select * from sys_user where id = #{userId}")
                                                                          SysUser getUserFromMaster(Long userId);
                                                                          /**
                                                                           * 从库查询
                                                                           */
                                                                          @DS("slave")
                                                                          @Select("select * from sys_user where id = #{userId}")
                                                                          SysUser getUserFromSlave(Long userId);
                                                                          
                                                                          • 单元测试类:
                                                                            @SpringBootTest
                                                                            @Slf4j
                                                                            class SysUserMapperTest {
                                                                                @Autowired
                                                                                private SysUserMapper userMapper;
                                                                                private final Long userId = 1L;
                                                                                @Test
                                                                                void testSwitchDataSourceByAnnotation() {
                                                                                    SysUser masterUser = userMapper.getUserFromMaster(userId);
                                                                                    log.info("用户ID:{} 主库姓名:{}", userId, masterUser.getNickname());
                                                                                    SysUser slaveUser = userMapper.getUserFromSlave(userId);
                                                                                    log.info("用户ID:{} 从库姓名:{}", userId, slaveUser.getNickname());
                                                                                }
                                                                            }
                                                                            

                                                                            测试结果如下图所示:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            扩展登录方式

                                                                            以下将以短信验证码登录这个常见场景为例,详细说明如何扩展 Spring Security 的认证机制。

                                                                            自定义认证 Token

                                                                            SmsAuthenticationToken 继承自 AbstractAuthenticationToken,通过策略模式由 AuthenticationManager 根据该 token 类型匹配相应的 Provider 进行认证,其中 Provider 负责具体的验证逻辑。

                                                                            /**
                                                                             * 短信验证码认证 Token
                                                                             *
                                                                             * @author youlai
                                                                             */
                                                                            public class SmsAuthenticationToken extends AbstractAuthenticationToken {
                                                                                @Serial
                                                                                private static final long serialVersionUID = 621L;
                                                                                /**
                                                                                 * 认证信息 (手机号)
                                                                                 */
                                                                                private final Object principal;
                                                                                /**
                                                                                 * 凭证信息 (短信验证码)
                                                                                 */
                                                                                private final Object credentials;
                                                                                /**
                                                                                 * 短信验证码认证 Token (未认证)
                                                                                 *
                                                                                 * @param principal 微信用户信息
                                                                                 */
                                                                                public SmsAuthenticationToken(Object principal, Object credentials) {
                                                                                    super(null);
                                                                                    this.principal = principal;
                                                                                    this.credentials = credentials;
                                                                                    this.setAuthenticated(false);
                                                                                }
                                                                                /**
                                                                                 * 短信验证码认证 Token (已认证)
                                                                                 *
                                                                                 * @param principal   用户信息
                                                                                 * @param authorities 授权信息
                                                                                 */
                                                                                public SmsAuthenticationToken(Object principal, Collection authentication) {
                                                                                    return SmsAuthenticationToken.class.isAssignableFrom(authentication);
                                                                                }
                                                                            }
                                                                            

                                                                            Spring Security 配置

                                                                            在 SecurityConfig 中注册自定义的 SmsAuthenticationProvider,实现短信验证码登录认证逻辑:

                                                                            /**
                                                                             * Spring Security 配置类
                                                                             *
                                                                             * @author youlai
                                                                             */
                                                                            @Configuration
                                                                            @EnableWebSecurity
                                                                            @EnableMethodSecurity
                                                                            @RequiredArgsConstructor
                                                                            public class SecurityConfig {
                                                                                private final RedisTemplate redisTemplate;
                                                                                private final UserService userService;
                                                                                
                                                                                // ....
                                                                                
                                                                                /**
                                                                                 * 默认账号密码认证的 Provider
                                                                                 */
                                                                                @Bean
                                                                                public DaoAuthenticationProvider daoAuthenticationProvider() {
                                                                                    DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
                                                                                    daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
                                                                                    daoAuthenticationProvider.setUserDetailsService(userDetailsService);
                                                                                    return daoAuthenticationProvider;
                                                                                }
                                                                                /**
                                                                                 * 短信验证码认证 Provider
                                                                                 */
                                                                                @Bean
                                                                                public SmsAuthenticationProvider smsAuthenticationProvider() {
                                                                                    return new SmsAuthenticationProvider(userService, redisTemplate);
                                                                                }
                                                                                /**
                                                                                 * 认证管理器
                                                                                 */
                                                                                @Bean
                                                                                public AuthenticationManager authenticationManager(
                                                                                        DaoAuthenticationProvider daoAuthenticationProvider,
                                                                                        SmsAuthenticationProvider smsAuthenticationProvider
                                                                                ) {
                                                                                    return new ProviderManager(
                                                                                            daoAuthenticationProvider,
                                                                                            smsAuthenticationProvider
                                                                                    );
                                                                                }
                                                                            }
                                                                            

                                                                            发送验证码

                                                                            控制层实现

                                                                            @Operation(summary = "发送登录短信验证码")
                                                                            @PostMapping("/login/sms/code")
                                                                            public Result sendLoginVerifyCode(
                                                                                    @Parameter(description = "手机号", example = "18812345678") @RequestParam String mobile
                                                                            ) {
                                                                                authService.sendSmsLoginCode(mobile);
                                                                                return Result.success();
                                                                            }
                                                                            

                                                                            服务层实现

                                                                            @Service
                                                                            @RequiredArgsConstructor
                                                                            @Slf4j
                                                                            public class AuthServiceImpl implements AuthService {
                                                                            	
                                                                                private final SmsService smsService;
                                                                                private final RedisTemplate redisTemplate;
                                                                            	
                                                                            	/**
                                                                                 * 发送登录短信验证码
                                                                                 *
                                                                                 * @param mobile 手机号
                                                                                 */
                                                                                @Override
                                                                                public void sendSmsLoginCode(String mobile) {
                                                                                    // 随机生成4位验证码
                                                                                    // String code = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));
                                                                                    // TODO 为了方便测试,验证码固定为 1234,实际开发中在配置了厂商短信服务后,可以使用上面的随机验证码
                                                                                    String code = "1234";
                                                                                    // 发送短信验证码
                                                                                    Map templateParams = new HashMap();
                                                                                    templateParams.put("code", code);
                                                                                    try {
                                                                                        smsService.sendSms(mobile, SmsTypeEnum.LOGIN, templateParams);
                                                                                    } catch (Exception e) {
                                                                                        log.error("发送短信验证码失败", e);
                                                                                    }
                                                                                    // 缓存验证码至Redis,用于登录校验
                                                                                    redisTemplate.opsForValue().set(RedisConstants.SMS_LOGIN_CODE_PREFIX + mobile, code, 5, TimeUnit.MINUTES);
                                                                                }
                                                                            }
                                                                            

                                                                            登录接口

                                                                            控制层实现

                                                                            /**
                                                                             * 认证控制层
                                                                             *
                                                                             * @author youlai
                                                                             */
                                                                            @RestController
                                                                            @RequestMapping("/api/v1/auth")
                                                                            @RequiredArgsConstructor
                                                                            public class AuthController {
                                                                                private final AuthService authService;
                                                                                // ...
                                                                                
                                                                                @Operation(summary = "短信验证码登录")
                                                                                @PostMapping("/login/sms")
                                                                                @Log(value = "短信验证码登录", module = LogModuleEnum.LOGIN)
                                                                                public Result loginBySms(
                                                                                        @Parameter(description = "手机号", example = "18812345678") @RequestParam String mobile,
                                                                                        @Parameter(description = "验证码", example = "1234") @RequestParam String code
                                                                                ) {
                                                                                    AuthenticationToken loginResult = authService.loginBySms(mobile, code);
                                                                                    return Result.success(loginResult);
                                                                                }
                                                                            }
                                                                            

                                                                            服务层实现

                                                                            /**
                                                                             * 认证服务实现类
                                                                             *
                                                                             * @author youlai
                                                                             */
                                                                            @Service
                                                                            @RequiredArgsConstructor
                                                                            @Slf4j
                                                                            public class AuthServiceImpl implements AuthService {
                                                                            	
                                                                                private final SmsService smsService;
                                                                                private final RedisTemplate redisTemplate;
                                                                            	
                                                                                /**
                                                                                 * 短信验证码登录
                                                                                 *
                                                                                 * @param mobile 手机号
                                                                                 * @param code   验证码
                                                                                 * @return 访问令牌
                                                                                 */
                                                                                @Override
                                                                                public AuthenticationToken loginBySms(String mobile, String code) {
                                                                                    // 1. 创建用户短信验证码认证的令牌(未认证)
                                                                                    SmsAuthenticationToken smsAuthenticationToken = new SmsAuthenticationToken(mobile, code);
                                                                                    // 2. 执行认证(认证中)
                                                                                    Authentication authentication = authenticationManager.authenticate(smsAuthenticationToken);
                                                                                    // 3. 认证成功后生成 JWT 令牌,并存入 Security 上下文,供登录日志 AOP 使用(已认证)
                                                                                    AuthenticationToken authenticationToken = tokenManager.generateToken(authentication);
                                                                                    SecurityContextHolder.getContext().setAuthentication(authentication);
                                                                                    return authenticationToken;
                                                                                }
                                                                            }
                                                                            

                                                                            接口测试

                                                                            访问接口文档 http://localhost:8989/doc.html,调用发送短信验证码接口,输入手机号。

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            模拟接收短信验证码(固定为 1234),调用短信验证码登录接口,输入手机号和验证码即可成功登录并返回访问令牌。

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            项目部署

                                                                            安装虚拟机

                                                                            如果没有云服务器,可在本地安装虚拟机,参考:VMware 搭建 Linux 虚拟机环境 (CentOS 7.9)。

                                                                            安装并启动 FinalShell: 下载地址。新建连接,连接到已安装的虚拟机。

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            安装 Docker

                                                                            参考文档:Linux (CentOS) 安装 Docker 和 Docker Compose。

                                                                            安装中间件

                                                                            上传脚本

                                                                            将项目的 docker 和 sql 目录复制到服务器的 /opt 目录下:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            授予执行权限

                                                                            sudo chmod +x /opt/docker/docker-compose.yml
                                                                            

                                                                            启动服务

                                                                            切换到 /opt/docker 目录,执行以下命令启动容器:

                                                                            cd  /opt/docker
                                                                            # 启动服务
                                                                            docker-compose up -d
                                                                            

                                                                            等待片刻,容器启动完成后如下:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            验证安装

                                                                            **MySQL **

                                                                            启动脚本会自动创建数据库:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            Redis

                                                                            Redis 启动正常:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            MinIO

                                                                            打开浏览器访问 http://192.168.179.21:9090(根据实际 IP 修改),使用默认用户名密码 minioadmin/minioadmin 登录。

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            XXL-JOB

                                                                            打开浏览器访问 http://192.168.179.21:8080/xxl-job-admin(根据实际 IP 修改),输入默认用户名密码 admin/123456 登录。

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            部署应用

                                                                            安装插件

                                                                            在 IDEA 菜单栏选择 File → Settings → Plugins,搜索 Docker 插件并安装,安装后重启 IDEA。

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            配置服务器

                                                                            在 IDEA 菜单栏选择 File → Settings → Build, Execution, Deployment → Docker,添加远程服务器的连接信息:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            连接成功后,显示 Connection successful:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            部署配置

                                                                            在 IDEA 顶部菜单选择 Edit Configurations 打开配置界面:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            选择 Dockerfile,设置部署相关参数:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            一键部署

                                                                            配置完成后,选择对应配置点击启动,将自动完成编译、打包、镜像构建、镜像推送和容器启动。「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            启动成功后如下:

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            浏览器访问 http://192.168.179.21:8989/doc.html(根据实际 IP 修改)查看接口文档,验证部署是否成功。

                                                                            「youlai-boot」进阶篇:Java & Spring Boot 企业级权限管理系统实战指南(全功能详解)

                                                                            结语

                                                                            感谢您阅读本文档,youlai-boot 项目提供高效、灵活且可扩展的企业级权限管理解决方案。本手册从基础到扩展,为开发者提供了详细的参考指南,帮助您快速搭建项目并应对复杂业务需求。如有问题,欢迎添加微信(微信号:haoxianrui)交流或访问开源项目:https://gitee.com/youlaiorg。

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码