首页 文章 精选 留言 我的

精选列表

搜索[SpringBoot4],共12篇文章
优秀的个人博客,低调大师

xtools-boot一款基于JDK25,SpringBoot4的通用Spring工具库

xtools-boot 项目设计文档 开源地址: https://gitee.com/jun-xtools/xtools-boot.git 一、功能和用途 1.1 项目概述 项目信息 描述 项目名称 xtools-boot 项目版本 5.0.0 父POM xtools-parent-boot:5.0.0 顶级父POM xtools-parent:5.0.0 Spring Boot 4.0.6 JDK版本 25 项目定位 SpringBoot工具模块框架,为业务应用提供开箱即用的基础能力 维护团队 org.xujun 1.2 技术特点 采用最新的 JDK 25 版本,充分利用虚拟线程(Virtual Threads)、ScopedValue等新特性 基于 Spring Boot 4.0.6 构建,支持自动配置和快速开发 使用 MyBatis-Plus 3.5.16 简化数据访问层开发 使用 MyBatis 4.0.1 提供灵活的SQL映射能力 使用 Druid 1.2.28 数据库连接池,内置SQL监控 集成 Elasticsearch 9.2.8 实现日志存储和检索 支持 Knife4j 4.5.0 自动生成 API 文档 集成 Spring AMQP 4.0.3 实现 RabbitMQ 异步消息处理 集成 Spring Data Redis 实现分布式缓存 集成 XXL-JOB 3.4.0 实现分布式任务调度 集成 Spring Boot Admin 4.0.4 实现应用监控 使用 Jackson 3.1.2 进行 JSON 序列化/反序列化 使用 FastJSON2 2.0.60 处理JSON数据 使用 Lombok 1.18.46 简化Java代码 使用 MapStruct 1.6.3 进行对象映射转换 支持 S3 2.42.41 对象存储 使用 ip2region 3.3.7 实现IP地址定位 1.3 核心功能 #mq6cnds9fgbtdm061ep{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cnds9fgbtdm061ep .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cnds9fgbtdm061ep .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cnds9fgbtdm061ep .error-icon{fill:#a44141;}#mq6cnds9fgbtdm061ep .error-text{fill:#ddd;stroke:#ddd;}#mq6cnds9fgbtdm061ep .edge-thickness-normal{stroke-width:1px;}#mq6cnds9fgbtdm061ep .edge-thickness-thick{stroke-width:3.5px;}#mq6cnds9fgbtdm061ep .edge-pattern-solid{stroke-dasharray:0;}#mq6cnds9fgbtdm061ep .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cnds9fgbtdm061ep .edge-pattern-dashed{stroke-dasharray:3;}#mq6cnds9fgbtdm061ep .edge-pattern-dotted{stroke-dasharray:2;}#mq6cnds9fgbtdm061ep .marker{fill:lightgrey;stroke:lightgrey;}#mq6cnds9fgbtdm061ep .marker.cross{stroke:lightgrey;}#mq6cnds9fgbtdm061ep svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cnds9fgbtdm061ep p{margin:0;}#mq6cnds9fgbtdm061ep .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cnds9fgbtdm061ep .cluster-label text{fill:#F9FFFE;}#mq6cnds9fgbtdm061ep .cluster-label span{color:#F9FFFE;}#mq6cnds9fgbtdm061ep .cluster-label span p{background-color:transparent;}#mq6cnds9fgbtdm061ep .label text,#mq6cnds9fgbtdm061ep span{fill:#ccc;color:#ccc;}#mq6cnds9fgbtdm061ep .node rect,#mq6cnds9fgbtdm061ep .node circle,#mq6cnds9fgbtdm061ep .node ellipse,#mq6cnds9fgbtdm061ep .node polygon,#mq6cnds9fgbtdm061ep .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cnds9fgbtdm061ep .rough-node .label text,#mq6cnds9fgbtdm061ep .node .label text,#mq6cnds9fgbtdm061ep .image-shape .label,#mq6cnds9fgbtdm061ep .icon-shape .label{text-anchor:middle;}#mq6cnds9fgbtdm061ep .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cnds9fgbtdm061ep .rough-node .label,#mq6cnds9fgbtdm061ep .node .label,#mq6cnds9fgbtdm061ep .image-shape .label,#mq6cnds9fgbtdm061ep .icon-shape .label{text-align:center;}#mq6cnds9fgbtdm061ep .node.clickable{cursor:pointer;}#mq6cnds9fgbtdm061ep .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cnds9fgbtdm061ep .arrowheadPath{fill:lightgrey;}#mq6cnds9fgbtdm061ep .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cnds9fgbtdm061ep .flowchart-link{stroke:lightgrey;fill:none;}#mq6cnds9fgbtdm061ep .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cnds9fgbtdm061ep .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cnds9fgbtdm061ep .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cnds9fgbtdm061ep .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cnds9fgbtdm061ep .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cnds9fgbtdm061ep .cluster text{fill:#F9FFFE;}#mq6cnds9fgbtdm061ep .cluster span{color:#F9FFFE;}#mq6cnds9fgbtdm061ep div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cnds9fgbtdm061ep .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cnds9fgbtdm061ep rect.text{fill:none;stroke-width:0;}#mq6cnds9fgbtdm061ep .icon-shape,#mq6cnds9fgbtdm061ep .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cnds9fgbtdm061ep .icon-shape p,#mq6cnds9fgbtdm061ep .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cnds9fgbtdm061ep .icon-shape rect,#mq6cnds9fgbtdm061ep .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cnds9fgbtdm061ep .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cnds9fgbtdm061ep .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cnds9fgbtdm061ep :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}核心模块Spring上下文工具路径匹配工具枚举工具时间工具树形工具JAR工具Knife4j模块API文档增强白名单配置IP模块IP地址查询IP定位工具脱敏模块数据脱敏注解脱敏类型枚举自定义脱敏线程模块虚拟线程工具异步回调存储模块存储抽象接口文件存储S3存储任务模块任务总线TaskBus任务状态管理XXL-JOB集成日志模块日志总线LogBus日志追踪虚拟线程日志运行信息消息队列模块消息总线MqBusRabbitMQ实现消息编解码错误处理搜索引擎模块ES查询工具ES监控索引操作数据库模块MyBatis配置MyBatis-Plus增强Druid连接池SQL监控拦截MySQL监控缓存模块Redis服务分布式锁缓存监控Hash操作Web模块全局异常处理日志追踪FilterJackson定制配置过滤器链白名单机制API模块统一响应Result异常体系基础枚举日志追踪LogTrack分页模型树形模型XSS过滤注解1.4 功能层次结构 #mq6cndsgg2bh1g5l5s9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgg2bh1g5l5s9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgg2bh1g5l5s9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgg2bh1g5l5s9 .error-icon{fill:#a44141;}#mq6cndsgg2bh1g5l5s9 .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgg2bh1g5l5s9 .edge-thickness-normal{stroke-width:1px;}#mq6cndsgg2bh1g5l5s9 .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgg2bh1g5l5s9 .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgg2bh1g5l5s9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgg2bh1g5l5s9 .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgg2bh1g5l5s9 .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgg2bh1g5l5s9 .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgg2bh1g5l5s9 .marker.cross{stroke:lightgrey;}#mq6cndsgg2bh1g5l5s9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgg2bh1g5l5s9 p{margin:0;}#mq6cndsgg2bh1g5l5s9 .edge{stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .section--1 rect,#mq6cndsgg2bh1g5l5s9 .section--1 path,#mq6cndsgg2bh1g5l5s9 .section--1 circle,#mq6cndsgg2bh1g5l5s9 .section--1 polygon,#mq6cndsgg2bh1g5l5s9 .section--1 path{fill:#1f2020;}#mq6cndsgg2bh1g5l5s9 .section--1 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon--1{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge--1{stroke:#1f2020;}#mq6cndsgg2bh1g5l5s9 .edge-depth--1{stroke-width:17;}#mq6cndsgg2bh1g5l5s9 .section--1 line{stroke:#e0dfdf;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-0 rect,#mq6cndsgg2bh1g5l5s9 .section-0 path,#mq6cndsgg2bh1g5l5s9 .section-0 circle,#mq6cndsgg2bh1g5l5s9 .section-0 polygon,#mq6cndsgg2bh1g5l5s9 .section-0 path{fill:#0b0000;}#mq6cndsgg2bh1g5l5s9 .section-0 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-0{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-0{stroke:#0b0000;}#mq6cndsgg2bh1g5l5s9 .edge-depth-0{stroke-width:14;}#mq6cndsgg2bh1g5l5s9 .section-0 line{stroke:#f4ffff;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-1 rect,#mq6cndsgg2bh1g5l5s9 .section-1 path,#mq6cndsgg2bh1g5l5s9 .section-1 circle,#mq6cndsgg2bh1g5l5s9 .section-1 polygon,#mq6cndsgg2bh1g5l5s9 .section-1 path{fill:#4d1037;}#mq6cndsgg2bh1g5l5s9 .section-1 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-1{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-1{stroke:#4d1037;}#mq6cndsgg2bh1g5l5s9 .edge-depth-1{stroke-width:11;}#mq6cndsgg2bh1g5l5s9 .section-1 line{stroke:#b2efc8;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-2 rect,#mq6cndsgg2bh1g5l5s9 .section-2 path,#mq6cndsgg2bh1g5l5s9 .section-2 circle,#mq6cndsgg2bh1g5l5s9 .section-2 polygon,#mq6cndsgg2bh1g5l5s9 .section-2 path{fill:#3f5258;}#mq6cndsgg2bh1g5l5s9 .section-2 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-2{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-2{stroke:#3f5258;}#mq6cndsgg2bh1g5l5s9 .edge-depth-2{stroke-width:8;}#mq6cndsgg2bh1g5l5s9 .section-2 line{stroke:#c0ada7;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-3 rect,#mq6cndsgg2bh1g5l5s9 .section-3 path,#mq6cndsgg2bh1g5l5s9 .section-3 circle,#mq6cndsgg2bh1g5l5s9 .section-3 polygon,#mq6cndsgg2bh1g5l5s9 .section-3 path{fill:#4f2f1b;}#mq6cndsgg2bh1g5l5s9 .section-3 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-3{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-3{stroke:#4f2f1b;}#mq6cndsgg2bh1g5l5s9 .edge-depth-3{stroke-width:5;}#mq6cndsgg2bh1g5l5s9 .section-3 line{stroke:#b0d0e4;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-4 rect,#mq6cndsgg2bh1g5l5s9 .section-4 path,#mq6cndsgg2bh1g5l5s9 .section-4 circle,#mq6cndsgg2bh1g5l5s9 .section-4 polygon,#mq6cndsgg2bh1g5l5s9 .section-4 path{fill:#6e0a0a;}#mq6cndsgg2bh1g5l5s9 .section-4 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-4{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-4{stroke:#6e0a0a;}#mq6cndsgg2bh1g5l5s9 .edge-depth-4{stroke-width:2;}#mq6cndsgg2bh1g5l5s9 .section-4 line{stroke:#91f5f5;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-5 rect,#mq6cndsgg2bh1g5l5s9 .section-5 path,#mq6cndsgg2bh1g5l5s9 .section-5 circle,#mq6cndsgg2bh1g5l5s9 .section-5 polygon,#mq6cndsgg2bh1g5l5s9 .section-5 path{fill:#3b0048;}#mq6cndsgg2bh1g5l5s9 .section-5 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-5{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-5{stroke:#3b0048;}#mq6cndsgg2bh1g5l5s9 .edge-depth-5{stroke-width:-1;}#mq6cndsgg2bh1g5l5s9 .section-5 line{stroke:#c4ffb7;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-6 rect,#mq6cndsgg2bh1g5l5s9 .section-6 path,#mq6cndsgg2bh1g5l5s9 .section-6 circle,#mq6cndsgg2bh1g5l5s9 .section-6 polygon,#mq6cndsgg2bh1g5l5s9 .section-6 path{fill:#995a01;}#mq6cndsgg2bh1g5l5s9 .section-6 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-6{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-6{stroke:#995a01;}#mq6cndsgg2bh1g5l5s9 .edge-depth-6{stroke-width:-4;}#mq6cndsgg2bh1g5l5s9 .section-6 line{stroke:#66a5fe;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-7 rect,#mq6cndsgg2bh1g5l5s9 .section-7 path,#mq6cndsgg2bh1g5l5s9 .section-7 circle,#mq6cndsgg2bh1g5l5s9 .section-7 polygon,#mq6cndsgg2bh1g5l5s9 .section-7 path{fill:#154706;}#mq6cndsgg2bh1g5l5s9 .section-7 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-7{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-7{stroke:#154706;}#mq6cndsgg2bh1g5l5s9 .edge-depth-7{stroke-width:-7;}#mq6cndsgg2bh1g5l5s9 .section-7 line{stroke:#eab8f9;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-8 rect,#mq6cndsgg2bh1g5l5s9 .section-8 path,#mq6cndsgg2bh1g5l5s9 .section-8 circle,#mq6cndsgg2bh1g5l5s9 .section-8 polygon,#mq6cndsgg2bh1g5l5s9 .section-8 path{fill:#161722;}#mq6cndsgg2bh1g5l5s9 .section-8 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-8{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-8{stroke:#161722;}#mq6cndsgg2bh1g5l5s9 .edge-depth-8{stroke-width:-10;}#mq6cndsgg2bh1g5l5s9 .section-8 line{stroke:#e9e8dd;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-9 rect,#mq6cndsgg2bh1g5l5s9 .section-9 path,#mq6cndsgg2bh1g5l5s9 .section-9 circle,#mq6cndsgg2bh1g5l5s9 .section-9 polygon,#mq6cndsgg2bh1g5l5s9 .section-9 path{fill:#00296f;}#mq6cndsgg2bh1g5l5s9 .section-9 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-9{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-9{stroke:#00296f;}#mq6cndsgg2bh1g5l5s9 .edge-depth-9{stroke-width:-13;}#mq6cndsgg2bh1g5l5s9 .section-9 line{stroke:#ffd690;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-10 rect,#mq6cndsgg2bh1g5l5s9 .section-10 path,#mq6cndsgg2bh1g5l5s9 .section-10 circle,#mq6cndsgg2bh1g5l5s9 .section-10 polygon,#mq6cndsgg2bh1g5l5s9 .section-10 path{fill:#01629c;}#mq6cndsgg2bh1g5l5s9 .section-10 text{fill:lightgrey;}#mq6cndsgg2bh1g5l5s9 .node-icon-10{font-size:40px;color:lightgrey;}#mq6cndsgg2bh1g5l5s9 .section-edge-10{stroke:#01629c;}#mq6cndsgg2bh1g5l5s9 .edge-depth-10{stroke-width:-16;}#mq6cndsgg2bh1g5l5s9 .section-10 line{stroke:#fe9d63;stroke-width:3;}#mq6cndsgg2bh1g5l5s9 .disabled,#mq6cndsgg2bh1g5l5s9 .disabled circle,#mq6cndsgg2bh1g5l5s9 .disabled text{fill:lightgray;}#mq6cndsgg2bh1g5l5s9 .disabled text{fill:#efefef;}#mq6cndsgg2bh1g5l5s9 .section-root rect,#mq6cndsgg2bh1g5l5s9 .section-root path,#mq6cndsgg2bh1g5l5s9 .section-root circle,#mq6cndsgg2bh1g5l5s9 .section-root polygon{fill:hsl(180, 1.5873015873%, 48.3529411765%);}#mq6cndsgg2bh1g5l5s9 .section-root text{fill:#2c2c2c;}#mq6cndsgg2bh1g5l5s9 .section-root span{color:#2c2c2c;}#mq6cndsgg2bh1g5l5s9 .section-2 span{color:#2c2c2c;}#mq6cndsgg2bh1g5l5s9 .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mq6cndsgg2bh1g5l5s9 .edge{fill:none;}#mq6cndsgg2bh1g5l5s9 .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mq6cndsgg2bh1g5l5s9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}xtools-bootSpringBoot工具模块框架API基础统一响应Result异常体系基础枚举日志追踪LogTrack分页模型树形模型Web基础全局异常处理日志追踪FilterJackson定制XSS过滤过滤器链缓存Redis服务分布式锁Hash操作缓存监控数据库MyBatis配置MyBatis-Plus增强Druid连接池SQL监控MySQL监控搜索引擎ES查询工具ES监控消息队列消息总线RabbitMQ实现消息编解码日志日志总线LogBus日志追踪虚拟线程日志任务任务总线TaskBusXXL-JOB集成存储存储抽象接口文件存储S3存储安全数据脱敏XSS防护工具虚拟线程IP定位枚举工具树形工具时间工具1.5 功能关系图 #mq6cndsg08vqsd6i2dvj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsg08vqsd6i2dvj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsg08vqsd6i2dvj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsg08vqsd6i2dvj .error-icon{fill:#a44141;}#mq6cndsg08vqsd6i2dvj .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsg08vqsd6i2dvj .edge-thickness-normal{stroke-width:1px;}#mq6cndsg08vqsd6i2dvj .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsg08vqsd6i2dvj .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsg08vqsd6i2dvj .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsg08vqsd6i2dvj .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsg08vqsd6i2dvj .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsg08vqsd6i2dvj .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsg08vqsd6i2dvj .marker.cross{stroke:lightgrey;}#mq6cndsg08vqsd6i2dvj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsg08vqsd6i2dvj p{margin:0;}#mq6cndsg08vqsd6i2dvj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsg08vqsd6i2dvj .cluster-label text{fill:#F9FFFE;}#mq6cndsg08vqsd6i2dvj .cluster-label span{color:#F9FFFE;}#mq6cndsg08vqsd6i2dvj .cluster-label span p{background-color:transparent;}#mq6cndsg08vqsd6i2dvj .label text,#mq6cndsg08vqsd6i2dvj span{fill:#ccc;color:#ccc;}#mq6cndsg08vqsd6i2dvj .node rect,#mq6cndsg08vqsd6i2dvj .node circle,#mq6cndsg08vqsd6i2dvj .node ellipse,#mq6cndsg08vqsd6i2dvj .node polygon,#mq6cndsg08vqsd6i2dvj .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsg08vqsd6i2dvj .rough-node .label text,#mq6cndsg08vqsd6i2dvj .node .label text,#mq6cndsg08vqsd6i2dvj .image-shape .label,#mq6cndsg08vqsd6i2dvj .icon-shape .label{text-anchor:middle;}#mq6cndsg08vqsd6i2dvj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsg08vqsd6i2dvj .rough-node .label,#mq6cndsg08vqsd6i2dvj .node .label,#mq6cndsg08vqsd6i2dvj .image-shape .label,#mq6cndsg08vqsd6i2dvj .icon-shape .label{text-align:center;}#mq6cndsg08vqsd6i2dvj .node.clickable{cursor:pointer;}#mq6cndsg08vqsd6i2dvj .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsg08vqsd6i2dvj .arrowheadPath{fill:lightgrey;}#mq6cndsg08vqsd6i2dvj .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsg08vqsd6i2dvj .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsg08vqsd6i2dvj .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsg08vqsd6i2dvj .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsg08vqsd6i2dvj .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsg08vqsd6i2dvj .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsg08vqsd6i2dvj .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsg08vqsd6i2dvj .cluster text{fill:#F9FFFE;}#mq6cndsg08vqsd6i2dvj .cluster span{color:#F9FFFE;}#mq6cndsg08vqsd6i2dvj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsg08vqsd6i2dvj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsg08vqsd6i2dvj rect.text{fill:none;stroke-width:0;}#mq6cndsg08vqsd6i2dvj .icon-shape,#mq6cndsg08vqsd6i2dvj .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsg08vqsd6i2dvj .icon-shape p,#mq6cndsg08vqsd6i2dvj .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsg08vqsd6i2dvj .icon-shape rect,#mq6cndsg08vqsd6i2dvj .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsg08vqsd6i2dvj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsg08vqsd6i2dvj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsg08vqsd6i2dvj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}异常异步异步存储持久化序列化HTTP请求过滤器链日志追踪Filter公共FilterController层Service层全局异常处理器Redis缓存数据库消息队列日志总线Elasticsearch任务总线XXL-JOB存储服务本地文件S3对象存储脱敏注解Jackson二、项目结构设计 2.1 整体架构 #mq6cndsgzw8sf9bekbj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgzw8sf9bekbj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgzw8sf9bekbj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgzw8sf9bekbj .error-icon{fill:#a44141;}#mq6cndsgzw8sf9bekbj .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgzw8sf9bekbj .edge-thickness-normal{stroke-width:1px;}#mq6cndsgzw8sf9bekbj .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgzw8sf9bekbj .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgzw8sf9bekbj .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgzw8sf9bekbj .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgzw8sf9bekbj .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgzw8sf9bekbj .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgzw8sf9bekbj .marker.cross{stroke:lightgrey;}#mq6cndsgzw8sf9bekbj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgzw8sf9bekbj p{margin:0;}#mq6cndsgzw8sf9bekbj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgzw8sf9bekbj .cluster-label text{fill:#F9FFFE;}#mq6cndsgzw8sf9bekbj .cluster-label span{color:#F9FFFE;}#mq6cndsgzw8sf9bekbj .cluster-label span p{background-color:transparent;}#mq6cndsgzw8sf9bekbj .label text,#mq6cndsgzw8sf9bekbj span{fill:#ccc;color:#ccc;}#mq6cndsgzw8sf9bekbj .node rect,#mq6cndsgzw8sf9bekbj .node circle,#mq6cndsgzw8sf9bekbj .node ellipse,#mq6cndsgzw8sf9bekbj .node polygon,#mq6cndsgzw8sf9bekbj .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgzw8sf9bekbj .rough-node .label text,#mq6cndsgzw8sf9bekbj .node .label text,#mq6cndsgzw8sf9bekbj .image-shape .label,#mq6cndsgzw8sf9bekbj .icon-shape .label{text-anchor:middle;}#mq6cndsgzw8sf9bekbj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgzw8sf9bekbj .rough-node .label,#mq6cndsgzw8sf9bekbj .node .label,#mq6cndsgzw8sf9bekbj .image-shape .label,#mq6cndsgzw8sf9bekbj .icon-shape .label{text-align:center;}#mq6cndsgzw8sf9bekbj .node.clickable{cursor:pointer;}#mq6cndsgzw8sf9bekbj .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgzw8sf9bekbj .arrowheadPath{fill:lightgrey;}#mq6cndsgzw8sf9bekbj .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgzw8sf9bekbj .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgzw8sf9bekbj .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgzw8sf9bekbj .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgzw8sf9bekbj .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgzw8sf9bekbj .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgzw8sf9bekbj .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgzw8sf9bekbj .cluster text{fill:#F9FFFE;}#mq6cndsgzw8sf9bekbj .cluster span{color:#F9FFFE;}#mq6cndsgzw8sf9bekbj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgzw8sf9bekbj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgzw8sf9bekbj rect.text{fill:none;stroke-width:0;}#mq6cndsgzw8sf9bekbj .icon-shape,#mq6cndsgzw8sf9bekbj .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgzw8sf9bekbj .icon-shape p,#mq6cndsgzw8sf9bekbj .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgzw8sf9bekbj .icon-shape rect,#mq6cndsgzw8sf9bekbj .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgzw8sf9bekbj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgzw8sf9bekbj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgzw8sf9bekbj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}xtools-boot父模块xtools-boot-apiAPI基础模块xtools-boot-core核心工具模块xtools-boot-cache缓存模块xtools-boot-db数据库模块xtools-boot-elasticsearch搜索引擎模块xtools-boot-ipIP工具模块xtools-boot-job任务调度模块xtools-boot-knife4jAPI文档模块xtools-boot-log日志模块xtools-boot-mask脱敏模块xtools-boot-mq消息队列模块xtools-boot-storage存储模块xtools-boot-task任务总线模块xtools-boot-thread线程模块xtools-boot-webWeb基础模块xtools-boot-cache-redisRedis缓存xtools-boot-db-mybatisMyBatisxtools-boot-db-mybatis-plusMyBatis-Plusxtools-boot-job-xxlXXL-JOBxtools-boot-mq-baseMQ基础xtools-boot-mq-rabbitRabbitMQxtools-boot-storage-base存储基础xtools-boot-storage-file文件存储xtools-boot-storage-s3S3存储xtools-boot-web-baseWeb基础xtools-boot-web-filter过滤器2.2 分层架构 #mq6cndsgcslslungmzh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgcslslungmzh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgcslslungmzh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgcslslungmzh .error-icon{fill:#a44141;}#mq6cndsgcslslungmzh .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgcslslungmzh .edge-thickness-normal{stroke-width:1px;}#mq6cndsgcslslungmzh .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgcslslungmzh .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgcslslungmzh .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgcslslungmzh .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgcslslungmzh .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgcslslungmzh .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgcslslungmzh .marker.cross{stroke:lightgrey;}#mq6cndsgcslslungmzh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgcslslungmzh p{margin:0;}#mq6cndsgcslslungmzh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgcslslungmzh .cluster-label text{fill:#F9FFFE;}#mq6cndsgcslslungmzh .cluster-label span{color:#F9FFFE;}#mq6cndsgcslslungmzh .cluster-label span p{background-color:transparent;}#mq6cndsgcslslungmzh .label text,#mq6cndsgcslslungmzh span{fill:#ccc;color:#ccc;}#mq6cndsgcslslungmzh .node rect,#mq6cndsgcslslungmzh .node circle,#mq6cndsgcslslungmzh .node ellipse,#mq6cndsgcslslungmzh .node polygon,#mq6cndsgcslslungmzh .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgcslslungmzh .rough-node .label text,#mq6cndsgcslslungmzh .node .label text,#mq6cndsgcslslungmzh .image-shape .label,#mq6cndsgcslslungmzh .icon-shape .label{text-anchor:middle;}#mq6cndsgcslslungmzh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgcslslungmzh .rough-node .label,#mq6cndsgcslslungmzh .node .label,#mq6cndsgcslslungmzh .image-shape .label,#mq6cndsgcslslungmzh .icon-shape .label{text-align:center;}#mq6cndsgcslslungmzh .node.clickable{cursor:pointer;}#mq6cndsgcslslungmzh .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgcslslungmzh .arrowheadPath{fill:lightgrey;}#mq6cndsgcslslungmzh .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgcslslungmzh .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgcslslungmzh .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgcslslungmzh .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgcslslungmzh .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgcslslungmzh .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgcslslungmzh .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgcslslungmzh .cluster text{fill:#F9FFFE;}#mq6cndsgcslslungmzh .cluster span{color:#F9FFFE;}#mq6cndsgcslslungmzh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgcslslungmzh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgcslslungmzh rect.text{fill:none;stroke-width:0;}#mq6cndsgcslslungmzh .icon-shape,#mq6cndsgcslslungmzh .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgcslslungmzh .icon-shape p,#mq6cndsgcslslungmzh .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgcslslungmzh .icon-shape rect,#mq6cndsgcslslungmzh .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgcslslungmzh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgcslslungmzh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgcslslungmzh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}数据层业务模块层Web层过滤器层SkipFilter白名单过滤器 Order:0LogTrackFilter日志追踪过滤器 Order:100CommonFilter公共过滤器 Order:101GlobalControllerExceptionHandler全局异常处理JacksonConfigJSON序列化配置MvcConverterConfigMVC转换器配置缓存模块 RedisService日志模块 LogBus任务模块 TaskBus消息模块 MqBus存储模块 StorageService脱敏模块 MaskSerializerMyBatis / MyBatis-PlusRedisElasticsearchRabbitMQ文件系统 / S32.3 模块职责 模块 职责 关键类 xtools-boot-api API基础定义:统一响应、异常体系、枚举、日志追踪模型、分页/树形模型 Result, BizError, LogTrack, PageReq, PageResp, TreeResp xtools-boot-core 核心工具集:Spring上下文、路径匹配、枚举工具、时间工具、树形工具、JAR工具 SpringContextUtils, PathPatternUtils, TreeUtils, TimeUtils xtools-boot-cache Redis缓存服务:数据缓存、分布式锁、Hash操作、缓存监控 RedisService, RedisUtils, RedisMonitor xtools-boot-db 数据库访问:MyBatis配置、MyBatis-Plus增强、Druid连接池、SQL监控、MySQL监控 BootDbMybatisConfiguration, BootDbMybatisPlusConfiguration, MySqlMonitor xtools-boot-elasticsearch 搜索引擎:ES查询构建、ES操作、ES监控 EsUtils, EsQueryUtils, ElasticsearchMonitor xtools-boot-ip IP地址工具:IP库初始化、IP地址查询和定位 IpUtils, InitIp xtools-boot-job 任务调度:XXL-JOB配置和初始化 XxlJobConfig, InitXxlJob xtools-boot-knife4j API文档:Knife4j集成和白名单配置 BootKnife4jConfiguration, Knife4jFilterWhitelist xtools-boot-log 日志总线:日志采集、格式化、异步持久化、日志追踪 LogBus, LogTrackHolder, LogBody, RunInfo xtools-boot-mask 数据脱敏:字段级脱敏注解、多种脱敏类型、自定义脱敏 @Mask, MaskSerializer, MaskType, DefaultMaskHandle xtools-boot-mq 消息队列:消息总线、RabbitMQ实现、消息编解码、错误处理 MqBus, RabbitMqHandle, BaseMessageHandle, MqMessageUtils xtools-boot-storage 存储抽象:统一存储接口、本地文件实现、S3实现 StorageService, StorageServiceFileImpl, StorageServiceS3Impl xtools-boot-task 任务总线:任务状态管理、任务信息持久化 TaskBus, TaskInfo, TaskStatus xtools-boot-thread 线程工具:虚拟线程执行、异步回调 VirtualThreadTaskUtils, VirtualThreadTaskCallback xtools-boot-web Web基础:全局异常处理、日志追踪Filter、Jackson定制、XSS过滤、过滤器链 GlobalControllerExceptionHandler, LogTrackFilter, CommonFilter 2.4 包结构设计 复制代码 xtools.boot.{module} ├── {Module}Configuration # 模块配置类(@Import ImportSelector) ├── selector │ └── {Module}ImportSelector # 自动导入选择器 ├── config # 模块配置属性 ├── constant # 常量定义 ├── enums # 枚举定义 ├── interfaces # 接口定义 │ ├── BusInterface # 总线接口(LogBusInterface, TaskBusInterface, MqEnums) │ └── BaseType # 基础类型接口(BaseEnum, BaseTaskType) ├── model │ └── dto # 数据传输对象 ├── utils # 工具类 ├── handle # 处理器 ├── filter # 过滤器 ├── init # 初始化(ApplicationRunner) ├── monitor # 监控组件 ├── holder # 持有器(ScopedValue) ├── service # 服务接口和实现 └── annotation # 自定义注解 2.5 模块自动装配设计 所有模块采用统一的自动装配模式: #mq6cxh344sd269atlkm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cxh344sd269atlkm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cxh344sd269atlkm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cxh344sd269atlkm .error-icon{fill:#a44141;}#mq6cxh344sd269atlkm .error-text{fill:#ddd;stroke:#ddd;}#mq6cxh344sd269atlkm .edge-thickness-normal{stroke-width:1px;}#mq6cxh344sd269atlkm .edge-thickness-thick{stroke-width:3.5px;}#mq6cxh344sd269atlkm .edge-pattern-solid{stroke-dasharray:0;}#mq6cxh344sd269atlkm .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cxh344sd269atlkm .edge-pattern-dashed{stroke-dasharray:3;}#mq6cxh344sd269atlkm .edge-pattern-dotted{stroke-dasharray:2;}#mq6cxh344sd269atlkm .marker{fill:lightgrey;stroke:lightgrey;}#mq6cxh344sd269atlkm .marker.cross{stroke:lightgrey;}#mq6cxh344sd269atlkm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cxh344sd269atlkm p{margin:0;}#mq6cxh344sd269atlkm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cxh344sd269atlkm .cluster-label text{fill:#F9FFFE;}#mq6cxh344sd269atlkm .cluster-label span{color:#F9FFFE;}#mq6cxh344sd269atlkm .cluster-label span p{background-color:transparent;}#mq6cxh344sd269atlkm .label text,#mq6cxh344sd269atlkm span{fill:#ccc;color:#ccc;}#mq6cxh344sd269atlkm .node rect,#mq6cxh344sd269atlkm .node circle,#mq6cxh344sd269atlkm .node ellipse,#mq6cxh344sd269atlkm .node polygon,#mq6cxh344sd269atlkm .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cxh344sd269atlkm .rough-node .label text,#mq6cxh344sd269atlkm .node .label text,#mq6cxh344sd269atlkm .image-shape .label,#mq6cxh344sd269atlkm .icon-shape .label{text-anchor:middle;}#mq6cxh344sd269atlkm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cxh344sd269atlkm .rough-node .label,#mq6cxh344sd269atlkm .node .label,#mq6cxh344sd269atlkm .image-shape .label,#mq6cxh344sd269atlkm .icon-shape .label{text-align:center;}#mq6cxh344sd269atlkm .node.clickable{cursor:pointer;}#mq6cxh344sd269atlkm .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cxh344sd269atlkm .arrowheadPath{fill:lightgrey;}#mq6cxh344sd269atlkm .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cxh344sd269atlkm .flowchart-link{stroke:lightgrey;fill:none;}#mq6cxh344sd269atlkm .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cxh344sd269atlkm .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cxh344sd269atlkm .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cxh344sd269atlkm .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cxh344sd269atlkm .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cxh344sd269atlkm .cluster text{fill:#F9FFFE;}#mq6cxh344sd269atlkm .cluster span{color:#F9FFFE;}#mq6cxh344sd269atlkm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cxh344sd269atlkm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cxh344sd269atlkm rect.text{fill:none;stroke-width:0;}#mq6cxh344sd269atlkm .icon-shape,#mq6cxh344sd269atlkm .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cxh344sd269atlkm .icon-shape p,#mq6cxh344sd269atlkm .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cxh344sd269atlkm .icon-shape rect,#mq6cxh344sd269atlkm .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cxh344sd269atlkm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cxh344sd269atlkm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cxh344sd269atlkm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}业务应用引入模块依赖模块Configuration类 @ConfigurationImportSelector通过 @Import导入扫描模块包路径registerBeanDefinitions注册模块内所有ComponentConfiguration / Utils / Monitor等设计原则: 每个模块通过 @Configuration + @Import(ImportSelector) 实现按需加载 ImportSelector 指定模块的根包路径,自动注册所有 @Component、@Configuration 等注解的类 业务应用只需引入对应模块的 Maven 依赖,无需手动配置 三、项目功能设计 3.1 统一响应与异常设计 统一响应模型 java 复制代码 public final class Result<T> { private boolean success; // 是否成功 private int code; // 响应代码 private Object msg; // 提示信息 private T data; // 响应数据 } 异常体系 #mq6cndsgjok64yhnldg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgjok64yhnldg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgjok64yhnldg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgjok64yhnldg .error-icon{fill:#a44141;}#mq6cndsgjok64yhnldg .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgjok64yhnldg .edge-thickness-normal{stroke-width:1px;}#mq6cndsgjok64yhnldg .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgjok64yhnldg .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgjok64yhnldg .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgjok64yhnldg .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgjok64yhnldg .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgjok64yhnldg .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgjok64yhnldg .marker.cross{stroke:lightgrey;}#mq6cndsgjok64yhnldg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgjok64yhnldg p{margin:0;}#mq6cndsgjok64yhnldg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgjok64yhnldg .cluster-label text{fill:#F9FFFE;}#mq6cndsgjok64yhnldg .cluster-label span{color:#F9FFFE;}#mq6cndsgjok64yhnldg .cluster-label span p{background-color:transparent;}#mq6cndsgjok64yhnldg .label text,#mq6cndsgjok64yhnldg span{fill:#ccc;color:#ccc;}#mq6cndsgjok64yhnldg .node rect,#mq6cndsgjok64yhnldg .node circle,#mq6cndsgjok64yhnldg .node ellipse,#mq6cndsgjok64yhnldg .node polygon,#mq6cndsgjok64yhnldg .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgjok64yhnldg .rough-node .label text,#mq6cndsgjok64yhnldg .node .label text,#mq6cndsgjok64yhnldg .image-shape .label,#mq6cndsgjok64yhnldg .icon-shape .label{text-anchor:middle;}#mq6cndsgjok64yhnldg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgjok64yhnldg .rough-node .label,#mq6cndsgjok64yhnldg .node .label,#mq6cndsgjok64yhnldg .image-shape .label,#mq6cndsgjok64yhnldg .icon-shape .label{text-align:center;}#mq6cndsgjok64yhnldg .node.clickable{cursor:pointer;}#mq6cndsgjok64yhnldg .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgjok64yhnldg .arrowheadPath{fill:lightgrey;}#mq6cndsgjok64yhnldg .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgjok64yhnldg .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgjok64yhnldg .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgjok64yhnldg .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgjok64yhnldg .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgjok64yhnldg .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgjok64yhnldg .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgjok64yhnldg .cluster text{fill:#F9FFFE;}#mq6cndsgjok64yhnldg .cluster span{color:#F9FFFE;}#mq6cndsgjok64yhnldg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgjok64yhnldg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgjok64yhnldg rect.text{fill:none;stroke-width:0;}#mq6cndsgjok64yhnldg .icon-shape,#mq6cndsgjok64yhnldg .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgjok64yhnldg .icon-shape p,#mq6cndsgjok64yhnldg .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgjok64yhnldg .icon-shape rect,#mq6cndsgjok64yhnldg .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgjok64yhnldg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgjok64yhnldg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgjok64yhnldg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}code >= 1000code >= 1000code >= 1000code=401CommonExceptionxtools-coreBizError业务异常BizWarning业务警告BizPublicKeyError公钥异常UnauthorizedError认证异常返回Result.success=truecode=业务码返回ResultType.UNAUTHORIZED全局异常处理流程 #mq6cndsgq4ptrynjta{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgq4ptrynjta .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgq4ptrynjta .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgq4ptrynjta .error-icon{fill:#a44141;}#mq6cndsgq4ptrynjta .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgq4ptrynjta .edge-thickness-normal{stroke-width:1px;}#mq6cndsgq4ptrynjta .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgq4ptrynjta .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgq4ptrynjta .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgq4ptrynjta .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgq4ptrynjta .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgq4ptrynjta .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgq4ptrynjta .marker.cross{stroke:lightgrey;}#mq6cndsgq4ptrynjta svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgq4ptrynjta p{margin:0;}#mq6cndsgq4ptrynjta .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgq4ptrynjta .cluster-label text{fill:#F9FFFE;}#mq6cndsgq4ptrynjta .cluster-label span{color:#F9FFFE;}#mq6cndsgq4ptrynjta .cluster-label span p{background-color:transparent;}#mq6cndsgq4ptrynjta .label text,#mq6cndsgq4ptrynjta span{fill:#ccc;color:#ccc;}#mq6cndsgq4ptrynjta .node rect,#mq6cndsgq4ptrynjta .node circle,#mq6cndsgq4ptrynjta .node ellipse,#mq6cndsgq4ptrynjta .node polygon,#mq6cndsgq4ptrynjta .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgq4ptrynjta .rough-node .label text,#mq6cndsgq4ptrynjta .node .label text,#mq6cndsgq4ptrynjta .image-shape .label,#mq6cndsgq4ptrynjta .icon-shape .label{text-anchor:middle;}#mq6cndsgq4ptrynjta .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgq4ptrynjta .rough-node .label,#mq6cndsgq4ptrynjta .node .label,#mq6cndsgq4ptrynjta .image-shape .label,#mq6cndsgq4ptrynjta .icon-shape .label{text-align:center;}#mq6cndsgq4ptrynjta .node.clickable{cursor:pointer;}#mq6cndsgq4ptrynjta .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgq4ptrynjta .arrowheadPath{fill:lightgrey;}#mq6cndsgq4ptrynjta .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgq4ptrynjta .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgq4ptrynjta .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgq4ptrynjta .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgq4ptrynjta .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgq4ptrynjta .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgq4ptrynjta .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgq4ptrynjta .cluster text{fill:#F9FFFE;}#mq6cndsgq4ptrynjta .cluster span{color:#F9FFFE;}#mq6cndsgq4ptrynjta div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgq4ptrynjta .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgq4ptrynjta rect.text{fill:none;stroke-width:0;}#mq6cndsgq4ptrynjta .icon-shape,#mq6cndsgq4ptrynjta .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgq4ptrynjta .icon-shape p,#mq6cndsgq4ptrynjta .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgq4ptrynjta .icon-shape rect,#mq6cndsgq4ptrynjta .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgq4ptrynjta .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgq4ptrynjta .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgq4ptrynjta :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}MethodArgumentTypeMismatchExceptionHandlerMethodValidationExceptionMethodArgumentNotValidExceptionHttpMessageNotReadableExceptionBizErrorBizWarningBizPublicKeyErrorUnauthorizedErrorHttpRequestMethodNotSupportedExceptionNoResourceFoundExceptionClientAbortExceptionExceptionController抛出异常异常类型参数类型不匹配参数校验异常参数校验异常请求参数格式错误业务异常业务警告公钥错误认证异常请求方法不支持资源未找到客户端断开默认异常处理返回 badRequest返回 business code返回 401 UNAUTHORIZED返回 405 METHOD_NOT_ALLOWED返回 404 NOT_FOUND静默处理返回 500 INTERNAL_SERVER_ERRORLogBus记录日志3.2 日志管理设计 日志总线架构 #mq6cndsgbjsbg0pk58v{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgbjsbg0pk58v .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgbjsbg0pk58v .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgbjsbg0pk58v .error-icon{fill:#a44141;}#mq6cndsgbjsbg0pk58v .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgbjsbg0pk58v .edge-thickness-normal{stroke-width:1px;}#mq6cndsgbjsbg0pk58v .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgbjsbg0pk58v .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgbjsbg0pk58v .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgbjsbg0pk58v .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgbjsbg0pk58v .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgbjsbg0pk58v .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgbjsbg0pk58v .marker.cross{stroke:lightgrey;}#mq6cndsgbjsbg0pk58v svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgbjsbg0pk58v p{margin:0;}#mq6cndsgbjsbg0pk58v .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgbjsbg0pk58v .cluster-label text{fill:#F9FFFE;}#mq6cndsgbjsbg0pk58v .cluster-label span{color:#F9FFFE;}#mq6cndsgbjsbg0pk58v .cluster-label span p{background-color:transparent;}#mq6cndsgbjsbg0pk58v .label text,#mq6cndsgbjsbg0pk58v span{fill:#ccc;color:#ccc;}#mq6cndsgbjsbg0pk58v .node rect,#mq6cndsgbjsbg0pk58v .node circle,#mq6cndsgbjsbg0pk58v .node ellipse,#mq6cndsgbjsbg0pk58v .node polygon,#mq6cndsgbjsbg0pk58v .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgbjsbg0pk58v .rough-node .label text,#mq6cndsgbjsbg0pk58v .node .label text,#mq6cndsgbjsbg0pk58v .image-shape .label,#mq6cndsgbjsbg0pk58v .icon-shape .label{text-anchor:middle;}#mq6cndsgbjsbg0pk58v .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgbjsbg0pk58v .rough-node .label,#mq6cndsgbjsbg0pk58v .node .label,#mq6cndsgbjsbg0pk58v .image-shape .label,#mq6cndsgbjsbg0pk58v .icon-shape .label{text-align:center;}#mq6cndsgbjsbg0pk58v .node.clickable{cursor:pointer;}#mq6cndsgbjsbg0pk58v .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgbjsbg0pk58v .arrowheadPath{fill:lightgrey;}#mq6cndsgbjsbg0pk58v .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgbjsbg0pk58v .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgbjsbg0pk58v .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgbjsbg0pk58v .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgbjsbg0pk58v .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgbjsbg0pk58v .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgbjsbg0pk58v .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgbjsbg0pk58v .cluster text{fill:#F9FFFE;}#mq6cndsgbjsbg0pk58v .cluster span{color:#F9FFFE;}#mq6cndsgbjsbg0pk58v div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgbjsbg0pk58v .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgbjsbg0pk58v rect.text{fill:none;stroke-width:0;}#mq6cndsgbjsbg0pk58v .icon-shape,#mq6cndsgbjsbg0pk58v .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgbjsbg0pk58v .icon-shape p,#mq6cndsgbjsbg0pk58v .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgbjsbg0pk58v .icon-shape rect,#mq6cndsgbjsbg0pk58v .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgbjsbg0pk58v .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgbjsbg0pk58v .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgbjsbg0pk58v :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}是否是否否是日志产生方LogBus.init设置日志级别设置日志类型设置标题附加数据data附加异常errorsave创建虚拟线程格式化堆栈信息是否打印?格式化日志输出到控制台跳过打印日志级别>=WARN?必须保存日志logTrack.save?跳过保存处理日志超长截断处理异常信息获取所有LogBusInterface逐个调用save方法日志追踪设计 #mq6cndsgq15p5c1hbg9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgq15p5c1hbg9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgq15p5c1hbg9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgq15p5c1hbg9 .error-icon{fill:#a44141;}#mq6cndsgq15p5c1hbg9 .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgq15p5c1hbg9 .edge-thickness-normal{stroke-width:1px;}#mq6cndsgq15p5c1hbg9 .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgq15p5c1hbg9 .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgq15p5c1hbg9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgq15p5c1hbg9 .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgq15p5c1hbg9 .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgq15p5c1hbg9 .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgq15p5c1hbg9 .marker.cross{stroke:lightgrey;}#mq6cndsgq15p5c1hbg9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgq15p5c1hbg9 p{margin:0;}#mq6cndsgq15p5c1hbg9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgq15p5c1hbg9 .cluster-label text{fill:#F9FFFE;}#mq6cndsgq15p5c1hbg9 .cluster-label span{color:#F9FFFE;}#mq6cndsgq15p5c1hbg9 .cluster-label span p{background-color:transparent;}#mq6cndsgq15p5c1hbg9 .label text,#mq6cndsgq15p5c1hbg9 span{fill:#ccc;color:#ccc;}#mq6cndsgq15p5c1hbg9 .node rect,#mq6cndsgq15p5c1hbg9 .node circle,#mq6cndsgq15p5c1hbg9 .node ellipse,#mq6cndsgq15p5c1hbg9 .node polygon,#mq6cndsgq15p5c1hbg9 .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgq15p5c1hbg9 .rough-node .label text,#mq6cndsgq15p5c1hbg9 .node .label text,#mq6cndsgq15p5c1hbg9 .image-shape .label,#mq6cndsgq15p5c1hbg9 .icon-shape .label{text-anchor:middle;}#mq6cndsgq15p5c1hbg9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgq15p5c1hbg9 .rough-node .label,#mq6cndsgq15p5c1hbg9 .node .label,#mq6cndsgq15p5c1hbg9 .image-shape .label,#mq6cndsgq15p5c1hbg9 .icon-shape .label{text-align:center;}#mq6cndsgq15p5c1hbg9 .node.clickable{cursor:pointer;}#mq6cndsgq15p5c1hbg9 .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgq15p5c1hbg9 .arrowheadPath{fill:lightgrey;}#mq6cndsgq15p5c1hbg9 .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgq15p5c1hbg9 .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgq15p5c1hbg9 .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgq15p5c1hbg9 .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgq15p5c1hbg9 .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgq15p5c1hbg9 .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgq15p5c1hbg9 .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgq15p5c1hbg9 .cluster text{fill:#F9FFFE;}#mq6cndsgq15p5c1hbg9 .cluster span{color:#F9FFFE;}#mq6cndsgq15p5c1hbg9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgq15p5c1hbg9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgq15p5c1hbg9 rect.text{fill:none;stroke-width:0;}#mq6cndsgq15p5c1hbg9 .icon-shape,#mq6cndsgq15p5c1hbg9 .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgq15p5c1hbg9 .icon-shape p,#mq6cndsgq15p5c1hbg9 .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgq15p5c1hbg9 .icon-shape rect,#mq6cndsgq15p5c1hbg9 .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgq15p5c1hbg9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgq15p5c1hbg9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgq15p5c1hbg9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}HTTP请求到达LogTrackFilterOrder:100创建LogTrack生成唯一ID生成traceId设置type=MAIN设置save=true绑定到ScopedValue子线程/虚拟线程从父线程获取LogTrack创建子LogTrack继承traceId设置type=THREAD绑定到新ScopedValueLogBus使用LogTrackHolder获取日志类型枚举 日志类型 说明 OTHER 其他 VIRTUAL_THREAD 虚拟线程 REDIS Redis操作 MYBATIS MyBatis操作 MQ 消息队列 ELASTICSEARCH Elasticsearch操作 SENTINEL Sentinel操作 STORAGE 存储操作 OPT_LOG 操作日志 HTTP HTTP操作 HTTP_REQUEST HTTP请求 HTTP_RESPONSE HTTP响应 CLOUD_REQUEST 云端请求 CLOUD_RESPONSE 云端响应 CONTROLLER Controller异常 TASK 任务操作 JOB 定时任务 RISK 风险操作 3.3 缓存设计 Redis服务架构 #mq6cndsgbhyih8h0jid{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgbhyih8h0jid .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgbhyih8h0jid .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgbhyih8h0jid .error-icon{fill:#a44141;}#mq6cndsgbhyih8h0jid .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgbhyih8h0jid .edge-thickness-normal{stroke-width:1px;}#mq6cndsgbhyih8h0jid .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgbhyih8h0jid .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgbhyih8h0jid .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgbhyih8h0jid .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgbhyih8h0jid .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgbhyih8h0jid .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgbhyih8h0jid .marker.cross{stroke:lightgrey;}#mq6cndsgbhyih8h0jid svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgbhyih8h0jid p{margin:0;}#mq6cndsgbhyih8h0jid .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgbhyih8h0jid .cluster-label text{fill:#F9FFFE;}#mq6cndsgbhyih8h0jid .cluster-label span{color:#F9FFFE;}#mq6cndsgbhyih8h0jid .cluster-label span p{background-color:transparent;}#mq6cndsgbhyih8h0jid .label text,#mq6cndsgbhyih8h0jid span{fill:#ccc;color:#ccc;}#mq6cndsgbhyih8h0jid .node rect,#mq6cndsgbhyih8h0jid .node circle,#mq6cndsgbhyih8h0jid .node ellipse,#mq6cndsgbhyih8h0jid .node polygon,#mq6cndsgbhyih8h0jid .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgbhyih8h0jid .rough-node .label text,#mq6cndsgbhyih8h0jid .node .label text,#mq6cndsgbhyih8h0jid .image-shape .label,#mq6cndsgbhyih8h0jid .icon-shape .label{text-anchor:middle;}#mq6cndsgbhyih8h0jid .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgbhyih8h0jid .rough-node .label,#mq6cndsgbhyih8h0jid .node .label,#mq6cndsgbhyih8h0jid .image-shape .label,#mq6cndsgbhyih8h0jid .icon-shape .label{text-align:center;}#mq6cndsgbhyih8h0jid .node.clickable{cursor:pointer;}#mq6cndsgbhyih8h0jid .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgbhyih8h0jid .arrowheadPath{fill:lightgrey;}#mq6cndsgbhyih8h0jid .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgbhyih8h0jid .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgbhyih8h0jid .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgbhyih8h0jid .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgbhyih8h0jid .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgbhyih8h0jid .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgbhyih8h0jid .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgbhyih8h0jid .cluster text{fill:#F9FFFE;}#mq6cndsgbhyih8h0jid .cluster span{color:#F9FFFE;}#mq6cndsgbhyih8h0jid div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgbhyih8h0jid .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgbhyih8h0jid rect.text{fill:none;stroke-width:0;}#mq6cndsgbhyih8h0jid .icon-shape,#mq6cndsgbhyih8h0jid .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgbhyih8h0jid .icon-shape p,#mq6cndsgbhyih8h0jid .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgbhyih8h0jid .icon-shape rect,#mq6cndsgbhyih8h0jid .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgbhyih8h0jid .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgbhyih8h0jid .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgbhyih8h0jid :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}底层序列化RedisServiceString操作set / get / del / incrKey操作expire / persist / renamegetByPattern / getKey分布式锁tryLock / releaseLockLua脚本保证原子性Hash操作hashPut / hashGethashEntries / hashDeletehashExists原子操作setNx / hashPut带过期FastJSON2序列化String直接存储Object序列化为JSONStringRedisTemplate字符串操作RedisTemplate分布式锁DefaultRedisScriptLua脚本3.4 消息队列设计 消息总线架构 #mq6cndsgvj4mw6tvfyd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgvj4mw6tvfyd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgvj4mw6tvfyd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgvj4mw6tvfyd .error-icon{fill:#a44141;}#mq6cndsgvj4mw6tvfyd .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgvj4mw6tvfyd .edge-thickness-normal{stroke-width:1px;}#mq6cndsgvj4mw6tvfyd .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgvj4mw6tvfyd .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgvj4mw6tvfyd .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgvj4mw6tvfyd .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgvj4mw6tvfyd .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgvj4mw6tvfyd .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgvj4mw6tvfyd .marker.cross{stroke:lightgrey;}#mq6cndsgvj4mw6tvfyd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgvj4mw6tvfyd p{margin:0;}#mq6cndsgvj4mw6tvfyd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgvj4mw6tvfyd .cluster-label text{fill:#F9FFFE;}#mq6cndsgvj4mw6tvfyd .cluster-label span{color:#F9FFFE;}#mq6cndsgvj4mw6tvfyd .cluster-label span p{background-color:transparent;}#mq6cndsgvj4mw6tvfyd .label text,#mq6cndsgvj4mw6tvfyd span{fill:#ccc;color:#ccc;}#mq6cndsgvj4mw6tvfyd .node rect,#mq6cndsgvj4mw6tvfyd .node circle,#mq6cndsgvj4mw6tvfyd .node ellipse,#mq6cndsgvj4mw6tvfyd .node polygon,#mq6cndsgvj4mw6tvfyd .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgvj4mw6tvfyd .rough-node .label text,#mq6cndsgvj4mw6tvfyd .node .label text,#mq6cndsgvj4mw6tvfyd .image-shape .label,#mq6cndsgvj4mw6tvfyd .icon-shape .label{text-anchor:middle;}#mq6cndsgvj4mw6tvfyd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgvj4mw6tvfyd .rough-node .label,#mq6cndsgvj4mw6tvfyd .node .label,#mq6cndsgvj4mw6tvfyd .image-shape .label,#mq6cndsgvj4mw6tvfyd .icon-shape .label{text-align:center;}#mq6cndsgvj4mw6tvfyd .node.clickable{cursor:pointer;}#mq6cndsgvj4mw6tvfyd .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgvj4mw6tvfyd .arrowheadPath{fill:lightgrey;}#mq6cndsgvj4mw6tvfyd .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgvj4mw6tvfyd .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgvj4mw6tvfyd .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgvj4mw6tvfyd .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgvj4mw6tvfyd .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgvj4mw6tvfyd .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgvj4mw6tvfyd .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgvj4mw6tvfyd .cluster text{fill:#F9FFFE;}#mq6cndsgvj4mw6tvfyd .cluster span{color:#F9FFFE;}#mq6cndsgvj4mw6tvfyd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgvj4mw6tvfyd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgvj4mw6tvfyd rect.text{fill:none;stroke-width:0;}#mq6cndsgvj4mw6tvfyd .icon-shape,#mq6cndsgvj4mw6tvfyd .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgvj4mw6tvfyd .icon-shape p,#mq6cndsgvj4mw6tvfyd .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgvj4mw6tvfyd .icon-shape rect,#mq6cndsgvj4mw6tvfyd .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgvj4mw6tvfyd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgvj4mw6tvfyd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgvj4mw6tvfyd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}是否成功失败业务代码调用MqBus.push获取BaseMqHandle实现是否存在实现?调用push方法抛出异常RabbitMqHandle.push消息序列化MqMessageUtils.toRabbitTemplate发送RabbitMQ Broker消费者接收消息反序列化MqMessageUtils.fromBaseMessageHandlebaseHandleMessage业务处理消息确认ACKBaseErrorHandle错误处理消息初始化流程 #mq6cndsgsan56liqjw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgsan56liqjw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgsan56liqjw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgsan56liqjw .error-icon{fill:#a44141;}#mq6cndsgsan56liqjw .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgsan56liqjw .edge-thickness-normal{stroke-width:1px;}#mq6cndsgsan56liqjw .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgsan56liqjw .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgsan56liqjw .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgsan56liqjw .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgsan56liqjw .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgsan56liqjw .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgsan56liqjw .marker.cross{stroke:lightgrey;}#mq6cndsgsan56liqjw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgsan56liqjw p{margin:0;}#mq6cndsgsan56liqjw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgsan56liqjw .cluster-label text{fill:#F9FFFE;}#mq6cndsgsan56liqjw .cluster-label span{color:#F9FFFE;}#mq6cndsgsan56liqjw .cluster-label span p{background-color:transparent;}#mq6cndsgsan56liqjw .label text,#mq6cndsgsan56liqjw span{fill:#ccc;color:#ccc;}#mq6cndsgsan56liqjw .node rect,#mq6cndsgsan56liqjw .node circle,#mq6cndsgsan56liqjw .node ellipse,#mq6cndsgsan56liqjw .node polygon,#mq6cndsgsan56liqjw .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgsan56liqjw .rough-node .label text,#mq6cndsgsan56liqjw .node .label text,#mq6cndsgsan56liqjw .image-shape .label,#mq6cndsgsan56liqjw .icon-shape .label{text-anchor:middle;}#mq6cndsgsan56liqjw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgsan56liqjw .rough-node .label,#mq6cndsgsan56liqjw .node .label,#mq6cndsgsan56liqjw .image-shape .label,#mq6cndsgsan56liqjw .icon-shape .label{text-align:center;}#mq6cndsgsan56liqjw .node.clickable{cursor:pointer;}#mq6cndsgsan56liqjw .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgsan56liqjw .arrowheadPath{fill:lightgrey;}#mq6cndsgsan56liqjw .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgsan56liqjw .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgsan56liqjw .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgsan56liqjw .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgsan56liqjw .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgsan56liqjw .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgsan56liqjw .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgsan56liqjw .cluster text{fill:#F9FFFE;}#mq6cndsgsan56liqjw .cluster span{color:#F9FFFE;}#mq6cndsgsan56liqjw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgsan56liqjw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgsan56liqjw rect.text{fill:none;stroke-width:0;}#mq6cndsgsan56liqjw .icon-shape,#mq6cndsgsan56liqjw .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgsan56liqjw .icon-shape p,#mq6cndsgsan56liqjw .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgsan56liqjw .icon-shape rect,#mq6cndsgsan56liqjw .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgsan56liqjw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgsan56liqjw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgsan56liqjw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}应用启动InitMqApplicationRunner Order:50获取所有BaseMqHandle实现逐个调用initQueue初始化队列添加监听器addListen消息队列就绪3.5 存储设计 存储抽象架构 #mq6cndsgpnjtpssl6dl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgpnjtpssl6dl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgpnjtpssl6dl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgpnjtpssl6dl .error-icon{fill:#a44141;}#mq6cndsgpnjtpssl6dl .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgpnjtpssl6dl .edge-thickness-normal{stroke-width:1px;}#mq6cndsgpnjtpssl6dl .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgpnjtpssl6dl .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgpnjtpssl6dl .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgpnjtpssl6dl .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgpnjtpssl6dl .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgpnjtpssl6dl .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgpnjtpssl6dl .marker.cross{stroke:lightgrey;}#mq6cndsgpnjtpssl6dl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgpnjtpssl6dl p{margin:0;}#mq6cndsgpnjtpssl6dl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgpnjtpssl6dl .cluster-label text{fill:#F9FFFE;}#mq6cndsgpnjtpssl6dl .cluster-label span{color:#F9FFFE;}#mq6cndsgpnjtpssl6dl .cluster-label span p{background-color:transparent;}#mq6cndsgpnjtpssl6dl .label text,#mq6cndsgpnjtpssl6dl span{fill:#ccc;color:#ccc;}#mq6cndsgpnjtpssl6dl .node rect,#mq6cndsgpnjtpssl6dl .node circle,#mq6cndsgpnjtpssl6dl .node ellipse,#mq6cndsgpnjtpssl6dl .node polygon,#mq6cndsgpnjtpssl6dl .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgpnjtpssl6dl .rough-node .label text,#mq6cndsgpnjtpssl6dl .node .label text,#mq6cndsgpnjtpssl6dl .image-shape .label,#mq6cndsgpnjtpssl6dl .icon-shape .label{text-anchor:middle;}#mq6cndsgpnjtpssl6dl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgpnjtpssl6dl .rough-node .label,#mq6cndsgpnjtpssl6dl .node .label,#mq6cndsgpnjtpssl6dl .image-shape .label,#mq6cndsgpnjtpssl6dl .icon-shape .label{text-align:center;}#mq6cndsgpnjtpssl6dl .node.clickable{cursor:pointer;}#mq6cndsgpnjtpssl6dl .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgpnjtpssl6dl .arrowheadPath{fill:lightgrey;}#mq6cndsgpnjtpssl6dl .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgpnjtpssl6dl .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgpnjtpssl6dl .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgpnjtpssl6dl .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgpnjtpssl6dl .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgpnjtpssl6dl .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgpnjtpssl6dl .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgpnjtpssl6dl .cluster text{fill:#F9FFFE;}#mq6cndsgpnjtpssl6dl .cluster span{color:#F9FFFE;}#mq6cndsgpnjtpssl6dl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgpnjtpssl6dl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgpnjtpssl6dl rect.text{fill:none;stroke-width:0;}#mq6cndsgpnjtpssl6dl .icon-shape,#mq6cndsgpnjtpssl6dl .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgpnjtpssl6dl .icon-shape p,#mq6cndsgpnjtpssl6dl .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgpnjtpssl6dl .icon-shape rect,#mq6cndsgpnjtpssl6dl .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgpnjtpssl6dl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgpnjtpssl6dl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgpnjtpssl6dl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}配置层实现层存储接口实现实现type=filetype=s3StorageService接口StorageServiceFileImpl本地文件存储StorageServiceS3ImplS3对象存储StorageConfig存储类型配置FileStorageConfig文件存储配置S3StorageConfigS3配置+S3ClientStorageService接口方法: 方法 说明 exists(String key) 判断文件是否存在 save(String key, InputStream data) 保存文件 get(String key) 获取文件输入流 del(String key) 删除文件 3.6 数据脱敏设计 脱敏注解 #mq6cw7t8d3fwiruff5m{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cw7t8d3fwiruff5m .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cw7t8d3fwiruff5m .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cw7t8d3fwiruff5m .error-icon{fill:#a44141;}#mq6cw7t8d3fwiruff5m .error-text{fill:#ddd;stroke:#ddd;}#mq6cw7t8d3fwiruff5m .edge-thickness-normal{stroke-width:1px;}#mq6cw7t8d3fwiruff5m .edge-thickness-thick{stroke-width:3.5px;}#mq6cw7t8d3fwiruff5m .edge-pattern-solid{stroke-dasharray:0;}#mq6cw7t8d3fwiruff5m .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cw7t8d3fwiruff5m .edge-pattern-dashed{stroke-dasharray:3;}#mq6cw7t8d3fwiruff5m .edge-pattern-dotted{stroke-dasharray:2;}#mq6cw7t8d3fwiruff5m .marker{fill:lightgrey;stroke:lightgrey;}#mq6cw7t8d3fwiruff5m .marker.cross{stroke:lightgrey;}#mq6cw7t8d3fwiruff5m svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cw7t8d3fwiruff5m p{margin:0;}#mq6cw7t8d3fwiruff5m .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cw7t8d3fwiruff5m .cluster-label text{fill:#F9FFFE;}#mq6cw7t8d3fwiruff5m .cluster-label span{color:#F9FFFE;}#mq6cw7t8d3fwiruff5m .cluster-label span p{background-color:transparent;}#mq6cw7t8d3fwiruff5m .label text,#mq6cw7t8d3fwiruff5m span{fill:#ccc;color:#ccc;}#mq6cw7t8d3fwiruff5m .node rect,#mq6cw7t8d3fwiruff5m .node circle,#mq6cw7t8d3fwiruff5m .node ellipse,#mq6cw7t8d3fwiruff5m .node polygon,#mq6cw7t8d3fwiruff5m .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cw7t8d3fwiruff5m .rough-node .label text,#mq6cw7t8d3fwiruff5m .node .label text,#mq6cw7t8d3fwiruff5m .image-shape .label,#mq6cw7t8d3fwiruff5m .icon-shape .label{text-anchor:middle;}#mq6cw7t8d3fwiruff5m .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cw7t8d3fwiruff5m .rough-node .label,#mq6cw7t8d3fwiruff5m .node .label,#mq6cw7t8d3fwiruff5m .image-shape .label,#mq6cw7t8d3fwiruff5m .icon-shape .label{text-align:center;}#mq6cw7t8d3fwiruff5m .node.clickable{cursor:pointer;}#mq6cw7t8d3fwiruff5m .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cw7t8d3fwiruff5m .arrowheadPath{fill:lightgrey;}#mq6cw7t8d3fwiruff5m .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cw7t8d3fwiruff5m .flowchart-link{stroke:lightgrey;fill:none;}#mq6cw7t8d3fwiruff5m .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cw7t8d3fwiruff5m .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cw7t8d3fwiruff5m .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cw7t8d3fwiruff5m .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cw7t8d3fwiruff5m .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cw7t8d3fwiruff5m .cluster text{fill:#F9FFFE;}#mq6cw7t8d3fwiruff5m .cluster span{color:#F9FFFE;}#mq6cw7t8d3fwiruff5m div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cw7t8d3fwiruff5m .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cw7t8d3fwiruff5m rect.text{fill:none;stroke-width:0;}#mq6cw7t8d3fwiruff5m .icon-shape,#mq6cw7t8d3fwiruff5m .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cw7t8d3fwiruff5m .icon-shape p,#mq6cw7t8d3fwiruff5m .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cw7t8d3fwiruff5m .icon-shape rect,#mq6cw7t8d3fwiruff5m .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cw7t8d3fwiruff5m .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cw7t8d3fwiruff5m .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cw7t8d3fwiruff5m :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}CHINESE_NAMEID_CARDMOBILE_PHONEEMAILBANK_CARDPASSWORDADDRESSCUSTOM是否是否实体类字段标注 @MaskMaskType类型姓名脱敏张三 -> 张*身份证脱敏110101199001011234 -> 110101****1234手机号脱敏13812345678 -> 138****5678邮箱脱敏test @example.com -> t***@example.com银行卡脱敏密码脱敏全部替换为***地址脱敏自定义脱敏实现MaskCustom接口Jackson序列化MaskSerializerMaskIgnoreUtils是否忽略脱敏?返回原始值执行脱敏处理always=true?必须脱敏可通过Holder忽略3.7 过滤器链设计 #mq6cndsgf39ojtqwujh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgf39ojtqwujh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgf39ojtqwujh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgf39ojtqwujh .error-icon{fill:#a44141;}#mq6cndsgf39ojtqwujh .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgf39ojtqwujh .edge-thickness-normal{stroke-width:1px;}#mq6cndsgf39ojtqwujh .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgf39ojtqwujh .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgf39ojtqwujh .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgf39ojtqwujh .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgf39ojtqwujh .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgf39ojtqwujh .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgf39ojtqwujh .marker.cross{stroke:lightgrey;}#mq6cndsgf39ojtqwujh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgf39ojtqwujh p{margin:0;}#mq6cndsgf39ojtqwujh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgf39ojtqwujh .cluster-label text{fill:#F9FFFE;}#mq6cndsgf39ojtqwujh .cluster-label span{color:#F9FFFE;}#mq6cndsgf39ojtqwujh .cluster-label span p{background-color:transparent;}#mq6cndsgf39ojtqwujh .label text,#mq6cndsgf39ojtqwujh span{fill:#ccc;color:#ccc;}#mq6cndsgf39ojtqwujh .node rect,#mq6cndsgf39ojtqwujh .node circle,#mq6cndsgf39ojtqwujh .node ellipse,#mq6cndsgf39ojtqwujh .node polygon,#mq6cndsgf39ojtqwujh .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgf39ojtqwujh .rough-node .label text,#mq6cndsgf39ojtqwujh .node .label text,#mq6cndsgf39ojtqwujh .image-shape .label,#mq6cndsgf39ojtqwujh .icon-shape .label{text-anchor:middle;}#mq6cndsgf39ojtqwujh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgf39ojtqwujh .rough-node .label,#mq6cndsgf39ojtqwujh .node .label,#mq6cndsgf39ojtqwujh .image-shape .label,#mq6cndsgf39ojtqwujh .icon-shape .label{text-align:center;}#mq6cndsgf39ojtqwujh .node.clickable{cursor:pointer;}#mq6cndsgf39ojtqwujh .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgf39ojtqwujh .arrowheadPath{fill:lightgrey;}#mq6cndsgf39ojtqwujh .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgf39ojtqwujh .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgf39ojtqwujh .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgf39ojtqwujh .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgf39ojtqwujh .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgf39ojtqwujh .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgf39ojtqwujh .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgf39ojtqwujh .cluster text{fill:#F9FFFE;}#mq6cndsgf39ojtqwujh .cluster span{color:#F9FFFE;}#mq6cndsgf39ojtqwujh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgf39ojtqwujh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgf39ojtqwujh rect.text{fill:none;stroke-width:0;}#mq6cndsgf39ojtqwujh .icon-shape,#mq6cndsgf39ojtqwujh .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgf39ojtqwujh .icon-shape p,#mq6cndsgf39ojtqwujh .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgf39ojtqwujh .icon-shape rect,#mq6cndsgf39ojtqwujh .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgf39ojtqwujh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgf39ojtqwujh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgf39ojtqwujh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}是否HTTP请求Order:0SkipFilter路径在白名单中?跳过后续Filter标记跳过继续执行Order:100LogTrackFilter创建LogTrack绑定到ScopedValueOrder:101CommonFilter绑定CommonHolder到ScopedValueController处理请求3.8 任务总线设计 #mq6cndsg0t9xlk0k74ve{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsg0t9xlk0k74ve .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsg0t9xlk0k74ve .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsg0t9xlk0k74ve .error-icon{fill:#a44141;}#mq6cndsg0t9xlk0k74ve .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsg0t9xlk0k74ve .edge-thickness-normal{stroke-width:1px;}#mq6cndsg0t9xlk0k74ve .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsg0t9xlk0k74ve .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsg0t9xlk0k74ve .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsg0t9xlk0k74ve .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsg0t9xlk0k74ve .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsg0t9xlk0k74ve .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsg0t9xlk0k74ve .marker.cross{stroke:lightgrey;}#mq6cndsg0t9xlk0k74ve svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsg0t9xlk0k74ve p{margin:0;}#mq6cndsg0t9xlk0k74ve .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsg0t9xlk0k74ve .cluster-label text{fill:#F9FFFE;}#mq6cndsg0t9xlk0k74ve .cluster-label span{color:#F9FFFE;}#mq6cndsg0t9xlk0k74ve .cluster-label span p{background-color:transparent;}#mq6cndsg0t9xlk0k74ve .label text,#mq6cndsg0t9xlk0k74ve span{fill:#ccc;color:#ccc;}#mq6cndsg0t9xlk0k74ve .node rect,#mq6cndsg0t9xlk0k74ve .node circle,#mq6cndsg0t9xlk0k74ve .node ellipse,#mq6cndsg0t9xlk0k74ve .node polygon,#mq6cndsg0t9xlk0k74ve .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsg0t9xlk0k74ve .rough-node .label text,#mq6cndsg0t9xlk0k74ve .node .label text,#mq6cndsg0t9xlk0k74ve .image-shape .label,#mq6cndsg0t9xlk0k74ve .icon-shape .label{text-anchor:middle;}#mq6cndsg0t9xlk0k74ve .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsg0t9xlk0k74ve .rough-node .label,#mq6cndsg0t9xlk0k74ve .node .label,#mq6cndsg0t9xlk0k74ve .image-shape .label,#mq6cndsg0t9xlk0k74ve .icon-shape .label{text-align:center;}#mq6cndsg0t9xlk0k74ve .node.clickable{cursor:pointer;}#mq6cndsg0t9xlk0k74ve .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsg0t9xlk0k74ve .arrowheadPath{fill:lightgrey;}#mq6cndsg0t9xlk0k74ve .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsg0t9xlk0k74ve .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsg0t9xlk0k74ve .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsg0t9xlk0k74ve .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsg0t9xlk0k74ve .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsg0t9xlk0k74ve .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsg0t9xlk0k74ve .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsg0t9xlk0k74ve .cluster text{fill:#F9FFFE;}#mq6cndsg0t9xlk0k74ve .cluster span{color:#F9FFFE;}#mq6cndsg0t9xlk0k74ve div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsg0t9xlk0k74ve .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsg0t9xlk0k74ve rect.text{fill:none;stroke-width:0;}#mq6cndsg0t9xlk0k74ve .icon-shape,#mq6cndsg0t9xlk0k74ve .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsg0t9xlk0k74ve .icon-shape p,#mq6cndsg0t9xlk0k74ve .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsg0t9xlk0k74ve .icon-shape rect,#mq6cndsg0t9xlk0k74ve .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsg0t9xlk0k74ve .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsg0t9xlk0k74ve .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsg0t9xlk0k74ve :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}任务开始TaskBus.initcode / type / statusTaskBus.info设置描述信息TaskBus.time设置任务时间TaskBus.save获取所有TaskBusInterface逐个调用save方法任务信息持久化任务状态枚举: 状态 值 说明 ING 0 进行中 SUCCESS 1 成功 ERROR 2 失败 3.9 虚拟线程设计 #mq6cndsgyeaw70zb53{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgyeaw70zb53 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgyeaw70zb53 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgyeaw70zb53 .error-icon{fill:#a44141;}#mq6cndsgyeaw70zb53 .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgyeaw70zb53 .edge-thickness-normal{stroke-width:1px;}#mq6cndsgyeaw70zb53 .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgyeaw70zb53 .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgyeaw70zb53 .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgyeaw70zb53 .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgyeaw70zb53 .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgyeaw70zb53 .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgyeaw70zb53 .marker.cross{stroke:lightgrey;}#mq6cndsgyeaw70zb53 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgyeaw70zb53 p{margin:0;}#mq6cndsgyeaw70zb53 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgyeaw70zb53 .cluster-label text{fill:#F9FFFE;}#mq6cndsgyeaw70zb53 .cluster-label span{color:#F9FFFE;}#mq6cndsgyeaw70zb53 .cluster-label span p{background-color:transparent;}#mq6cndsgyeaw70zb53 .label text,#mq6cndsgyeaw70zb53 span{fill:#ccc;color:#ccc;}#mq6cndsgyeaw70zb53 .node rect,#mq6cndsgyeaw70zb53 .node circle,#mq6cndsgyeaw70zb53 .node ellipse,#mq6cndsgyeaw70zb53 .node polygon,#mq6cndsgyeaw70zb53 .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgyeaw70zb53 .rough-node .label text,#mq6cndsgyeaw70zb53 .node .label text,#mq6cndsgyeaw70zb53 .image-shape .label,#mq6cndsgyeaw70zb53 .icon-shape .label{text-anchor:middle;}#mq6cndsgyeaw70zb53 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgyeaw70zb53 .rough-node .label,#mq6cndsgyeaw70zb53 .node .label,#mq6cndsgyeaw70zb53 .image-shape .label,#mq6cndsgyeaw70zb53 .icon-shape .label{text-align:center;}#mq6cndsgyeaw70zb53 .node.clickable{cursor:pointer;}#mq6cndsgyeaw70zb53 .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgyeaw70zb53 .arrowheadPath{fill:lightgrey;}#mq6cndsgyeaw70zb53 .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgyeaw70zb53 .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgyeaw70zb53 .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgyeaw70zb53 .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgyeaw70zb53 .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgyeaw70zb53 .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgyeaw70zb53 .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgyeaw70zb53 .cluster text{fill:#F9FFFE;}#mq6cndsgyeaw70zb53 .cluster span{color:#F9FFFE;}#mq6cndsgyeaw70zb53 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgyeaw70zb53 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgyeaw70zb53 rect.text{fill:none;stroke-width:0;}#mq6cndsgyeaw70zb53 .icon-shape,#mq6cndsgyeaw70zb53 .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgyeaw70zb53 .icon-shape p,#mq6cndsgyeaw70zb53 .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgyeaw70zb53 .icon-shape rect,#mq6cndsgyeaw70zb53 .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgyeaw70zb53 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgyeaw70zb53 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgyeaw70zb53 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}VirtualThreadTaskUtilssimple方法简单虚拟线程执行execute方法带回调的虚拟线程执行创建虚拟线程执行Runnable任务返回CompletableFuture创建虚拟线程执行任务VirtualThreadTaskCallbackonSuccess / onError四、编码规范设计 4.1 命名规范 类命名 类型 命名规范 示例 配置类 Boot{Module}Configuration BootCacheRedisConfiguration 导入选择器 Boot{Module}ImportSelector BootCacheRedisImportSelector 配置属性 {功能}Config LogBusConfig, StorageConfig 工具类 {功能}Utils RedisUtils, TreeUtils, TimeUtils 监控类 {组件}Monitor RedisMonitor, MySqlMonitor 枚举类 {功能}Enums / {功能}Enum MySqlMonitorEnums, MaskType 异常类 Biz{类型}Error BizError, BizWarning, BizPublicKeyError 接口 {功能}Interface / Base{功能} LogBusInterface, BaseTaskType DTO {功能}Dto / {功能} Result, LogBody, TaskInfo, RunInfo 总线 {功能}Bus LogBus, TaskBus, MqBus 初始化 Init{功能} InitIp, InitMq, InitXxlJob 处理器 {功能}Handle / {功能}Handler RabbitMqHandle, DefaultMaskHandle 持有器 {功能}Holder LogTrackHolder, CommonHolder 注解 {功能} @Mask, @IgnoreXss 方法命名 操作 前缀 示例 初始化 init LogBus.init(), TaskBus.init() 保存 save logBus.save(), taskBus.save() 获取 get RedisService.get(), hashGet() 删除 del RedisService.del(), hashDelete() 判断 is/has/exists hashExists() 格式化 fmt fmtLog(), fmtStackTrace() 执行 do doSave() 4.2 注释规范 类注释格式 java 复制代码 /** * <p>Title : 类名称</p> * <p>Description : 类描述</p> * <p>DevelopTools : Idea_x64_v2026.1</p> * <p>DevelopSystem : macOS Sequoia 15.7.5</p> * <p>Company : org.xujun</p> * * @author : XuJun * @version : 5.0.0 * @date : 2026/01/01 09:30 */ 方法注释格式 java 复制代码 /** * 方法描述 * * @param param 参数说明 * @return 返回值说明 */ 4.3 代码风格 Lombok简化代码:使用 @Data、@Slf4j、@Resource 等注解减少样板代码 构造器注入:通过 @Resource 进行依赖注入 统一返回格式:所有Controller方法返回 Result<T> 统一异常处理:通过 @RestControllerAdvice 全局捕获异常 ScopedValue:使用JDK 21的ScopedValue替代ThreadLocal,用于线程间上下文传递 虚拟线程:日志保存、消息处理等使用虚拟线程异步执行 链式调用:LogBus、TaskBus、MqBus支持链式API调用 接口驱动:LogBusInterface、TaskBusInterface、BaseMqHandle、StorageService均通过接口定义,业务层实现 4.4 设计规范 单一职责:每个模块专注单一功能领域(缓存、日志、消息队列等) 开闭原则:通过接口(LogBusInterface、TaskBusInterface、BaseMqHandle)支持扩展,无需修改框架代码 依赖倒置:高层模块通过接口依赖低层实现,如StorageService接口抽象文件存储和S3存储 按需加载:通过ImportSelector实现模块按需自动装配,引入依赖即生效 总线模式:LogBus、TaskBus、MqBus统一采用总线模式,通过Spring容器获取所有接口实现 4.5 安全规范 XSS防护:@IgnoreXss 注解标记不需要XSS过滤的字段,Jackson的String反序列化器自动过滤XSS 数据脱敏:@Mask 注解在JSON序列化阶段自动脱敏敏感数据 SQL监控:MyBatis拦截器记录慢查询和SQL日志 参数验证:使用 @Valid 注解进行参数校验,全局异常处理器统一处理校验失败 五、项目依赖设计 5.1 核心框架依赖 依赖 版本 用途 Spring Boot 4.0.6 应用框架 Spring Framework 7.0.7 核心框架 Spring AMQP 4.0.3 RabbitMQ集成 Spring Data BOM 2025.1.5 Spring Data版本管理 Jakarta Servlet 6.1.0 Servlet规范 5.2 数据访问依赖 依赖 版本 用途 MyBatis 4.0.1 ORM框架 MyBatis-Plus 3.5.16 ORM增强工具 Druid 1.2.28 数据库连接池 MySQL Connector 9.7.0 MySQL驱动 Elasticsearch Client 9.2.8 Elasticsearch客户端 5.3 工具库依赖 依赖 版本 用途 Lombok 1.18.46 代码简化 MapStruct 1.6.3 对象映射 FastJSON2 2.0.60 JSON处理 Jackson 3.1.2 JSON序列化/反序列化 Commons Lang3 3.20.0 通用工具 Commons IO 2.22.0 IO工具 Commons Text 1.15.0 文本处理 5.4 扩展工具依赖 依赖 版本 用途 BouncyCastle 1.84 加密库 OSHI 6.12.0 系统监控 ip2region 3.3.7 IP地址定位 java-jwt 4.5.1 JWT令牌 Caffeine 3.2.3 本地缓存 AWS S3 SDK 2.42.41 S3对象存储 5.5 办公工具依赖 依赖 版本 用途 Fesod Sheet 2.0.1-incubating Excel处理 PDFBox 3.0.7 PDF处理 5.6 文档相关依赖 依赖 版本 用途 Knife4j 4.5.0 API文档增强 Swagger Annotations 2.2.48 OpenAPI注解 SpringDoc OpenAPI 3.0.3 OpenAPI文档生成 5.7 任务调度依赖 依赖 版本 用途 XXL-JOB 3.4.0 分布式任务调度 5.8 监控依赖 依赖 版本 用途 Spring Boot Admin 4.0.4 应用监控 5.9 其他工具依赖 依赖 版本 用途 Velocity 2.4.1 模板引擎 Easy Captcha 1.6.2 验证码生成 Jsoup 1.22.2 HTML解析 UserAgentUtils 1.21 浏览器标识解析 Pinyin4j 2.5.1 拼音转换 Thumbnailator 0.4.21 图片压缩 ZXing 3.5.4 二维码/条形码 mmseg4j 1.10.0 中文分词 5.10 POM继承链 #mq6cndsgvkegjsqo1x9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6cndsgvkegjsqo1x9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6cndsgvkegjsqo1x9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6cndsgvkegjsqo1x9 .error-icon{fill:#a44141;}#mq6cndsgvkegjsqo1x9 .error-text{fill:#ddd;stroke:#ddd;}#mq6cndsgvkegjsqo1x9 .edge-thickness-normal{stroke-width:1px;}#mq6cndsgvkegjsqo1x9 .edge-thickness-thick{stroke-width:3.5px;}#mq6cndsgvkegjsqo1x9 .edge-pattern-solid{stroke-dasharray:0;}#mq6cndsgvkegjsqo1x9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6cndsgvkegjsqo1x9 .edge-pattern-dashed{stroke-dasharray:3;}#mq6cndsgvkegjsqo1x9 .edge-pattern-dotted{stroke-dasharray:2;}#mq6cndsgvkegjsqo1x9 .marker{fill:lightgrey;stroke:lightgrey;}#mq6cndsgvkegjsqo1x9 .marker.cross{stroke:lightgrey;}#mq6cndsgvkegjsqo1x9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6cndsgvkegjsqo1x9 p{margin:0;}#mq6cndsgvkegjsqo1x9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6cndsgvkegjsqo1x9 .cluster-label text{fill:#F9FFFE;}#mq6cndsgvkegjsqo1x9 .cluster-label span{color:#F9FFFE;}#mq6cndsgvkegjsqo1x9 .cluster-label span p{background-color:transparent;}#mq6cndsgvkegjsqo1x9 .label text,#mq6cndsgvkegjsqo1x9 span{fill:#ccc;color:#ccc;}#mq6cndsgvkegjsqo1x9 .node rect,#mq6cndsgvkegjsqo1x9 .node circle,#mq6cndsgvkegjsqo1x9 .node ellipse,#mq6cndsgvkegjsqo1x9 .node polygon,#mq6cndsgvkegjsqo1x9 .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6cndsgvkegjsqo1x9 .rough-node .label text,#mq6cndsgvkegjsqo1x9 .node .label text,#mq6cndsgvkegjsqo1x9 .image-shape .label,#mq6cndsgvkegjsqo1x9 .icon-shape .label{text-anchor:middle;}#mq6cndsgvkegjsqo1x9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6cndsgvkegjsqo1x9 .rough-node .label,#mq6cndsgvkegjsqo1x9 .node .label,#mq6cndsgvkegjsqo1x9 .image-shape .label,#mq6cndsgvkegjsqo1x9 .icon-shape .label{text-align:center;}#mq6cndsgvkegjsqo1x9 .node.clickable{cursor:pointer;}#mq6cndsgvkegjsqo1x9 .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6cndsgvkegjsqo1x9 .arrowheadPath{fill:lightgrey;}#mq6cndsgvkegjsqo1x9 .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6cndsgvkegjsqo1x9 .flowchart-link{stroke:lightgrey;fill:none;}#mq6cndsgvkegjsqo1x9 .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgvkegjsqo1x9 .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6cndsgvkegjsqo1x9 .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgvkegjsqo1x9 .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6cndsgvkegjsqo1x9 .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6cndsgvkegjsqo1x9 .cluster text{fill:#F9FFFE;}#mq6cndsgvkegjsqo1x9 .cluster span{color:#F9FFFE;}#mq6cndsgvkegjsqo1x9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6cndsgvkegjsqo1x9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6cndsgvkegjsqo1x9 rect.text{fill:none;stroke-width:0;}#mq6cndsgvkegjsqo1x9 .icon-shape,#mq6cndsgvkegjsqo1x9 .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6cndsgvkegjsqo1x9 .icon-shape p,#mq6cndsgvkegjsqo1x9 .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6cndsgvkegjsqo1x9 .icon-shape rect,#mq6cndsgvkegjsqo1x9 .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6cndsgvkegjsqo1x9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6cndsgvkegjsqo1x9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6cndsgvkegjsqo1x9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}管理管理管理管理管理管理管理管理管理管理管理管理管理管理管理管理管理管理管理管理管理spring-boot-starter-parent4.0.6xtools-parent5.0.0xtools-parent-boot5.0.0xtools-boot5.0.0Spring Framework 7.0.7Jackson 3.1.2Spring AMQP 4.0.3Elasticsearch 9.2.8MySQL 9.7.0Lettuce 6.8.2RabbitMQ 5.27.1Tomcat 11.0.21FastJSON2 2.0.60BouncyCastle 1.84OSHI 6.12.0MapStruct 1.6.3Velocity 2.4.1S3 SDK 2.42.41ip2region 3.3.7MyBatis-Plus 3.5.16MyBatis 4.0.1Druid 1.2.28Knife4j 4.5.0XXL-JOB 3.4.0Spring Boot Admin 4.0.4六、技术选型说明 6.1 JDK 25 LTS版本:JDK 25是长期支持版本,提供长期稳定的安全更新 虚拟线程(Virtual Threads):项目大量使用虚拟线程进行异步操作,如日志保存、消息处理,大幅简化并发编程 ScopedValue:替代传统的ThreadLocal,用于线程间上下文传递(LogTrack、CommonHolder),性能更优且更安全 Record模式匹配:枚举类型使用record定义,支持简洁的模式匹配语法 Switch表达式:全局异常处理器等场景使用增强的switch表达式 文本块和String模板:日志格式化等场景使用文本块提升可读性 6.2 Spring Boot 4.0.6 Spring Framework版本:7.0.7,提供最新的核心功能 Jakarta EE 11:全面支持Jakarta EE 11规范(Jakarta Servlet 6.1.0) 自动配置:所有模块基于Spring Boot自动配置机制,引入依赖即生效 Actuator:内置应用监控端点 嵌入式容器:Tomcat 11.0.21 6.3 MyBatis-Plus 3.5.16 简化CRUD:通过BaseMapper提供通用增删改查 分页插件:内置分页拦截器,配合QueryUtils实现分页查询 代码生成:配合xtools-app-gen模块实现代码生成 SQL解析:通过mybatis-plus-jsqlparser支持SQL解析和优化 支持MyBatis版本:4.0.1 6.4 Elasticsearch 9.2.8 Spring Data Elasticsearch:通过Spring Data BOM 2025.1.5管理 全文搜索:用于日志检索和全文查询 高性能:基于Lucene的分布式搜索引擎 EsUtils:封装ES的GET/POST操作 EsQueryUtils:封装常用查询条件(matchPhrase、wildcard、timeRange) 6.5 Redis Spring Data Redis:通过Spring Boot 4.0.6管理(Lettuce 6.8.2客户端) RedisService:封装String、Hash、分布式锁等操作 FastJSON2序列化:使用FastJSON2进行Redis值的序列化/反序列化 分布式锁:基于RedisTemplate的setIfAbsent + Lua脚本实现 6.6 RabbitMQ Spring AMQP:4.0.3版本,提供RabbitMQ集成 RabbitMQ Client:5.27.1版本 消息总线:通过MqBus统一消息推送接口 消息编解码:MqMessageUtils提供消息的打包/解包 6.7 其他重要技术选型 技术 版本 选型原因 Jackson 3.1.2 Spring Boot默认JSON库(tools.jackson包),用于HTTP响应序列化 FastJSON2 2.0.60 高性能JSON库,用于Redis序列化和内部数据处理 Knife4j 4.5.0 增强Swagger UI,提供更友好的API文档界面 XXL-JOB 3.4.0 轻量级分布式任务调度平台 Druid 1.2.28 阿里巴巴数据库连接池,内置SQL监控和防火墙 ip2region 3.3.7 离线IP地址定位库,无需网络请求 BouncyCastle 1.84 Java加密扩展库,支持SM2/SM3等国密算法 OSHI 6.12.0 跨平台系统信息监控库 S3 SDK 2.42.41 AWS官方S3客户端,支持所有S3兼容存储 Spring Boot Admin 4.0.4 开源应用监控管理平台 文档版本:v1.0 编写日期:2026-06-09 项目版本:5.0.0 父POM版本:xtools-parent-boot:5.0.0 顶级父POM:xtools-parent:5.0.0 JDK版本:25 维护团队:xujun.org

优秀的个人博客,低调大师

xtools-app一款基于JDK25,SpringBoot4,SpringCloud的最新微服务脚手架

xtools-app 设计文档 开源地址: https://gitee.com/jun-xtools/xtools-app.git 一、功能和用途 1.1 项目概述 项目属性 值 项目名称 xtools-app 项目版本 1.0.0 父POM org.xujun:xtools-parent-cloud:5.0.0 JDK版本 25 项目描述 低调大师工具箱,基础应用模块,适配JDK25 组织 org.xujun (https://www.xujun.org) xtools-app 是一套基于 Spring Boot 构建的企业级基础应用平台,提供系统管理、代码生成、监控管理等核心功能。项目采用多模块架构,支持独立部署(Standalone)和微服务部署两种模式。 1.2 技术特点 采用最新的 JDK 25 版本,充分利用虚拟线程(Virtual Thread)、ScopedValue 等新特性 基于 Spring Boot 4.0.6 构建,支持自动配置和快速开发 集成 Spring Cloud Alibaba 2025.1.0.0 微服务框架 使用 MyBatis-Plus 3.5.16 简化数据访问层开发 集成 Elasticsearch 实现日志存储和检索(Spring Data BOM 2025.1.5) 支持 Nacos 3.1.1 服务注册与发现、Sentinel 1.8.9 流量控制和熔断降级 使用 Redis 实现分布式缓存和会话管理 使用 RabbitMQ(Spring AMQP 4.0.3)实现异步消息处理 支持 Knife4j 4.5.0 自动生成 API 文档 使用 SM2/SM3 国密算法保障密码安全 1.3 核心功能 #mq6disnaqhi0o8stwjd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disnaqhi0o8stwjd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disnaqhi0o8stwjd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disnaqhi0o8stwjd .error-icon{fill:#a44141;}#mq6disnaqhi0o8stwjd .error-text{fill:#ddd;stroke:#ddd;}#mq6disnaqhi0o8stwjd .edge-thickness-normal{stroke-width:1px;}#mq6disnaqhi0o8stwjd .edge-thickness-thick{stroke-width:3.5px;}#mq6disnaqhi0o8stwjd .edge-pattern-solid{stroke-dasharray:0;}#mq6disnaqhi0o8stwjd .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disnaqhi0o8stwjd .edge-pattern-dashed{stroke-dasharray:3;}#mq6disnaqhi0o8stwjd .edge-pattern-dotted{stroke-dasharray:2;}#mq6disnaqhi0o8stwjd .marker{fill:lightgrey;stroke:lightgrey;}#mq6disnaqhi0o8stwjd .marker.cross{stroke:lightgrey;}#mq6disnaqhi0o8stwjd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disnaqhi0o8stwjd p{margin:0;}#mq6disnaqhi0o8stwjd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disnaqhi0o8stwjd .cluster-label text{fill:#F9FFFE;}#mq6disnaqhi0o8stwjd .cluster-label span{color:#F9FFFE;}#mq6disnaqhi0o8stwjd .cluster-label span p{background-color:transparent;}#mq6disnaqhi0o8stwjd .label text,#mq6disnaqhi0o8stwjd span{fill:#ccc;color:#ccc;}#mq6disnaqhi0o8stwjd .node rect,#mq6disnaqhi0o8stwjd .node circle,#mq6disnaqhi0o8stwjd .node ellipse,#mq6disnaqhi0o8stwjd .node polygon,#mq6disnaqhi0o8stwjd .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disnaqhi0o8stwjd .rough-node .label text,#mq6disnaqhi0o8stwjd .node .label text,#mq6disnaqhi0o8stwjd .image-shape .label,#mq6disnaqhi0o8stwjd .icon-shape .label{text-anchor:middle;}#mq6disnaqhi0o8stwjd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disnaqhi0o8stwjd .rough-node .label,#mq6disnaqhi0o8stwjd .node .label,#mq6disnaqhi0o8stwjd .image-shape .label,#mq6disnaqhi0o8stwjd .icon-shape .label{text-align:center;}#mq6disnaqhi0o8stwjd .node.clickable{cursor:pointer;}#mq6disnaqhi0o8stwjd .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disnaqhi0o8stwjd .arrowheadPath{fill:lightgrey;}#mq6disnaqhi0o8stwjd .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disnaqhi0o8stwjd .flowchart-link{stroke:lightgrey;fill:none;}#mq6disnaqhi0o8stwjd .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disnaqhi0o8stwjd .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disnaqhi0o8stwjd .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disnaqhi0o8stwjd .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disnaqhi0o8stwjd .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disnaqhi0o8stwjd .cluster text{fill:#F9FFFE;}#mq6disnaqhi0o8stwjd .cluster span{color:#F9FFFE;}#mq6disnaqhi0o8stwjd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disnaqhi0o8stwjd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disnaqhi0o8stwjd rect.text{fill:none;stroke-width:0;}#mq6disnaqhi0o8stwjd .icon-shape,#mq6disnaqhi0o8stwjd .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disnaqhi0o8stwjd .icon-shape p,#mq6disnaqhi0o8stwjd .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disnaqhi0o8stwjd .icon-shape rect,#mq6disnaqhi0o8stwjd .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disnaqhi0o8stwjd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disnaqhi0o8stwjd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disnaqhi0o8stwjd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}认证安全模块认证模块Token管理、白名单风控模块IP风险、URI风险文件模块文件操作、S3存储参数模块系统参数工具定时任务模块动态定时任务标签模块Swagger标签拦截监控模块监控客户端Boot Admin Client健康检查Health Controller监控服务端Boot Admin Server公共模块缓存模块Redis缓存、AOP日志远程调用HTTP服务调用、拦截器JAR管理JAR加载、初始化日志总线事件发布、异步存储日志过滤HTTP请求拦截、请求响应日志消息队列RabbitMQ、错误重试任务调度异步任务总线、任务记录限流降级Sentinel、BlockException处理通用配置公共配置项代码生成模块数据源管理多数据源、连接测试表结构管理数据库同步、字段配置代码生成Velocity模板、前后端代码代码预览下载在线预览、ZIP下载系统管理模块用户管理CRUD 、角色分配、状态管理角色管理权限分配、菜单分配菜单管理树形结构、动态加载、接口权限部门管理树形结构、人员管理字典管理类型管理、项管理、Excel导入导出日志管理操作日志、系统日志、Elasticsearch存储任务管理定时任务配置、任务监控、异步任务系统监控Redis监控、MySQL监控、ES监控JAR管理JAR加载、依赖缓存文件管理上传下载、S3存储、生命周期管理公告管理公告发布、用户公告参数管理系统参数配置、参数缓存风控管理IP黑名单、URI黑名单、本地缓存地址管理IP归属地查询、地址缓存更新历史数据变更记录1.4 功能关系图 #mq6disobaoyc7r4t0av{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobaoyc7r4t0av .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobaoyc7r4t0av .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobaoyc7r4t0av .error-icon{fill:#a44141;}#mq6disobaoyc7r4t0av .error-text{fill:#ddd;stroke:#ddd;}#mq6disobaoyc7r4t0av .edge-thickness-normal{stroke-width:1px;}#mq6disobaoyc7r4t0av .edge-thickness-thick{stroke-width:3.5px;}#mq6disobaoyc7r4t0av .edge-pattern-solid{stroke-dasharray:0;}#mq6disobaoyc7r4t0av .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobaoyc7r4t0av .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobaoyc7r4t0av .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobaoyc7r4t0av .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobaoyc7r4t0av .marker.cross{stroke:lightgrey;}#mq6disobaoyc7r4t0av svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobaoyc7r4t0av p{margin:0;}#mq6disobaoyc7r4t0av .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disobaoyc7r4t0av .cluster-label text{fill:#F9FFFE;}#mq6disobaoyc7r4t0av .cluster-label span{color:#F9FFFE;}#mq6disobaoyc7r4t0av .cluster-label span p{background-color:transparent;}#mq6disobaoyc7r4t0av .label text,#mq6disobaoyc7r4t0av span{fill:#ccc;color:#ccc;}#mq6disobaoyc7r4t0av .node rect,#mq6disobaoyc7r4t0av .node circle,#mq6disobaoyc7r4t0av .node ellipse,#mq6disobaoyc7r4t0av .node polygon,#mq6disobaoyc7r4t0av .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disobaoyc7r4t0av .rough-node .label text,#mq6disobaoyc7r4t0av .node .label text,#mq6disobaoyc7r4t0av .image-shape .label,#mq6disobaoyc7r4t0av .icon-shape .label{text-anchor:middle;}#mq6disobaoyc7r4t0av .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disobaoyc7r4t0av .rough-node .label,#mq6disobaoyc7r4t0av .node .label,#mq6disobaoyc7r4t0av .image-shape .label,#mq6disobaoyc7r4t0av .icon-shape .label{text-align:center;}#mq6disobaoyc7r4t0av .node.clickable{cursor:pointer;}#mq6disobaoyc7r4t0av .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disobaoyc7r4t0av .arrowheadPath{fill:lightgrey;}#mq6disobaoyc7r4t0av .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disobaoyc7r4t0av .flowchart-link{stroke:lightgrey;fill:none;}#mq6disobaoyc7r4t0av .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobaoyc7r4t0av .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disobaoyc7r4t0av .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobaoyc7r4t0av .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disobaoyc7r4t0av .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disobaoyc7r4t0av .cluster text{fill:#F9FFFE;}#mq6disobaoyc7r4t0av .cluster span{color:#F9FFFE;}#mq6disobaoyc7r4t0av div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disobaoyc7r4t0av .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disobaoyc7r4t0av rect.text{fill:none;stroke-width:0;}#mq6disobaoyc7r4t0av .icon-shape,#mq6disobaoyc7r4t0av .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobaoyc7r4t0av .icon-shape p,#mq6disobaoyc7r4t0av .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disobaoyc7r4t0av .icon-shape rect,#mq6disobaoyc7r4t0av .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobaoyc7r4t0av .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disobaoyc7r4t0av .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disobaoyc7r4t0av :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}用户登录认证菜单访问数据操作SM2加密传输认证授权Token管理Redis存储权限验证RBAC模型角色操作日志消息队列ElasticsearchRedis缓存代码生成数据库系统监控RedisMySQL1.5 功能层次图 #mq6disobvm5opy0ckn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobvm5opy0ckn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobvm5opy0ckn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobvm5opy0ckn .error-icon{fill:#a44141;}#mq6disobvm5opy0ckn .error-text{fill:#ddd;stroke:#ddd;}#mq6disobvm5opy0ckn .edge-thickness-normal{stroke-width:1px;}#mq6disobvm5opy0ckn .edge-thickness-thick{stroke-width:3.5px;}#mq6disobvm5opy0ckn .edge-pattern-solid{stroke-dasharray:0;}#mq6disobvm5opy0ckn .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobvm5opy0ckn .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobvm5opy0ckn .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobvm5opy0ckn .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobvm5opy0ckn .marker.cross{stroke:lightgrey;}#mq6disobvm5opy0ckn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobvm5opy0ckn p{margin:0;}#mq6disobvm5opy0ckn .edge{stroke-width:3;}#mq6disobvm5opy0ckn .section--1 rect,#mq6disobvm5opy0ckn .section--1 path,#mq6disobvm5opy0ckn .section--1 circle,#mq6disobvm5opy0ckn .section--1 polygon,#mq6disobvm5opy0ckn .section--1 path{fill:#1f2020;}#mq6disobvm5opy0ckn .section--1 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon--1{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge--1{stroke:#1f2020;}#mq6disobvm5opy0ckn .edge-depth--1{stroke-width:17;}#mq6disobvm5opy0ckn .section--1 line{stroke:#e0dfdf;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-0 rect,#mq6disobvm5opy0ckn .section-0 path,#mq6disobvm5opy0ckn .section-0 circle,#mq6disobvm5opy0ckn .section-0 polygon,#mq6disobvm5opy0ckn .section-0 path{fill:#0b0000;}#mq6disobvm5opy0ckn .section-0 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-0{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-0{stroke:#0b0000;}#mq6disobvm5opy0ckn .edge-depth-0{stroke-width:14;}#mq6disobvm5opy0ckn .section-0 line{stroke:#f4ffff;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-1 rect,#mq6disobvm5opy0ckn .section-1 path,#mq6disobvm5opy0ckn .section-1 circle,#mq6disobvm5opy0ckn .section-1 polygon,#mq6disobvm5opy0ckn .section-1 path{fill:#4d1037;}#mq6disobvm5opy0ckn .section-1 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-1{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-1{stroke:#4d1037;}#mq6disobvm5opy0ckn .edge-depth-1{stroke-width:11;}#mq6disobvm5opy0ckn .section-1 line{stroke:#b2efc8;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-2 rect,#mq6disobvm5opy0ckn .section-2 path,#mq6disobvm5opy0ckn .section-2 circle,#mq6disobvm5opy0ckn .section-2 polygon,#mq6disobvm5opy0ckn .section-2 path{fill:#3f5258;}#mq6disobvm5opy0ckn .section-2 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-2{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-2{stroke:#3f5258;}#mq6disobvm5opy0ckn .edge-depth-2{stroke-width:8;}#mq6disobvm5opy0ckn .section-2 line{stroke:#c0ada7;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-3 rect,#mq6disobvm5opy0ckn .section-3 path,#mq6disobvm5opy0ckn .section-3 circle,#mq6disobvm5opy0ckn .section-3 polygon,#mq6disobvm5opy0ckn .section-3 path{fill:#4f2f1b;}#mq6disobvm5opy0ckn .section-3 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-3{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-3{stroke:#4f2f1b;}#mq6disobvm5opy0ckn .edge-depth-3{stroke-width:5;}#mq6disobvm5opy0ckn .section-3 line{stroke:#b0d0e4;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-4 rect,#mq6disobvm5opy0ckn .section-4 path,#mq6disobvm5opy0ckn .section-4 circle,#mq6disobvm5opy0ckn .section-4 polygon,#mq6disobvm5opy0ckn .section-4 path{fill:#6e0a0a;}#mq6disobvm5opy0ckn .section-4 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-4{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-4{stroke:#6e0a0a;}#mq6disobvm5opy0ckn .edge-depth-4{stroke-width:2;}#mq6disobvm5opy0ckn .section-4 line{stroke:#91f5f5;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-5 rect,#mq6disobvm5opy0ckn .section-5 path,#mq6disobvm5opy0ckn .section-5 circle,#mq6disobvm5opy0ckn .section-5 polygon,#mq6disobvm5opy0ckn .section-5 path{fill:#3b0048;}#mq6disobvm5opy0ckn .section-5 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-5{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-5{stroke:#3b0048;}#mq6disobvm5opy0ckn .edge-depth-5{stroke-width:-1;}#mq6disobvm5opy0ckn .section-5 line{stroke:#c4ffb7;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-6 rect,#mq6disobvm5opy0ckn .section-6 path,#mq6disobvm5opy0ckn .section-6 circle,#mq6disobvm5opy0ckn .section-6 polygon,#mq6disobvm5opy0ckn .section-6 path{fill:#995a01;}#mq6disobvm5opy0ckn .section-6 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-6{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-6{stroke:#995a01;}#mq6disobvm5opy0ckn .edge-depth-6{stroke-width:-4;}#mq6disobvm5opy0ckn .section-6 line{stroke:#66a5fe;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-7 rect,#mq6disobvm5opy0ckn .section-7 path,#mq6disobvm5opy0ckn .section-7 circle,#mq6disobvm5opy0ckn .section-7 polygon,#mq6disobvm5opy0ckn .section-7 path{fill:#154706;}#mq6disobvm5opy0ckn .section-7 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-7{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-7{stroke:#154706;}#mq6disobvm5opy0ckn .edge-depth-7{stroke-width:-7;}#mq6disobvm5opy0ckn .section-7 line{stroke:#eab8f9;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-8 rect,#mq6disobvm5opy0ckn .section-8 path,#mq6disobvm5opy0ckn .section-8 circle,#mq6disobvm5opy0ckn .section-8 polygon,#mq6disobvm5opy0ckn .section-8 path{fill:#161722;}#mq6disobvm5opy0ckn .section-8 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-8{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-8{stroke:#161722;}#mq6disobvm5opy0ckn .edge-depth-8{stroke-width:-10;}#mq6disobvm5opy0ckn .section-8 line{stroke:#e9e8dd;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-9 rect,#mq6disobvm5opy0ckn .section-9 path,#mq6disobvm5opy0ckn .section-9 circle,#mq6disobvm5opy0ckn .section-9 polygon,#mq6disobvm5opy0ckn .section-9 path{fill:#00296f;}#mq6disobvm5opy0ckn .section-9 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-9{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-9{stroke:#00296f;}#mq6disobvm5opy0ckn .edge-depth-9{stroke-width:-13;}#mq6disobvm5opy0ckn .section-9 line{stroke:#ffd690;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-10 rect,#mq6disobvm5opy0ckn .section-10 path,#mq6disobvm5opy0ckn .section-10 circle,#mq6disobvm5opy0ckn .section-10 polygon,#mq6disobvm5opy0ckn .section-10 path{fill:#01629c;}#mq6disobvm5opy0ckn .section-10 text{fill:lightgrey;}#mq6disobvm5opy0ckn .node-icon-10{font-size:40px;color:lightgrey;}#mq6disobvm5opy0ckn .section-edge-10{stroke:#01629c;}#mq6disobvm5opy0ckn .edge-depth-10{stroke-width:-16;}#mq6disobvm5opy0ckn .section-10 line{stroke:#fe9d63;stroke-width:3;}#mq6disobvm5opy0ckn .disabled,#mq6disobvm5opy0ckn .disabled circle,#mq6disobvm5opy0ckn .disabled text{fill:lightgray;}#mq6disobvm5opy0ckn .disabled text{fill:#efefef;}#mq6disobvm5opy0ckn .section-root rect,#mq6disobvm5opy0ckn .section-root path,#mq6disobvm5opy0ckn .section-root circle,#mq6disobvm5opy0ckn .section-root polygon{fill:hsl(180, 1.5873015873%, 48.3529411765%);}#mq6disobvm5opy0ckn .section-root text{fill:#2c2c2c;}#mq6disobvm5opy0ckn .section-root span{color:#2c2c2c;}#mq6disobvm5opy0ckn .section-2 span{color:#2c2c2c;}#mq6disobvm5opy0ckn .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mq6disobvm5opy0ckn .edge{fill:none;}#mq6disobvm5opy0ckn .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mq6disobvm5opy0ckn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}xtools-app基础应用平台系统管理用户管理增删改查角色分配密码管理状态管理数据脱敏角色管理角色配置菜单分配菜单管理树形结构动态加载接口权限配置部门管理树形结构字典管理类型管理项管理Excel导入导出日志管理操作日志系统日志ES存储检索任务管理定时任务配置任务执行监控系统监控Redis监控MySQL监控ES监控文件管理上传下载S3存储生命周期管理参数管理系统参数配置风控管理IP黑名单URI黑名单代码生成数据源管理多数据源配置连接测试表结构管理数据库同步字段配置代码生成Velocity模板前后端代码代码预览下载在线预览ZIP打包下载公共能力缓存管理Redis缓存缓存枚举AOP日志记录远程调用HTTP服务调用日志处理HTTP请求日志日志总线MQ异步存储消息队列RabbitMQ错误重试机制任务调度异步任务总线动态定时任务限流降级Sentinel集成二、项目结构设计 2.1 整体架构 #mq6disoby53mnb5emq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disoby53mnb5emq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disoby53mnb5emq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disoby53mnb5emq .error-icon{fill:#a44141;}#mq6disoby53mnb5emq .error-text{fill:#ddd;stroke:#ddd;}#mq6disoby53mnb5emq .edge-thickness-normal{stroke-width:1px;}#mq6disoby53mnb5emq .edge-thickness-thick{stroke-width:3.5px;}#mq6disoby53mnb5emq .edge-pattern-solid{stroke-dasharray:0;}#mq6disoby53mnb5emq .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disoby53mnb5emq .edge-pattern-dashed{stroke-dasharray:3;}#mq6disoby53mnb5emq .edge-pattern-dotted{stroke-dasharray:2;}#mq6disoby53mnb5emq .marker{fill:lightgrey;stroke:lightgrey;}#mq6disoby53mnb5emq .marker.cross{stroke:lightgrey;}#mq6disoby53mnb5emq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disoby53mnb5emq p{margin:0;}#mq6disoby53mnb5emq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disoby53mnb5emq .cluster-label text{fill:#F9FFFE;}#mq6disoby53mnb5emq .cluster-label span{color:#F9FFFE;}#mq6disoby53mnb5emq .cluster-label span p{background-color:transparent;}#mq6disoby53mnb5emq .label text,#mq6disoby53mnb5emq span{fill:#ccc;color:#ccc;}#mq6disoby53mnb5emq .node rect,#mq6disoby53mnb5emq .node circle,#mq6disoby53mnb5emq .node ellipse,#mq6disoby53mnb5emq .node polygon,#mq6disoby53mnb5emq .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disoby53mnb5emq .rough-node .label text,#mq6disoby53mnb5emq .node .label text,#mq6disoby53mnb5emq .image-shape .label,#mq6disoby53mnb5emq .icon-shape .label{text-anchor:middle;}#mq6disoby53mnb5emq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disoby53mnb5emq .rough-node .label,#mq6disoby53mnb5emq .node .label,#mq6disoby53mnb5emq .image-shape .label,#mq6disoby53mnb5emq .icon-shape .label{text-align:center;}#mq6disoby53mnb5emq .node.clickable{cursor:pointer;}#mq6disoby53mnb5emq .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disoby53mnb5emq .arrowheadPath{fill:lightgrey;}#mq6disoby53mnb5emq .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disoby53mnb5emq .flowchart-link{stroke:lightgrey;fill:none;}#mq6disoby53mnb5emq .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disoby53mnb5emq .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disoby53mnb5emq .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disoby53mnb5emq .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disoby53mnb5emq .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disoby53mnb5emq .cluster text{fill:#F9FFFE;}#mq6disoby53mnb5emq .cluster span{color:#F9FFFE;}#mq6disoby53mnb5emq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disoby53mnb5emq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disoby53mnb5emq rect.text{fill:none;stroke-width:0;}#mq6disoby53mnb5emq .icon-shape,#mq6disoby53mnb5emq .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disoby53mnb5emq .icon-shape p,#mq6disoby53mnb5emq .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disoby53mnb5emq .icon-shape rect,#mq6disoby53mnb5emq .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disoby53mnb5emq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disoby53mnb5emq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disoby53mnb5emq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}聚合聚合聚合聚合xtools-app父模块 v1.0.0xtools-app-common公共模块xtools-app-sys系统管理模块xtools-app-gen代码生成模块xtools-app-monitor监控模块xtools-app-standalone独立部署模块common-cache缓存模块common-call远程调用模块common-config通用配置common-jarJAR管理模块common-job任务模块common-log日志模块common-mq消息队列模块common-sentinel限流降级模块common-task异步任务模块common-log-bus日志总线common-log-filter日志过滤器sys-api系统API接口sys-auth认证授权sys-biz系统业务逻辑sys-boot系统启动模块sys-call系统远程调用sys-file文件管理sys-file-web文件Web接口sys-log-bus-elasticsearchES日志存储sys-param参数管理sys-risk风控管理sys-scheduled定时任务sys-tag标签管理gen-biz代码生成业务gen-boot代码生成启动monitor-boot监控服务端monitor-client监控客户端monitor-health健康检查2.2 分层架构 #mq6disob27tb9nfnb3k{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disob27tb9nfnb3k .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disob27tb9nfnb3k .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disob27tb9nfnb3k .error-icon{fill:#a44141;}#mq6disob27tb9nfnb3k .error-text{fill:#ddd;stroke:#ddd;}#mq6disob27tb9nfnb3k .edge-thickness-normal{stroke-width:1px;}#mq6disob27tb9nfnb3k .edge-thickness-thick{stroke-width:3.5px;}#mq6disob27tb9nfnb3k .edge-pattern-solid{stroke-dasharray:0;}#mq6disob27tb9nfnb3k .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disob27tb9nfnb3k .edge-pattern-dashed{stroke-dasharray:3;}#mq6disob27tb9nfnb3k .edge-pattern-dotted{stroke-dasharray:2;}#mq6disob27tb9nfnb3k .marker{fill:lightgrey;stroke:lightgrey;}#mq6disob27tb9nfnb3k .marker.cross{stroke:lightgrey;}#mq6disob27tb9nfnb3k svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disob27tb9nfnb3k p{margin:0;}#mq6disob27tb9nfnb3k .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disob27tb9nfnb3k .cluster-label text{fill:#F9FFFE;}#mq6disob27tb9nfnb3k .cluster-label span{color:#F9FFFE;}#mq6disob27tb9nfnb3k .cluster-label span p{background-color:transparent;}#mq6disob27tb9nfnb3k .label text,#mq6disob27tb9nfnb3k span{fill:#ccc;color:#ccc;}#mq6disob27tb9nfnb3k .node rect,#mq6disob27tb9nfnb3k .node circle,#mq6disob27tb9nfnb3k .node ellipse,#mq6disob27tb9nfnb3k .node polygon,#mq6disob27tb9nfnb3k .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disob27tb9nfnb3k .rough-node .label text,#mq6disob27tb9nfnb3k .node .label text,#mq6disob27tb9nfnb3k .image-shape .label,#mq6disob27tb9nfnb3k .icon-shape .label{text-anchor:middle;}#mq6disob27tb9nfnb3k .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disob27tb9nfnb3k .rough-node .label,#mq6disob27tb9nfnb3k .node .label,#mq6disob27tb9nfnb3k .image-shape .label,#mq6disob27tb9nfnb3k .icon-shape .label{text-align:center;}#mq6disob27tb9nfnb3k .node.clickable{cursor:pointer;}#mq6disob27tb9nfnb3k .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disob27tb9nfnb3k .arrowheadPath{fill:lightgrey;}#mq6disob27tb9nfnb3k .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disob27tb9nfnb3k .flowchart-link{stroke:lightgrey;fill:none;}#mq6disob27tb9nfnb3k .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disob27tb9nfnb3k .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disob27tb9nfnb3k .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disob27tb9nfnb3k .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disob27tb9nfnb3k .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disob27tb9nfnb3k .cluster text{fill:#F9FFFE;}#mq6disob27tb9nfnb3k .cluster span{color:#F9FFFE;}#mq6disob27tb9nfnb3k div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disob27tb9nfnb3k .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disob27tb9nfnb3k rect.text{fill:none;stroke-width:0;}#mq6disob27tb9nfnb3k .icon-shape,#mq6disob27tb9nfnb3k .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disob27tb9nfnb3k .icon-shape p,#mq6disob27tb9nfnb3k .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disob27tb9nfnb3k .icon-shape rect,#mq6disob27tb9nfnb3k .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disob27tb9nfnb3k .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disob27tb9nfnb3k .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disob27tb9nfnb3k :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}基础设施层Mapper层Service层Controller层过滤器层异步异步存储HttpLogFilter请求响应日志Order: 200AuthFilter认证授权Order: 201接收HTTP请求参数验证 @Valid调用Service层返回统一响应 Result实现业务逻辑事务控制调用Mapper层对象转换 Convert缓存操作 Cache数据库访问SQL执行结果映射Redis缓存RabbitMQ消息ElasticsearchS3文件存储MySQL数据库2.3 模块职责 层级 职责 说明 过滤器层 请求拦截 HttpLogFilter 记录请求响应日志,AuthFilter 验证认证授权 Controller层 接口暴露 接收请求、参数验证、调用Service、返回统一Result响应 Service层 业务逻辑 事务控制、业务验证、调用Mapper、对象转换 Service Base层 基础CRUD 封装通用增删改查,减少重复代码 Mapper层 数据访问 MyBatis-Plus Mapper,数据库操作 Entity层 实体对象 数据库表映射实体 DTO层 数据传输 请求DTO(req)、响应DTO(resp)、Excel DTO Convert层 对象转换 MapStruct 转换器,Entity <-> DTO Config层 配置管理 模块配置、白名单、初始化 MQ层 消息处理 RabbitMQ 消息消费者 Job层 定时任务 BaseJob 定时任务实现 Utils层 工具方法 密码加密、数据源工具等 AOP层 切面增强 Redis操作日志、存储操作日志 2.4 包结构设计 复制代码 xtools.app.{module} ├── controller # 控制器 ├── service # 服务接口 │ ├── base # 基础CRUD服务接口 │ └── impl # 服务实现 ├── mapper # MyBatis Mapper ├── model │ ├── entity # 实体类 │ ├── dto │ │ ├── req # 请求DTO(AddReq, UpdateReq, PageReq) │ │ ├── resp # 响应DTO │ │ └── excel # Excel导入导出DTO │ └── vo # 视图对象 ├── convert # MapStruct 对象转换器 ├── config # 模块配置 ├── utils # 工具类 ├── mq # RabbitMQ 消息消费者 ├── job # 定时任务 ├── enums # 枚举类 ├── init # 初始化(ApplicationRunner) └── aop # AOP切面 2.5 系统边界视图 #mq6disob13pvp6w4wy7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disob13pvp6w4wy7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disob13pvp6w4wy7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disob13pvp6w4wy7 .error-icon{fill:#a44141;}#mq6disob13pvp6w4wy7 .error-text{fill:#ddd;stroke:#ddd;}#mq6disob13pvp6w4wy7 .edge-thickness-normal{stroke-width:1px;}#mq6disob13pvp6w4wy7 .edge-thickness-thick{stroke-width:3.5px;}#mq6disob13pvp6w4wy7 .edge-pattern-solid{stroke-dasharray:0;}#mq6disob13pvp6w4wy7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disob13pvp6w4wy7 .edge-pattern-dashed{stroke-dasharray:3;}#mq6disob13pvp6w4wy7 .edge-pattern-dotted{stroke-dasharray:2;}#mq6disob13pvp6w4wy7 .marker{fill:lightgrey;stroke:lightgrey;}#mq6disob13pvp6w4wy7 .marker.cross{stroke:lightgrey;}#mq6disob13pvp6w4wy7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disob13pvp6w4wy7 p{margin:0;}#mq6disob13pvp6w4wy7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disob13pvp6w4wy7 .cluster-label text{fill:#F9FFFE;}#mq6disob13pvp6w4wy7 .cluster-label span{color:#F9FFFE;}#mq6disob13pvp6w4wy7 .cluster-label span p{background-color:transparent;}#mq6disob13pvp6w4wy7 .label text,#mq6disob13pvp6w4wy7 span{fill:#ccc;color:#ccc;}#mq6disob13pvp6w4wy7 .node rect,#mq6disob13pvp6w4wy7 .node circle,#mq6disob13pvp6w4wy7 .node ellipse,#mq6disob13pvp6w4wy7 .node polygon,#mq6disob13pvp6w4wy7 .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disob13pvp6w4wy7 .rough-node .label text,#mq6disob13pvp6w4wy7 .node .label text,#mq6disob13pvp6w4wy7 .image-shape .label,#mq6disob13pvp6w4wy7 .icon-shape .label{text-anchor:middle;}#mq6disob13pvp6w4wy7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disob13pvp6w4wy7 .rough-node .label,#mq6disob13pvp6w4wy7 .node .label,#mq6disob13pvp6w4wy7 .image-shape .label,#mq6disob13pvp6w4wy7 .icon-shape .label{text-align:center;}#mq6disob13pvp6w4wy7 .node.clickable{cursor:pointer;}#mq6disob13pvp6w4wy7 .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disob13pvp6w4wy7 .arrowheadPath{fill:lightgrey;}#mq6disob13pvp6w4wy7 .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disob13pvp6w4wy7 .flowchart-link{stroke:lightgrey;fill:none;}#mq6disob13pvp6w4wy7 .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disob13pvp6w4wy7 .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disob13pvp6w4wy7 .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disob13pvp6w4wy7 .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disob13pvp6w4wy7 .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disob13pvp6w4wy7 .cluster text{fill:#F9FFFE;}#mq6disob13pvp6w4wy7 .cluster span{color:#F9FFFE;}#mq6disob13pvp6w4wy7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disob13pvp6w4wy7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disob13pvp6w4wy7 rect.text{fill:none;stroke-width:0;}#mq6disob13pvp6w4wy7 .icon-shape,#mq6disob13pvp6w4wy7 .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disob13pvp6w4wy7 .icon-shape p,#mq6disob13pvp6w4wy7 .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disob13pvp6w4wy7 .icon-shape rect,#mq6disob13pvp6w4wy7 .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disob13pvp6w4wy7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disob13pvp6w4wy7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disob13pvp6w4wy7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}数据层公共模块层业务模块层应用层用户层Web前端xtools-app-standalone独立部署应用SysApplication系统管理应用GenApplication代码生成应用MonitorApplication监控服务应用sys-biz系统业务gen-biz代码生成业务sys-scheduled动态定时任务sys-log-bus-elasticsearchES日志存储common-cachecommon-callcommon-jarcommon-log-buscommon-log-filtercommon-mqcommon-sentinelcommon-taskcommon-configMySQLRedisElasticsearchRabbitMQS3存储三、项目功能设计 3.1 认证授权设计 3.1.1 登录认证流程 #mq6disobw2d1e48pd88{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobw2d1e48pd88 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobw2d1e48pd88 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobw2d1e48pd88 .error-icon{fill:#a44141;}#mq6disobw2d1e48pd88 .error-text{fill:#ddd;stroke:#ddd;}#mq6disobw2d1e48pd88 .edge-thickness-normal{stroke-width:1px;}#mq6disobw2d1e48pd88 .edge-thickness-thick{stroke-width:3.5px;}#mq6disobw2d1e48pd88 .edge-pattern-solid{stroke-dasharray:0;}#mq6disobw2d1e48pd88 .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobw2d1e48pd88 .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobw2d1e48pd88 .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobw2d1e48pd88 .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobw2d1e48pd88 .marker.cross{stroke:lightgrey;}#mq6disobw2d1e48pd88 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobw2d1e48pd88 p{margin:0;}#mq6disobw2d1e48pd88 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disobw2d1e48pd88 .cluster-label text{fill:#F9FFFE;}#mq6disobw2d1e48pd88 .cluster-label span{color:#F9FFFE;}#mq6disobw2d1e48pd88 .cluster-label span p{background-color:transparent;}#mq6disobw2d1e48pd88 .label text,#mq6disobw2d1e48pd88 span{fill:#ccc;color:#ccc;}#mq6disobw2d1e48pd88 .node rect,#mq6disobw2d1e48pd88 .node circle,#mq6disobw2d1e48pd88 .node ellipse,#mq6disobw2d1e48pd88 .node polygon,#mq6disobw2d1e48pd88 .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disobw2d1e48pd88 .rough-node .label text,#mq6disobw2d1e48pd88 .node .label text,#mq6disobw2d1e48pd88 .image-shape .label,#mq6disobw2d1e48pd88 .icon-shape .label{text-anchor:middle;}#mq6disobw2d1e48pd88 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disobw2d1e48pd88 .rough-node .label,#mq6disobw2d1e48pd88 .node .label,#mq6disobw2d1e48pd88 .image-shape .label,#mq6disobw2d1e48pd88 .icon-shape .label{text-align:center;}#mq6disobw2d1e48pd88 .node.clickable{cursor:pointer;}#mq6disobw2d1e48pd88 .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disobw2d1e48pd88 .arrowheadPath{fill:lightgrey;}#mq6disobw2d1e48pd88 .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disobw2d1e48pd88 .flowchart-link{stroke:lightgrey;fill:none;}#mq6disobw2d1e48pd88 .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobw2d1e48pd88 .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disobw2d1e48pd88 .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobw2d1e48pd88 .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disobw2d1e48pd88 .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disobw2d1e48pd88 .cluster text{fill:#F9FFFE;}#mq6disobw2d1e48pd88 .cluster span{color:#F9FFFE;}#mq6disobw2d1e48pd88 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disobw2d1e48pd88 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disobw2d1e48pd88 rect.text{fill:none;stroke-width:0;}#mq6disobw2d1e48pd88 .icon-shape,#mq6disobw2d1e48pd88 .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobw2d1e48pd88 .icon-shape p,#mq6disobw2d1e48pd88 .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disobw2d1e48pd88 .icon-shape rect,#mq6disobw2d1e48pd88 .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobw2d1e48pd88 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disobw2d1e48pd88 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disobw2d1e48pd88 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}验证失败验证成功用户不存在用户存在已锁定已过期正常密码错误是否密码正确用户请求登录前端获取验证码GET /sys/login/captcha前端获取SM2公钥POST /sys/login/public-key用户输入账号密码使用SM2公钥加密提交登录请求POST /sys/login/passwd验证验证码Redis: UID_CAPTCHA返回验证码错误SM2解密密码验证公钥匹配查询用户信息返回用户不存在检查账号状态锁定/过期返回账号已锁定返回账号已过期验证密码SM3加密比对记录错误次数Redis计数器错误次数超限?锁定账号Redis: LOCK_SYS_USER返回密码错误清除错误计数生成TokenUUID accessToken + refreshToken缓存登录用户Redis: AUTH_SYS_USER返回Token信息3.1.2 Token管理机制 Token 基于 UUID 生成,存储在 Redis 中,包含四种键类型: Redis Key 说明 TTL accessToken:{uuid} Token -> 登录用户映射 60分钟 refreshToken:{uuid} 刷新Token -> AccessToken映射 60分钟 user:{userId} 用户 -> Token映射(单设备登录) 60分钟 mask:{userId} 数据脱敏忽略标记 按配置 Token 刷新流程:客户端使用 refreshToken 请求 GET /sys/login/refresh/{refreshToken},后端查找对应的 accessToken,获取登录用户信息,生成新的 Token 对。 3.1.3 授权设计(RBAC模型) #mq6disob5ogni39ranu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disob5ogni39ranu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disob5ogni39ranu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disob5ogni39ranu .error-icon{fill:#a44141;}#mq6disob5ogni39ranu .error-text{fill:#ddd;stroke:#ddd;}#mq6disob5ogni39ranu .edge-thickness-normal{stroke-width:1px;}#mq6disob5ogni39ranu .edge-thickness-thick{stroke-width:3.5px;}#mq6disob5ogni39ranu .edge-pattern-solid{stroke-dasharray:0;}#mq6disob5ogni39ranu .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disob5ogni39ranu .edge-pattern-dashed{stroke-dasharray:3;}#mq6disob5ogni39ranu .edge-pattern-dotted{stroke-dasharray:2;}#mq6disob5ogni39ranu .marker{fill:lightgrey;stroke:lightgrey;}#mq6disob5ogni39ranu .marker.cross{stroke:lightgrey;}#mq6disob5ogni39ranu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disob5ogni39ranu p{margin:0;}#mq6disob5ogni39ranu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disob5ogni39ranu .cluster-label text{fill:#F9FFFE;}#mq6disob5ogni39ranu .cluster-label span{color:#F9FFFE;}#mq6disob5ogni39ranu .cluster-label span p{background-color:transparent;}#mq6disob5ogni39ranu .label text,#mq6disob5ogni39ranu span{fill:#ccc;color:#ccc;}#mq6disob5ogni39ranu .node rect,#mq6disob5ogni39ranu .node circle,#mq6disob5ogni39ranu .node ellipse,#mq6disob5ogni39ranu .node polygon,#mq6disob5ogni39ranu .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disob5ogni39ranu .rough-node .label text,#mq6disob5ogni39ranu .node .label text,#mq6disob5ogni39ranu .image-shape .label,#mq6disob5ogni39ranu .icon-shape .label{text-anchor:middle;}#mq6disob5ogni39ranu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disob5ogni39ranu .rough-node .label,#mq6disob5ogni39ranu .node .label,#mq6disob5ogni39ranu .image-shape .label,#mq6disob5ogni39ranu .icon-shape .label{text-align:center;}#mq6disob5ogni39ranu .node.clickable{cursor:pointer;}#mq6disob5ogni39ranu .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disob5ogni39ranu .arrowheadPath{fill:lightgrey;}#mq6disob5ogni39ranu .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disob5ogni39ranu .flowchart-link{stroke:lightgrey;fill:none;}#mq6disob5ogni39ranu .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disob5ogni39ranu .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disob5ogni39ranu .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disob5ogni39ranu .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disob5ogni39ranu .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disob5ogni39ranu .cluster text{fill:#F9FFFE;}#mq6disob5ogni39ranu .cluster span{color:#F9FFFE;}#mq6disob5ogni39ranu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disob5ogni39ranu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disob5ogni39ranu rect.text{fill:none;stroke-width:0;}#mq6disob5ogni39ranu .icon-shape,#mq6disob5ogni39ranu .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disob5ogni39ranu .icon-shape p,#mq6disob5ogni39ranu .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disob5ogni39ranu .icon-shape rect,#mq6disob5ogni39ranu .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disob5ogni39ranu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disob5ogni39ranu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disob5ogni39ranu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}多对多多对多多对多多对多包含拥有匹配key: 模块:方法value: 角色ID列表用户 SysUser用户角色关联SysUserRole角色 SysRole角色菜单关联SysRoleMenu菜单 SysMenu接口权限SysInterfacePerm角色ID列表roleIds权限缓存Redis Hash权限验证3.1.4 权限验证流程 #mq6disobedavs1jgrrw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobedavs1jgrrw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobedavs1jgrrw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobedavs1jgrrw .error-icon{fill:#a44141;}#mq6disobedavs1jgrrw .error-text{fill:#ddd;stroke:#ddd;}#mq6disobedavs1jgrrw .edge-thickness-normal{stroke-width:1px;}#mq6disobedavs1jgrrw .edge-thickness-thick{stroke-width:3.5px;}#mq6disobedavs1jgrrw .edge-pattern-solid{stroke-dasharray:0;}#mq6disobedavs1jgrrw .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobedavs1jgrrw .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobedavs1jgrrw .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobedavs1jgrrw .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobedavs1jgrrw .marker.cross{stroke:lightgrey;}#mq6disobedavs1jgrrw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobedavs1jgrrw p{margin:0;}#mq6disobedavs1jgrrw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disobedavs1jgrrw .cluster-label text{fill:#F9FFFE;}#mq6disobedavs1jgrrw .cluster-label span{color:#F9FFFE;}#mq6disobedavs1jgrrw .cluster-label span p{background-color:transparent;}#mq6disobedavs1jgrrw .label text,#mq6disobedavs1jgrrw span{fill:#ccc;color:#ccc;}#mq6disobedavs1jgrrw .node rect,#mq6disobedavs1jgrrw .node circle,#mq6disobedavs1jgrrw .node ellipse,#mq6disobedavs1jgrrw .node polygon,#mq6disobedavs1jgrrw .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disobedavs1jgrrw .rough-node .label text,#mq6disobedavs1jgrrw .node .label text,#mq6disobedavs1jgrrw .image-shape .label,#mq6disobedavs1jgrrw .icon-shape .label{text-anchor:middle;}#mq6disobedavs1jgrrw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disobedavs1jgrrw .rough-node .label,#mq6disobedavs1jgrrw .node .label,#mq6disobedavs1jgrrw .image-shape .label,#mq6disobedavs1jgrrw .icon-shape .label{text-align:center;}#mq6disobedavs1jgrrw .node.clickable{cursor:pointer;}#mq6disobedavs1jgrrw .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disobedavs1jgrrw .arrowheadPath{fill:lightgrey;}#mq6disobedavs1jgrrw .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disobedavs1jgrrw .flowchart-link{stroke:lightgrey;fill:none;}#mq6disobedavs1jgrrw .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobedavs1jgrrw .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disobedavs1jgrrw .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobedavs1jgrrw .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disobedavs1jgrrw .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disobedavs1jgrrw .cluster text{fill:#F9FFFE;}#mq6disobedavs1jgrrw .cluster span{color:#F9FFFE;}#mq6disobedavs1jgrrw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disobedavs1jgrrw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disobedavs1jgrrw rect.text{fill:none;stroke-width:0;}#mq6disobedavs1jgrrw .icon-shape,#mq6disobedavs1jgrrw .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobedavs1jgrrw .icon-shape p,#mq6disobedavs1jgrrw .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disobedavs1jgrrw .icon-shape rect,#mq6disobedavs1jgrrw .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobedavs1jgrrw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disobedavs1jgrrw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disobedavs1jgrrw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}是否是否无效有效使用AntPathMatcher是否用户发起接口请求AuthFilter拦截请求是否在认证白名单?跳过认证是否在登录白名单?仅验证登录状态验证AccessTokenToken有效?返回未授权获取LoginUserDtoPremUtils.checkInterfacePerm从URI提取模块名如 /sys/user -> sys/user查询Redis权限缓存key: sys/user:GET匹配权限规则?获取允许的角色ID列表用户角色ID在允许列表中?放行请求返回权限不足存储用户上下文到CommonHolder3.1.5 权限缓存初始化 系统启动时 InitSys(ApplicationRunner, Order: 200)执行权限缓存加载: 查询所有 SysInterfacePerm 记录 按 模块名:HTTP方法 分组 以 JSON 字符串存入 Redis Hash(key: AUTH_SYS_URI) 使用 ScopedValue 传递日志追踪上下文 3.2 日志管理设计 3.2.1 日志类型 日志类型 说明 存储方式 HTTP请求日志 请求URI、方法、参数、IP、Header RabbitMQ异步 HTTP响应日志 响应状态码、Header、Body、耗时 RabbitMQ异步 操作日志 用户操作记录、权限验证记录 MySQL + RabbitMQ 系统日志 各类系统事件 MySQL / Elasticsearch Redis操作日志 缓存操作记录 LogBus异步 存储操作日志 文件存储操作记录 LogBus异步 任务日志 定时任务执行记录 MySQL 3.2.2 日志处理流程 #mq6disobwxp0hy3uzu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobwxp0hy3uzu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobwxp0hy3uzu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobwxp0hy3uzu .error-icon{fill:#a44141;}#mq6disobwxp0hy3uzu .error-text{fill:#ddd;stroke:#ddd;}#mq6disobwxp0hy3uzu .edge-thickness-normal{stroke-width:1px;}#mq6disobwxp0hy3uzu .edge-thickness-thick{stroke-width:3.5px;}#mq6disobwxp0hy3uzu .edge-pattern-solid{stroke-dasharray:0;}#mq6disobwxp0hy3uzu .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobwxp0hy3uzu .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobwxp0hy3uzu .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobwxp0hy3uzu .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobwxp0hy3uzu .marker.cross{stroke:lightgrey;}#mq6disobwxp0hy3uzu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobwxp0hy3uzu p{margin:0;}#mq6disobwxp0hy3uzu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disobwxp0hy3uzu .cluster-label text{fill:#F9FFFE;}#mq6disobwxp0hy3uzu .cluster-label span{color:#F9FFFE;}#mq6disobwxp0hy3uzu .cluster-label span p{background-color:transparent;}#mq6disobwxp0hy3uzu .label text,#mq6disobwxp0hy3uzu span{fill:#ccc;color:#ccc;}#mq6disobwxp0hy3uzu .node rect,#mq6disobwxp0hy3uzu .node circle,#mq6disobwxp0hy3uzu .node ellipse,#mq6disobwxp0hy3uzu .node polygon,#mq6disobwxp0hy3uzu .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disobwxp0hy3uzu .rough-node .label text,#mq6disobwxp0hy3uzu .node .label text,#mq6disobwxp0hy3uzu .image-shape .label,#mq6disobwxp0hy3uzu .icon-shape .label{text-anchor:middle;}#mq6disobwxp0hy3uzu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disobwxp0hy3uzu .rough-node .label,#mq6disobwxp0hy3uzu .node .label,#mq6disobwxp0hy3uzu .image-shape .label,#mq6disobwxp0hy3uzu .icon-shape .label{text-align:center;}#mq6disobwxp0hy3uzu .node.clickable{cursor:pointer;}#mq6disobwxp0hy3uzu .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disobwxp0hy3uzu .arrowheadPath{fill:lightgrey;}#mq6disobwxp0hy3uzu .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disobwxp0hy3uzu .flowchart-link{stroke:lightgrey;fill:none;}#mq6disobwxp0hy3uzu .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobwxp0hy3uzu .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disobwxp0hy3uzu .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobwxp0hy3uzu .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disobwxp0hy3uzu .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disobwxp0hy3uzu .cluster text{fill:#F9FFFE;}#mq6disobwxp0hy3uzu .cluster span{color:#F9FFFE;}#mq6disobwxp0hy3uzu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disobwxp0hy3uzu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disobwxp0hy3uzu rect.text{fill:none;stroke-width:0;}#mq6disobwxp0hy3uzu .icon-shape,#mq6disobwxp0hy3uzu .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobwxp0hy3uzu .icon-shape p,#mq6disobwxp0hy3uzu .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disobwxp0hy3uzu .icon-shape rect,#mq6disobwxp0hy3uzu .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobwxp0hy3uzu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disobwxp0hy3uzu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disobwxp0hy3uzu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}存在不存在是否HTTP请求HttpLogFilterOrder: 200包装Request/ResponseContentCachingWrapperAuthFilterOrder: 201业务处理LogBus记录操作日志OPT_LOG本地LogBusService?直接写入数据库发布到MQRabbitMqEnums.SYS_LOGSysLogMq消费者并发5-10LogBusService.saveLog异步记录HTTP日志VirtualThreadLogBusService存在?3.2.3 Elasticsearch日志存储 当配置 sys.log.type=elasticsearch 时,EsSysLogServiceImpl(标记 @Primary)替代默认的 SysLogServiceImpl: 使用 Spring Data Elasticsearch Repository 存储日志 支持分页查询:match_phrase(精确匹配)、wildcard(模糊匹配)、时间范围过滤 支持链路追踪查询:按 logIndex 和 logTime 排序,最多查询 10,000 条 支持按时间范围批量删除:_delete_by_query 3.3 代码生成设计 3.3.1 代码生成流程 #mq6disob9ceb2rfpajo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disob9ceb2rfpajo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disob9ceb2rfpajo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disob9ceb2rfpajo .error-icon{fill:#a44141;}#mq6disob9ceb2rfpajo .error-text{fill:#ddd;stroke:#ddd;}#mq6disob9ceb2rfpajo .edge-thickness-normal{stroke-width:1px;}#mq6disob9ceb2rfpajo .edge-thickness-thick{stroke-width:3.5px;}#mq6disob9ceb2rfpajo .edge-pattern-solid{stroke-dasharray:0;}#mq6disob9ceb2rfpajo .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disob9ceb2rfpajo .edge-pattern-dashed{stroke-dasharray:3;}#mq6disob9ceb2rfpajo .edge-pattern-dotted{stroke-dasharray:2;}#mq6disob9ceb2rfpajo .marker{fill:lightgrey;stroke:lightgrey;}#mq6disob9ceb2rfpajo .marker.cross{stroke:lightgrey;}#mq6disob9ceb2rfpajo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disob9ceb2rfpajo p{margin:0;}#mq6disob9ceb2rfpajo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disob9ceb2rfpajo .cluster-label text{fill:#F9FFFE;}#mq6disob9ceb2rfpajo .cluster-label span{color:#F9FFFE;}#mq6disob9ceb2rfpajo .cluster-label span p{background-color:transparent;}#mq6disob9ceb2rfpajo .label text,#mq6disob9ceb2rfpajo span{fill:#ccc;color:#ccc;}#mq6disob9ceb2rfpajo .node rect,#mq6disob9ceb2rfpajo .node circle,#mq6disob9ceb2rfpajo .node ellipse,#mq6disob9ceb2rfpajo .node polygon,#mq6disob9ceb2rfpajo .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disob9ceb2rfpajo .rough-node .label text,#mq6disob9ceb2rfpajo .node .label text,#mq6disob9ceb2rfpajo .image-shape .label,#mq6disob9ceb2rfpajo .icon-shape .label{text-anchor:middle;}#mq6disob9ceb2rfpajo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disob9ceb2rfpajo .rough-node .label,#mq6disob9ceb2rfpajo .node .label,#mq6disob9ceb2rfpajo .image-shape .label,#mq6disob9ceb2rfpajo .icon-shape .label{text-align:center;}#mq6disob9ceb2rfpajo .node.clickable{cursor:pointer;}#mq6disob9ceb2rfpajo .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disob9ceb2rfpajo .arrowheadPath{fill:lightgrey;}#mq6disob9ceb2rfpajo .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disob9ceb2rfpajo .flowchart-link{stroke:lightgrey;fill:none;}#mq6disob9ceb2rfpajo .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disob9ceb2rfpajo .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disob9ceb2rfpajo .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disob9ceb2rfpajo .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disob9ceb2rfpajo .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disob9ceb2rfpajo .cluster text{fill:#F9FFFE;}#mq6disob9ceb2rfpajo .cluster span{color:#F9FFFE;}#mq6disob9ceb2rfpajo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disob9ceb2rfpajo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disob9ceb2rfpajo rect.text{fill:none;stroke-width:0;}#mq6disob9ceb2rfpajo .icon-shape,#mq6disob9ceb2rfpajo .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disob9ceb2rfpajo .icon-shape p,#mq6disob9ceb2rfpajo .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disob9ceb2rfpajo .icon-shape rect,#mq6disob9ceb2rfpajo .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disob9ceb2rfpajo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disob9ceb2rfpajo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disob9ceb2rfpajo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}在线预览打包下载直接生成配置数据源同步数据库表结构syncDbJDBC连接外部数据库DatabaseMetaData读取所有表getTables保存到gen_table读取表字段getColumns + getPrimaryKeys保存到gen_table_column配置生成参数模板选择 、包名 、模块名生成方式previewCodeVelocity渲染模板downloadCodeZIP打包genCode写入项目目录返回代码内容Map生成ZIP文件包含前后端代码3.3.2 模板引擎配置 使用 Apache Velocity 2.4.1 模板引擎 模板从 classpath 加载,UTF-8 编码 通过 GenProperties 配置后端/前端应用名、模块名、作者、版本等参数 支持过滤字段(正则匹配字段注释) 支持排除表(配置不生成的表名) 3.3.3 生成代码结构 复制代码 {backendAppName}/{moduleName}/{moduleName}-biz/src/main/java/{packageName}/{subPackageName}/ ├── controller/ # Controller类 ├── service/ # Service接口 │ ├── base/ # 基础CRUD │ └── impl/ # Service实现 ├── mapper/ # Mapper接口 ├── model/ │ ├── entity/ # 实体类 │ └── dto/ │ ├── req/ # 请求DTO │ └── resp/ # 响应DTO ├── convert/ # MapStruct转换器 └── utils/ # 工具类 {frontendAppName}/src/{subPackageName}/{subModuleName}/ ├── index.ts # API接口 └── {tableName}/index.vue # Vue页面 sql/ # SQL脚本 3.4 任务调度设计 3.4.1 任务类型 任务类型 说明 实现类 DEL_SYS_LOG 清理过期系统日志 SysLogJob DEL_SYS_FILE 清理过期文件 SysFileJob DEL_DISABLE_SYS_USER 清理禁用用户 SysUserJob 自定义任务 动态定时任务 SysScheduledService 3.4.2 定时任务实现 #mq6disobe13ipezkn9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobe13ipezkn9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobe13ipezkn9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobe13ipezkn9 .error-icon{fill:#a44141;}#mq6disobe13ipezkn9 .error-text{fill:#ddd;stroke:#ddd;}#mq6disobe13ipezkn9 .edge-thickness-normal{stroke-width:1px;}#mq6disobe13ipezkn9 .edge-thickness-thick{stroke-width:3.5px;}#mq6disobe13ipezkn9 .edge-pattern-solid{stroke-dasharray:0;}#mq6disobe13ipezkn9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobe13ipezkn9 .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobe13ipezkn9 .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobe13ipezkn9 .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobe13ipezkn9 .marker.cross{stroke:lightgrey;}#mq6disobe13ipezkn9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobe13ipezkn9 p{margin:0;}#mq6disobe13ipezkn9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disobe13ipezkn9 .cluster-label text{fill:#F9FFFE;}#mq6disobe13ipezkn9 .cluster-label span{color:#F9FFFE;}#mq6disobe13ipezkn9 .cluster-label span p{background-color:transparent;}#mq6disobe13ipezkn9 .label text,#mq6disobe13ipezkn9 span{fill:#ccc;color:#ccc;}#mq6disobe13ipezkn9 .node rect,#mq6disobe13ipezkn9 .node circle,#mq6disobe13ipezkn9 .node ellipse,#mq6disobe13ipezkn9 .node polygon,#mq6disobe13ipezkn9 .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disobe13ipezkn9 .rough-node .label text,#mq6disobe13ipezkn9 .node .label text,#mq6disobe13ipezkn9 .image-shape .label,#mq6disobe13ipezkn9 .icon-shape .label{text-anchor:middle;}#mq6disobe13ipezkn9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disobe13ipezkn9 .rough-node .label,#mq6disobe13ipezkn9 .node .label,#mq6disobe13ipezkn9 .image-shape .label,#mq6disobe13ipezkn9 .icon-shape .label{text-align:center;}#mq6disobe13ipezkn9 .node.clickable{cursor:pointer;}#mq6disobe13ipezkn9 .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disobe13ipezkn9 .arrowheadPath{fill:lightgrey;}#mq6disobe13ipezkn9 .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disobe13ipezkn9 .flowchart-link{stroke:lightgrey;fill:none;}#mq6disobe13ipezkn9 .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobe13ipezkn9 .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disobe13ipezkn9 .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobe13ipezkn9 .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disobe13ipezkn9 .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disobe13ipezkn9 .cluster text{fill:#F9FFFE;}#mq6disobe13ipezkn9 .cluster span{color:#F9FFFE;}#mq6disobe13ipezkn9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disobe13ipezkn9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disobe13ipezkn9 rect.text{fill:none;stroke-width:0;}#mq6disobe13ipezkn9 .icon-shape,#mq6disobe13ipezkn9 .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobe13ipezkn9 .icon-shape p,#mq6disobe13ipezkn9 .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disobe13ipezkn9 .icon-shape rect,#mq6disobe13ipezkn9 .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobe13ipezkn9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disobe13ipezkn9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disobe13ipezkn9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}成功失败任务执行BaseJob.runJobTaskBus.init设置任务状态ING执行任务逻辑执行成功?TaskBus.save状态: SUCCESSTaskBus.error状态: ERRORTaskBus -> RabbitMQ队列: sys.taskSysTaskMq消费者并发5-10SysTaskService.save写入任务记录3.4.3 动态定时任务 SysScheduledService 提供动态定时任务管理: init():启动时从数据库加载所有启用的定时任务 start():启动指定任务(创建 ScheduledTask 注册到 Spring TaskScheduler) stop():停止指定任务(取消 ScheduledTask) restart():重启指定任务 run():立即执行一次任务 任务初始化通过 InitSysScheduled(ApplicationRunner, Order: 200)在系统启动时自动完成。 3.5 缓存设计 3.5.1 缓存策略 项目使用 Redis 作为主要缓存介质,所有缓存键和 TTL 通过 AppCache 枚举集中管理: 缓存Key TTL 用途 UID_SM2 5分钟 SM2密钥对(每次登录生成) UID_CAPTCHA 1分钟 验证码 AUTH_SYS_USER 60分钟 登录用户Token AUTH_SYS_URI 永久 URI权限缓存(启动加载) AUTH_CLOUD_TOKEN 1分钟 微服务调用Token(一次性) LOCK_JOB 5分钟 Job分布式锁 LOCK_SYS_USER 按配置 用户锁定(密码错误超限) RISK_IP 永久 IP风控黑名单 RISK_URI 永久 URI风控黑名单 SYS_CACHE_PARAM 永久 系统参数缓存 SYS_CACHE_AP_RULE 永久 密码规则缓存 SYS_CACHE_JAR 永久 JAR依赖缓存 SYS_CACHE_ADDR 60分钟 IP归属地缓存 COUNT_SYS_USER_PASSWD_ERR 永久 密码错误计数 3.5.2 Redis操作日志AOP RedisServiceAop 切面环绕所有 RedisService 方法: 记录方法名、参数、返回值、执行时间 通过 LogBus 发布 REDIS 类型日志 仅在存在 LogTrack 上下文时记录 3.5.3 风控本地缓存 URI风控使用两级缓存架构: 一级缓存:Caffeine 本地缓存(20秒过期) 二级缓存:Redis String 缓存 查询顺序:Caffeine -> Redis 3.6 风控管理设计 #mq6disobkqi8q4u93a{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobkqi8q4u93a .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobkqi8q4u93a .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobkqi8q4u93a .error-icon{fill:#a44141;}#mq6disobkqi8q4u93a .error-text{fill:#ddd;stroke:#ddd;}#mq6disobkqi8q4u93a .edge-thickness-normal{stroke-width:1px;}#mq6disobkqi8q4u93a .edge-thickness-thick{stroke-width:3.5px;}#mq6disobkqi8q4u93a .edge-pattern-solid{stroke-dasharray:0;}#mq6disobkqi8q4u93a .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobkqi8q4u93a .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobkqi8q4u93a .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobkqi8q4u93a .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobkqi8q4u93a .marker.cross{stroke:lightgrey;}#mq6disobkqi8q4u93a svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobkqi8q4u93a p{margin:0;}#mq6disobkqi8q4u93a .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disobkqi8q4u93a .cluster-label text{fill:#F9FFFE;}#mq6disobkqi8q4u93a .cluster-label span{color:#F9FFFE;}#mq6disobkqi8q4u93a .cluster-label span p{background-color:transparent;}#mq6disobkqi8q4u93a .label text,#mq6disobkqi8q4u93a span{fill:#ccc;color:#ccc;}#mq6disobkqi8q4u93a .node rect,#mq6disobkqi8q4u93a .node circle,#mq6disobkqi8q4u93a .node ellipse,#mq6disobkqi8q4u93a .node polygon,#mq6disobkqi8q4u93a .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disobkqi8q4u93a .rough-node .label text,#mq6disobkqi8q4u93a .node .label text,#mq6disobkqi8q4u93a .image-shape .label,#mq6disobkqi8q4u93a .icon-shape .label{text-anchor:middle;}#mq6disobkqi8q4u93a .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disobkqi8q4u93a .rough-node .label,#mq6disobkqi8q4u93a .node .label,#mq6disobkqi8q4u93a .image-shape .label,#mq6disobkqi8q4u93a .icon-shape .label{text-align:center;}#mq6disobkqi8q4u93a .node.clickable{cursor:pointer;}#mq6disobkqi8q4u93a .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disobkqi8q4u93a .arrowheadPath{fill:lightgrey;}#mq6disobkqi8q4u93a .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disobkqi8q4u93a .flowchart-link{stroke:lightgrey;fill:none;}#mq6disobkqi8q4u93a .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobkqi8q4u93a .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disobkqi8q4u93a .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobkqi8q4u93a .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disobkqi8q4u93a .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disobkqi8q4u93a .cluster text{fill:#F9FFFE;}#mq6disobkqi8q4u93a .cluster span{color:#F9FFFE;}#mq6disobkqi8q4u93a div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disobkqi8q4u93a .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disobkqi8q4u93a rect.text{fill:none;stroke-width:0;}#mq6disobkqi8q4u93a .icon-shape,#mq6disobkqi8q4u93a .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobkqi8q4u93a .icon-shape p,#mq6disobkqi8q4u93a .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disobkqi8q4u93a .icon-shape rect,#mq6disobkqi8q4u93a .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobkqi8q4u93a .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disobkqi8q4u93a .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disobkqi8q4u93a :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}是否命中未命中是否请求到达IpRisk检查Redis Hash: RISK_IPIP在黑名单?拒绝请求UriRisk检查Caffeine缓存?获取URI黑名单列表查询Redis缓存RISK_URI写入Caffeine20秒过期URI包含黑名单字符串?放行请求 IP风控:启动时从数据库加载 IP 黑名单到 Redis Hash,支持动态添加/移除 URI风控:使用 Caffeine + Redis 两级缓存,启动时从数据库加载 URI 黑名单字符串 风控数据来源:SysRisk 实体,按 SysRiskType(IP/URI)分类存储 3.7 文件管理设计 #mq6disobq6yrsh31ada{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobq6yrsh31ada .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobq6yrsh31ada .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobq6yrsh31ada .error-icon{fill:#a44141;}#mq6disobq6yrsh31ada .error-text{fill:#ddd;stroke:#ddd;}#mq6disobq6yrsh31ada .edge-thickness-normal{stroke-width:1px;}#mq6disobq6yrsh31ada .edge-thickness-thick{stroke-width:3.5px;}#mq6disobq6yrsh31ada .edge-pattern-solid{stroke-dasharray:0;}#mq6disobq6yrsh31ada .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobq6yrsh31ada .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobq6yrsh31ada .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobq6yrsh31ada .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobq6yrsh31ada .marker.cross{stroke:lightgrey;}#mq6disobq6yrsh31ada svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobq6yrsh31ada p{margin:0;}#mq6disobq6yrsh31ada .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disobq6yrsh31ada .cluster-label text{fill:#F9FFFE;}#mq6disobq6yrsh31ada .cluster-label span{color:#F9FFFE;}#mq6disobq6yrsh31ada .cluster-label span p{background-color:transparent;}#mq6disobq6yrsh31ada .label text,#mq6disobq6yrsh31ada span{fill:#ccc;color:#ccc;}#mq6disobq6yrsh31ada .node rect,#mq6disobq6yrsh31ada .node circle,#mq6disobq6yrsh31ada .node ellipse,#mq6disobq6yrsh31ada .node polygon,#mq6disobq6yrsh31ada .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disobq6yrsh31ada .rough-node .label text,#mq6disobq6yrsh31ada .node .label text,#mq6disobq6yrsh31ada .image-shape .label,#mq6disobq6yrsh31ada .icon-shape .label{text-anchor:middle;}#mq6disobq6yrsh31ada .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disobq6yrsh31ada .rough-node .label,#mq6disobq6yrsh31ada .node .label,#mq6disobq6yrsh31ada .image-shape .label,#mq6disobq6yrsh31ada .icon-shape .label{text-align:center;}#mq6disobq6yrsh31ada .node.clickable{cursor:pointer;}#mq6disobq6yrsh31ada .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disobq6yrsh31ada .arrowheadPath{fill:lightgrey;}#mq6disobq6yrsh31ada .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disobq6yrsh31ada .flowchart-link{stroke:lightgrey;fill:none;}#mq6disobq6yrsh31ada .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobq6yrsh31ada .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disobq6yrsh31ada .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobq6yrsh31ada .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disobq6yrsh31ada .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disobq6yrsh31ada .cluster text{fill:#F9FFFE;}#mq6disobq6yrsh31ada .cluster span{color:#F9FFFE;}#mq6disobq6yrsh31ada div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disobq6yrsh31ada .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disobq6yrsh31ada rect.text{fill:none;stroke-width:0;}#mq6disobq6yrsh31ada .icon-shape,#mq6disobq6yrsh31ada .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobq6yrsh31ada .icon-shape p,#mq6disobq6yrsh31ada .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disobq6yrsh31ada .icon-shape rect,#mq6disobq6yrsh31ada .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobq6yrsh31ada .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disobq6yrsh31ada .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disobq6yrsh31ada :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}非法合法不支持支持超限合法已删除TEMP且过期正常文件上传请求SysFileOptServiceImpl.upload验证文件名拒绝上传验证扩展名bizType.extArr验证文件大小bizType.maxSize计算MD5和SM3哈希5GB以下文件生成UUID存储路径StorageService存储记录文件元数据类型: TEMP设置过期时间bizType.expiry文件下载请求SysFileOptServiceImpl.download检查文件状态返回文件不存在自动删除文件StorageService下载文件生命周期状态:TEMP(临时) -> OK(确认)或 DELETE(删除/过期) 3.8 系统监控设计 SysMonitorController(/sys/monitor)提供以下监控端点: 端点 方法 说明 /sys/monitor/redis GET Redis 监控(内存、连接数、命中率等) /sys/monitor/mysql/{type} GET MySQL 监控(进程列表、InnoDB状态等) /sys/monitor/elasticsearch/{type} GET Elasticsearch 监控(集群健康、索引统计等) 使用枚举类型选择不同的监控指标,委托给 boot 框架中的 RedisMonitor、MySqlMonitor、ElasticsearchMonitor 实现。 3.9 消息队列设计 #mq6disobme12hnjq7vc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#ccc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mq6disobme12hnjq7vc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mq6disobme12hnjq7vc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mq6disobme12hnjq7vc .error-icon{fill:#a44141;}#mq6disobme12hnjq7vc .error-text{fill:#ddd;stroke:#ddd;}#mq6disobme12hnjq7vc .edge-thickness-normal{stroke-width:1px;}#mq6disobme12hnjq7vc .edge-thickness-thick{stroke-width:3.5px;}#mq6disobme12hnjq7vc .edge-pattern-solid{stroke-dasharray:0;}#mq6disobme12hnjq7vc .edge-thickness-invisible{stroke-width:0;fill:none;}#mq6disobme12hnjq7vc .edge-pattern-dashed{stroke-dasharray:3;}#mq6disobme12hnjq7vc .edge-pattern-dotted{stroke-dasharray:2;}#mq6disobme12hnjq7vc .marker{fill:lightgrey;stroke:lightgrey;}#mq6disobme12hnjq7vc .marker.cross{stroke:lightgrey;}#mq6disobme12hnjq7vc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mq6disobme12hnjq7vc p{margin:0;}#mq6disobme12hnjq7vc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#ccc;}#mq6disobme12hnjq7vc .cluster-label text{fill:#F9FFFE;}#mq6disobme12hnjq7vc .cluster-label span{color:#F9FFFE;}#mq6disobme12hnjq7vc .cluster-label span p{background-color:transparent;}#mq6disobme12hnjq7vc .label text,#mq6disobme12hnjq7vc span{fill:#ccc;color:#ccc;}#mq6disobme12hnjq7vc .node rect,#mq6disobme12hnjq7vc .node circle,#mq6disobme12hnjq7vc .node ellipse,#mq6disobme12hnjq7vc .node polygon,#mq6disobme12hnjq7vc .node path{fill:#1f2020;stroke:#ccc;stroke-width:1px;}#mq6disobme12hnjq7vc .rough-node .label text,#mq6disobme12hnjq7vc .node .label text,#mq6disobme12hnjq7vc .image-shape .label,#mq6disobme12hnjq7vc .icon-shape .label{text-anchor:middle;}#mq6disobme12hnjq7vc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mq6disobme12hnjq7vc .rough-node .label,#mq6disobme12hnjq7vc .node .label,#mq6disobme12hnjq7vc .image-shape .label,#mq6disobme12hnjq7vc .icon-shape .label{text-align:center;}#mq6disobme12hnjq7vc .node.clickable{cursor:pointer;}#mq6disobme12hnjq7vc .root .anchor path{fill:lightgrey!important;stroke-width:0;stroke:lightgrey;}#mq6disobme12hnjq7vc .arrowheadPath{fill:lightgrey;}#mq6disobme12hnjq7vc .edgePath .path{stroke:lightgrey;stroke-width:2.0px;}#mq6disobme12hnjq7vc .flowchart-link{stroke:lightgrey;fill:none;}#mq6disobme12hnjq7vc .edgeLabel{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobme12hnjq7vc .edgeLabel p{background-color:hsl(0, 0%, 34.4117647059%);}#mq6disobme12hnjq7vc .edgeLabel rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobme12hnjq7vc .labelBkg{background-color:rgba(87.75, 87.75, 87.75, 0.5);}#mq6disobme12hnjq7vc .cluster rect{fill:hsl(180, 1.5873015873%, 28.3529411765%);stroke:rgba(255, 255, 255, 0.25);stroke-width:1px;}#mq6disobme12hnjq7vc .cluster text{fill:#F9FFFE;}#mq6disobme12hnjq7vc .cluster span{color:#F9FFFE;}#mq6disobme12hnjq7vc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(20, 1.5873015873%, 12.3529411765%);border:1px solid rgba(255, 255, 255, 0.25);border-radius:2px;pointer-events:none;z-index:100;}#mq6disobme12hnjq7vc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#ccc;}#mq6disobme12hnjq7vc rect.text{fill:none;stroke-width:0;}#mq6disobme12hnjq7vc .icon-shape,#mq6disobme12hnjq7vc .image-shape{background-color:hsl(0, 0%, 34.4117647059%);text-align:center;}#mq6disobme12hnjq7vc .icon-shape p,#mq6disobme12hnjq7vc .image-shape p{background-color:hsl(0, 0%, 34.4117647059%);padding:2px;}#mq6disobme12hnjq7vc .icon-shape rect,#mq6disobme12hnjq7vc .image-shape rect{opacity:0.5;background-color:hsl(0, 0%, 34.4117647059%);fill:hsl(0, 0%, 34.4117647059%);}#mq6disobme12hnjq7vc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mq6disobme12hnjq7vc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mq6disobme12hnjq7vc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}成功失败成功失败是否消息生产者MqBus.push发送消息RabbitMQ Broker消费者组1: SysLogMq队列: sys.log并发: 5-10消费者组2: SysTaskMq队列: sys.task并发: 5-10处理成功?LogBusService.saveLog存储日志MqErrorHandle处理成功?SysTaskService.save存储任务记录SM3哈希消息Redis错误计数+1错误次数 >= 3?放弃消息删除计数器等待1秒抛出异常触发重投递队列定义: 队列 用途 消息类型 记录日志 sys.log 异步日志存储 LogBody 否 sys.task 异步任务记录 TaskInfo 是 错误处理:使用 SM3 哈希消息内容作为去重键,通过 Redis 计数器跟踪重试次数,最多重试 3 次。 四、编码规范设计 4.1 命名规范 类命名 类型 命名规范 示例 实体类 Sys + 功能名 SysUser、SysRole、SysMenu 请求DTO Sys + 功能名 + AddReq/UpdateReq/PageReq SysUserAddReq 响应DTO Sys + 功能名 + Resp SysUserResp Excel DTO Sys + 功能名 + Excel SysUserExcel Service接口 Sys + 功能名 + Service SysUserService Service实现 Sys + 功能名 + ServiceImpl SysUserServiceImpl Service Base Sys + 功能名 + BaseService SysUserBaseService Controller Sys + 功能名 + Controller SysUserController Mapper Sys + 功能名 + Mapper SysUserMapper Convert Sys + 功能名 + Convert SysUserConvert 枚举 功能名 + Enum SysRiskEnum 配置类 功能名 + Config SysConfig 初始化类 Init + 模块名 InitSys 消息消费者 Sys + 功能名 + Mq SysLogMq 定时任务 Sys + 功能名 + Job SysLogJob 工具类 功能名 + Utils PasswdUtils 方法命名 操作 命名规范 示例 查询单个 get + 功能名 getSysUser 分页查询 page + 功能名 pageSysUser 列表查询 list + 功能名 listSysRole 新增 add + 功能名 addSysUser 修改 update + 功能名 updateSysUser 删除 delete + 功能名 + ByIds deleteSysUserByIds 4.2 注释规范 类注释格式: java 复制代码 /** * <p>Title : 类名称</p> * <p>Description : 类描述</p> * <p>Company : org.xujun</p> * * @author : 作者名 * @version : 版本号 * @date : 日期 */ 方法注释格式: java 复制代码 /** * 方法描述 * * @param param 参数说明 * @return 返回值说明 */ 4.3 代码风格 Lombok:使用 @Data、@Builder、@Slf4j、@AllArgsConstructor、@NoArgsConstructor 等注解简化 POJO 代码 MapStruct:使用 @Mapper 注解定义对象转换器,编译期生成转换代码 MyBatis-Plus:使用 BaseMapper 简化 CRUD 操作,IService 封装 Service 层通用方法 构造器注入:使用 @RequiredArgsConstructor(Lombok)替代 @Autowired 字段注入 统一返回格式:所有 API 响应使用 Result<T> 统一封装 统一异常处理:BizError(业务错误)、BizWarning(业务警告)、UnauthorizedError(未授权)、BizPublicKeyError(密钥过期) API文档:使用 @Tag、@Operation、@Schema 注解生成 Knife4j API 文档 4.4 设计规范 分层原则:Controller -> Service -> Mapper,每层职责单一明确 单一职责:每个 Service 只负责一个业务领域 开闭原则:通过 @Primary 注解支持 Service 实现的运行时替换(如 EsSysLogServiceImpl 替换默认 SysLogServiceImpl) 基础抽象:BaseService + BaseServiceImpl 封装通用 CRUD,业务 Service 只关注差异化逻辑 过滤器链:使用 @Order 控制过滤器执行顺序(HttpLogFilter: 200 -> AuthFilter: 201) 初始化模式:ApplicationRunner + @Order 控制启动顺序 4.5 安全规范 安全措施 实现方式 说明 密码传输加密 SM2 非对称加密 服务端生成密钥对,客户端用公钥加密,服务端用私钥解密 密码存储加密 SM3 国密哈希 不可逆哈希存储,登录时对比哈希值 密钥管理 Redis 临时存储 SM2密钥对存储5分钟,防止重放攻击 SQL安全 MyBatis-Plus 参数化查询 防止SQL注入 数据验证 @Valid 注解 请求参数校验 认证授权 Token + RBAC UUID Token + Redis + 接口权限 数据脱敏 MaskIgnoreUtils 敏感字段按会话级别脱敏控制 账号锁定 Redis计数器 密码错误超限自动锁定 微服务认证 一次性Token Cloud Token 从 Redis Hash 删除后失效 五、项目依赖设计 5.1 核心框架依赖 依赖 版本 用途 Spring Boot 4.0.6 应用框架 Spring Framework 7.0.7 核心框架 Spring Security 7.0.5 安全框架 Spring Data BOM 2025.1.5 数据访问版本管理 Spring AMQP 4.0.3 RabbitMQ集成 Jackson BOM 2.21.2 JSON序列化(主) Jackson BOM 3.1.2 JSON序列化(新) MyBatis Spring Boot Starter 4.0.1 MyBatis集成 MyBatis-Plus 3.5.16 ORM增强工具 5.2 工具库依赖 依赖 版本 用途 Lombok 1.18.46 代码简化 MapStruct 1.6.3 对象映射 FastJSON2 2.0.60 JSON处理 Velocity 2.4.1 模板引擎(代码生成) Commons IO 2.22.0 IO工具 Commons Lang3 3.20.0 通用工具 Commons Text 1.15.0 文本处理 Caffeine 3.2.3 本地缓存(风控) 5.3 安全相关依赖 依赖 版本 用途 BouncyCastle 1.84 SM2/SM3国密算法 java-jwt 4.5.1 JWT Token Easy Captcha 1.6.2 验证码生成 5.4 文档相关依赖 依赖 版本 用途 Knife4j 4.5.0 API文档增强 Swagger Annotations 2.2.48 OpenAPI注解 SpringDoc OpenAPI 3.0.3 OpenAPI文档生成 5.5 消息队列依赖 依赖 版本 用途 Spring AMQP 4.0.3 RabbitMQ集成(由Spring Boot 4.0.6管理) 5.6 缓存依赖 依赖 版本 用途 Spring Data Redis 由Spring Boot管理 Redis集成 5.7 系统监控依赖 依赖 版本 用途 OSHI 6.12.0 系统信息采集 Spring Boot Admin 4.0.4 应用监控 5.8 数据库依赖 依赖 版本 用途 Druid 1.2.28 数据库连接池 5.9 文件处理依赖 依赖 版本 用途 Fesod Sheet 2.0.1-incubating Excel处理 S3 SDK 2.42.41 S3对象存储 5.10 其他工具依赖 依赖 版本 用途 ip2region 3.3.7 IP归属地查询 UserAgentUtils 1.21 浏览器标识解析 pinyin4j 2.5.1 拼音转换 thumbnailator 0.4.21 图片压缩 mmseg4j-core 1.10.0 中文分词 ZXing 3.5.4 二维码/条形码 PDFBox 3.0.7 PDF处理 Jsoup 1.22.2 HTML解析 JUnit Jupiter 6.0.3 单元测试 Byte Buddy 1.17.8 字节码操作 5.11 微服务相关依赖 依赖 版本 用途 Spring Cloud 2025.1.1 微服务框架 Spring Cloud Alibaba 2025.1.0.0 微服务组件 Nacos Client 3.1.1 服务注册与配置中心 Sentinel 1.8.9 流量控制与熔断降级 Seata 2.5.0 分布式事务 RocketMQ 5.3.1 消息队列(可选) XXL-Job 3.4.0 分布式任务调度(可选) 5.12 xtools内部框架依赖 所有 xtools 内部模块版本均为 5.0.0: 模块 用途 xtools-core 核心工具库 xtools-web Web工具库 xtools-extend 扩展工具库 xtools-api API接口定义 xtools-boot-api Boot API模块 xtools-boot-core Boot核心模块 xtools-boot-cache-redis Redis缓存模块 xtools-boot-db-mybatis MyBatis数据库模块 xtools-boot-db-mybatis-plus MyBatis-Plus模块 xtools-boot-elasticsearch Elasticsearch模块 xtools-boot-ip IP地址模块 xtools-boot-knife4j Knife4j文档模块 xtools-boot-log 日志模块 xtools-boot-mask 数据脱敏模块 xtools-boot-mq-base MQ基础模块 xtools-boot-mq-rabbit RabbitMQ模块 xtools-boot-storage-base 存储基础模块 xtools-boot-storage-s3 S3存储模块 xtools-boot-task 任务模块 xtools-boot-thread 线程模块 xtools-boot-web-base Web基础模块 xtools-boot-web-filter Web过滤器模块 xtools-cloud-alibaba-nacos Nacos集成 xtools-cloud-alibaba-sentinel Sentinel集成 xtools-cloud-call 微服务调用 六、技术选型说明 6.1 JDK 25 选择原因:最新LTS版本,提供长期支持和性能优化 主要新特性: 虚拟线程(Virtual Threads):轻量级线程,大幅提升并发能力,项目中用于异步日志记录(VirtualThreadTaskUtils.simple()) Scoped Value:虚拟线程间的上下文传递,项目中用于 LogTrackHolder 上下文传播 Structured Concurrency:结构化并发编程 改进的 ZGC/Shenandoah 垃圾回收器 Pattern Matching 增强 Record Classes 增强 6.2 Spring Boot 4.0.6 Spring Framework 版本:7.0.7 Spring Security 版本:7.0.5 主要特性: 支持 Jakarta EE 11 原生支持虚拟线程 改进的可观测性(Observability) 增强 GraalVM Native Image 支持 改进的自动配置机制 6.3 MyBatis-Plus 3.5.16 支持的 MyBatis 版本:4.0.1 主要特性: 简化 CRUD 操作(BaseMapper、IService) 内置分页插件 条件构造器(QueryWrapper、LambdaQueryWrapper) 自动填充、逻辑删除、乐观锁 代码生成器 SQL 性能分析 6.4 Elasticsearch Spring Data BOM 版本:2025.1.5 主要特性: 全文搜索和倒排索引 分布式架构,高可用 近实时搜索 项目中用于系统日志的存储和检索,支持分页查询、链路追踪和批量删除 6.5 Redis 版本说明:由 Spring Boot 4.0.6 管理 主要特性: 高性能键值缓存 支持多种数据结构(String、Hash、List、Set、ZSet) 项目中用于:Token存储、权限缓存、风控数据、分布式锁、参数缓存等 通过 RedisService 封装操作,AOP切面记录操作日志 6.6 RabbitMQ 版本说明:Spring AMQP 4.0.3(由Spring Boot管理) 主要特性: 可靠消息传递(确认机制、持久化) 灵活路由(Direct/Fanout/Topic交换机) 消息确认和重试机制 项目中用于:异步日志存储、异步任务记录 自定义错误处理:SM3去重 + Redis计数器 + 最多3次重试 6.7 Nacos 3.1.1 选择原因:Spring Cloud Alibaba 生态核心组件 主要特性: 服务注册与发现 动态配置管理 健康检查 支持微服务部署模式 6.8 其他重要依赖版本 依赖 版本 用途 选择原因 Sentinel 1.8.9 流量控制与熔断降级 阿里开源,轻量级高可用 FastJSON2 2.0.60 JSON序列化 高性能,国产开源 Lombok 1.18.46 代码简化 编译期注解处理,零运行时开销 MapStruct 1.6.3 对象映射 编译期生成,高性能 Velocity 2.4.1 模板引擎 代码生成模板渲染 Knife4j 4.5.0 API文档增强 增强Swagger UI,国人友好 BouncyCastle 1.84 加密库 SM2/SM3国密算法支持 OSHI 6.12.0 系统监控 跨平台系统信息采集 Easy Captcha 1.6.2 验证码生成 支持算术验证码、GIF动画验证码 Fesod Sheet 2.0.1-incubating Excel处理 Apache POI孵化项目 Druid 1.2.28 数据库连接池 阿里开源,监控功能完善 Caffeine 3.2.3 本地缓存 高性能,支持过期策略 S3 SDK 2.42.41 对象存储 AWS S3协议兼容 Jackson 2.21.2 JSON处理 Spring Boot默认JSON库 文档版本:v1.0 编写日期:2026-06-09 项目版本:1.0.0 父POM版本:xtools-parent-cloud:5.0.0 JDK版本:25 维护团队:xujun.org

优秀的个人博客,低调大师

BeetlSQL 3.36 发布,支持 SpringBoot4

BeetlSQL 研发自 2015 年,核心和生态扩展全部自研。目标是提供开发高效,维护高效,运行高效的数据访问框架,它适用范围广,定制性强,入门快。 阅读文档源码和例子在线体验多库使用性能测试插件支持 本次发布主要支持Spring Boot 4 新增 sql-springboot4-starter 支持Spring Boot 4 数据库集成。 Query类新增and or 接口,允许传入Consume<T>。 更新Beetl版本到最新的3.20。 BeetlSQL 核心功能 BeetlSQL 核心 功能 sql-core 核心包,封装了 JDBC 操作,SQL 文件管理,注解的注解管理 sql-fetch 类似 Hibernate 那样提供 @Fetch,@FetchMany 等注解 sql-mapper mapper 类定义和扩展,用户可以自定义自己的 mapper 和 mapper 的注解 sql-intergration 整合 Spring,solon,jfinal 等框架,以及例子 sql-query Query 和 LambdaQuery,用 Java API 构造和使用 SQL sql-mapping 支持单表,多表与 POJO 的互相映射,支持 json 定义,xml 定义映射方式,或者约定习俗 sql-template Beetl 模板实现,且支持其他模板语言 sql-gen 代码生成抽象包,并提供默认实现可以生成 dao,sql 文件,md 文档 sql-db-support 各种数据库的测试和验证,支持 33+ 数据库。 sql-samples 包含了上百个使用 beetlsql 的例子 sql-test 包含了上百个单元测试例子 BeetlSQL 最新扩展包 BeetlSQL 扩展包 功能 sql-xml 高仿 myabtis 的 xml 语法,如果喜欢使用 xml 写 sql 模板的,可以使用此扩展包 sql-accelerator 性能加速包,通过反射优化,缓存,让 beetlsql 性能提升 50%-200%,接近一半手写 JDBC 的性能 sql-firewall sql 防火墙,避免不小心写的 sql 破坏数据库 sql-dynamic-table 支持像访问静态表格那样防火动态表格,简化动态创建表格的业务需求开发 sql-bean-encrypt 支持 @MD5 ,@AES 等对字段加密解密 sql-rewrite 采用 sql 重写,支持单表多租户模式,逻辑删除,数据权限功能 SAGA(实验) BeetSQL 的 SAGA 是实现,用 SAGA 微服务事务 使用加速扩展性能优化结果:能达到近一半手写 JDBC 的性能 查询 测试内容 BeetlSQL(ops/ms) 纯 jdbc mybatis JPA beetlsqlExecuteJdbc 直接执行 JDBC 318 678 / 64 beetlsqlExecuteTemplate 执行 SQL 模板 268 / 44 66 beetlsqlFile SQL 存放在文件统一管理 266 / 41 / beetlsqlInsert 插入一条 129 248 43 59 beetlsqlGetAll 获取所有数据 13 40 4 5 beetlsqlLambdaQuery Java 函数编写 SQL 执行查询 196 / 9 / beetlsqlPageQuery 翻页查询 159 / 17 59 beetlsqlSelectById 查询一条 259 670 43 61 JMH性能测试 Benchmark Mode Cnt Score Error Units Beetl.addEntity thrpt 5 133.190 ± 38.548 ops/ms Beetl.complexMapping thrpt 5 236.289 ± 288.370 ops/ms Beetl.executeJdbcSql thrpt 5 298.657 ± 80.480 ops/ms Beetl.executeTemplateSql thrpt 5 251.418 ± 77.757 ops/ms Beetl.getAll thrpt 5 14.531 ± 0.605 ops/ms Beetl.getEntity thrpt 5 359.275 ± 85.099 ops/ms Beetl.lambdaQuery thrpt 5 187.228 ± 59.697 ops/ms Beetl.one2Many thrpt 5 178.041 ± 181.829 ops/ms Beetl.pageQuery thrpt 5 148.982 ± 39.327 ops/ms Beetl.sqlFile thrpt 5 249.206 ± 100.083 ops/ms DBVisitor.addEntity thrpt 5 99.294 ± 33.564 ops/ms DBVisitor.executeJdbcSql thrpt 5 185.177 ± 50.993 ops/ms DBVisitor.executeTemplateSql thrpt 5 3.189 ± 0.748 ops/ms DBVisitor.getAll thrpt 5 3.163 ± 0.980 ops/ms DBVisitor.getEntity thrpt 5 125.683 ± 44.190 ops/ms DBVisitor.lambdaQuery thrpt 5 94.314 ± 38.499 ops/ms DBVisitor.pageQuery thrpt 5 49.954 ± 18.254 ops/ms EasyQuery.addEntity thrpt 5 98.904 ± 39.890 ops/ms EasyQuery.complexMapping thrpt 5 67.397 ± 59.919 ops/ms EasyQuery.executeJdbcSql thrpt 5 243.160 ± 48.080 ops/ms EasyQuery.getAll thrpt 5 14.896 ± 2.219 ops/ms EasyQuery.getEntity thrpt 5 134.370 ± 67.962 ops/ms EasyQuery.lambdaQuery thrpt 5 137.292 ± 53.438 ops/ms EasyQuery.one2Many thrpt 5 75.083 ± 53.738 ops/ms EasyQuery.pageQuery thrpt 5 84.596 ± 46.942 ops/ms Flex.addEntity thrpt 5 86.484 ± 40.022 ops/ms Flex.getAll thrpt 5 2.926 ± 0.993 ops/ms Flex.getEntity thrpt 5 73.445 ± 39.437 ops/ms Flex.pageQuery thrpt 5 33.999 ± 26.776 ops/ms Jdbc.addEntity thrpt 5 225.223 ± 304.585 ops/ms Jdbc.executeJdbcSql thrpt 5 691.616 ± 145.280 ops/ms Jdbc.getAll thrpt 5 35.827 ± 7.295 ops/ms Jdbc.getEntity thrpt 5 678.791 ± 165.527 ops/ms Jpa.addEntity thrpt 5 53.219 ± 78.543 ops/ms Jpa.executeJdbcSql thrpt 5 60.734 ± 61.299 ops/ms Jpa.executeTemplateSql thrpt 5 64.478 ± 48.688 ops/ms Jpa.getAll thrpt 5 4.710 ± 2.062 ops/ms Jpa.getEntity thrpt 5 56.325 ± 53.744 ops/ms Jpa.one2Many thrpt 5 92.168 ± 111.591 ops/ms Jpa.pageQuery thrpt 5 58.756 ± 48.056 ops/ms MyBatis.addEntity thrpt 5 40.533 ± 12.461 ops/ms MyBatis.complexMapping thrpt 5 106.348 ± 57.688 ops/ms MyBatis.executeTemplateSql thrpt 5 46.953 ± 13.541 ops/ms MyBatis.getAll thrpt 5 5.394 ± 0.502 ops/ms MyBatis.getEntity thrpt 5 45.303 ± 11.928 ops/ms MyBatis.lambdaQuery thrpt 5 23.756 ± 13.613 ops/ms MyBatis.pageQuery thrpt 5 16.190 ± 5.682 ops/ms MyBatis.sqlFile thrpt 5 42.558 ± 18.025 ops/ms SqlUtils.addEntity thrpt 5 232.501 ± 332.656 ops/ms SqlUtils.executeJdbcSql thrpt 5 682.610 ± 171.506 ops/ms SqlUtils.getAll thrpt 5 44.353 ± 4.346 ops/ms SqlUtils.getEntity thrpt 5 643.873 ± 131.587 ops/ms Wood.addEntity thrpt 5 105.097 ± 79.961 ops/ms Wood.executeJdbcSql thrpt 5 127.020 ± 48.142 ops/ms Wood.executeTemplateSql thrpt 5 129.193 ± 44.455 ops/ms Wood.getAll thrpt 5 2.051 ± 0.524 ops/ms Wood.getEntity thrpt 5 126.104 ± 41.976 ops/ms Wood.lambdaQuery thrpt 5 125.013 ± 43.991 ops/ms Wood.pageQuery thrpt 5 220.101 ± 90.028 ops/ms Wood.sqlFile thrpt 5 132.431 ± 50.141 ops/ms

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册