【JEECG Boot】 JEECG Boot——数据字典管理 系统性知识体系全解析

文章目录

  • [JEECG Boot------数据字典管理](#JEECG Boot——数据字典管理)
    • 一、核心定位与设计理念
      • [1. 核心价值](#1. 核心价值)
      • [2. 整体架构分层](#2. 整体架构分层)
    • 二、底层数据模型与存储设计
      • [1. 字典主表:sys_dict](#1. 字典主表:sys_dict)
      • [2. 字典项从表:sys_dict_item](#2. 字典项从表:sys_dict_item)
    • 三、后端核心能力体系
      • [1. 核心注解:@Dict 字典翻译注解](#1. 核心注解:@Dict 字典翻译注解)
      • [2. 翻译核心:DictAspect AOP切面](#2. 翻译核心:DictAspect AOP切面)
        • [2.1 核心工作机制](#2.1 核心工作机制)
        • [2.2 关键特性](#2.2 关键特性)
      • [3. 缓存机制](#3. 缓存机制)
        • [3.1 后端Redis缓存](#3.1 后端Redis缓存)
        • [3.2 前端本地缓存](#3.2 前端本地缓存)
      • [4. 核心API接口](#4. 核心API接口)
      • [5. 高级扩展能力](#5. 高级扩展能力)
    • [四、前端核心组件:JDictSelectTag 全解析](#四、前端核心组件:JDictSelectTag 全解析)
      • [1. 组件核心定位](#1. 组件核心定位)
      • [2. 核心API参数](#2. 核心API参数)
      • [3. 基础用法示例](#3. 基础用法示例)
        • [3.1 普通字典用法](#3.1 普通字典用法)
        • [3.2 表字典用法(动态业务表数据)](#3.2 表字典用法(动态业务表数据))
        • [3.3 带过滤条件的表字典用法](#3.3 带过滤条件的表字典用法)
        • [3.4 不同渲染类型用法](#3.4 不同渲染类型用法)
      • [4. 高级用法](#4. 高级用法)
        • [4.1 表单校验集成](#4.1 表单校验集成)
        • [4.2 动态加载与手动获取字典数据](#4.2 动态加载与手动获取字典数据)
        • [4.3 表格列自定义渲染](#4.3 表格列自定义渲染)
    • 五、全链路工作流程
    • 六、最佳实践与规范
      • [1. 字典设计规范](#1. 字典设计规范)
      • [2. 性能优化最佳实践](#2. 性能优化最佳实践)
      • [3. 安全规范](#3. 安全规范)
    • 七、常见问题与解决方案
      • [1. @Dict注解翻译不生效](#1. @Dict注解翻译不生效)
      • [2. 字典修改后,前端显示旧数据](#2. 字典修改后,前端显示旧数据)
      • [3. JDictSelectTag组件数值回显失败](#3. JDictSelectTag组件数值回显失败)
      • [4. 表字典查询报SQL注入错误](#4. 表字典查询报SQL注入错误)

JEECG Boot------数据字典管理

JEECG Boot 数据字典管理是平台核心基础能力,通过后端统一配置+注解自动翻译+前端组件化渲染的全链路设计,解决企业级应用中枚举值、状态码、业务常量等静态数据的统一管理、动态更新、全局复用问题,彻底消除代码硬编码,实现一处配置、全系统生效。

一、核心定位与设计理念

1. 核心价值

  • 统一管控:集中管理系统内所有静态枚举数据,支持可视化增删改查,无需修改代码即可调整业务选项
  • 自动翻译:通过注解实现数据库存储值(如1/2)与前端展示文本(男/女)的自动双向转换,无需手动写翻译逻辑
  • 组件化复用 :前端封装JDictSelectTag等专用组件,一行代码实现字典下拉、单选等渲染,大幅降低开发成本
  • 高性能保障:多层级缓存机制,针对读多写少的字典场景做深度优化,减少数据库与接口请求压力
  • 扩展性极强:支持普通字典、动态表字典、多租户、多数据源、多级联动等复杂场景,适配各类业务需求

2. 整体架构分层

JEECG Boot 数据字典体系采用前后端分离的四层架构设计,从上到下依次为:

架构层级 核心载体 核心能力
前端渲染层 JDictSelectTag组件、配套工具函数 字典数据渲染、表单绑定、值转换、本地缓存
接口服务层 字典Controller、OpenAPI 字典数据查询、管理、缓存刷新、权限控制
核心能力层 @Dict注解、DictAspect切面、缓存服务 自动翻译、动态解析、缓存管理、安全校验
数据存储层 sys_dict(主表)、sys_dict_item(从表) 字典元数据与字典项数据的持久化存储

二、底层数据模型与存储设计

JEECG Boot 采用主从表结构实现字典数据的规范化存储,两张核心表通过字典ID关联,支持多租户、低代码应用隔离。

1. 字典主表:sys_dict

存储字典的元数据信息,一个字典编码对应一条主表记录,是全局唯一标识。

核心字段 字段类型 字段说明 核心约束
id varchar(32) 主键ID 非空、主键
dict_name varchar(100) 字典名称(界面展示) 非空
dict_code varchar(100) 字典编码(全局唯一调用标识) 非空、唯一索引
description varchar(500) 字典描述 -
del_flag int(1) 逻辑删除标志(0未删除 1已删除) 默认0
tenant_id int 租户ID(多租户隔离) -
low_app_id varchar(32) 低代码应用ID -

2. 字典项从表:sys_dict_item

存储字典对应的具体选项数据,一条主表记录对应多条从表记录,支持排序、禁用、颜色标识等扩展能力。

核心字段 字段类型 字段说明 核心约束
id varchar(32) 主键ID 非空、主键
dict_id varchar(32) 关联主表的字典ID 非空、外键关联
item_text varchar(100) 字典项文本(前端展示值) 非空
item_value varchar(100) 字典项值(数据库存储值) 非空
sort_order int 排序号(控制前端展示顺序) 默认0
status int(1) 状态(1启用 0禁用) 默认1
item_color varchar(100) 字典项颜色标识(用于标签、状态展示) -

三、后端核心能力体系

1. 核心注解:@Dict 字典翻译注解

@Dict是后端字典能力的核心载体,标注在实体类字段上,框架通过AOP自动完成字典值的翻译,生成字段名_dictText格式的翻译字段。

1.1 注解核心参数
参数名 适用场景 说明 示例
dicCode 普通字典 对应sys_dict表中的字典编码,必填 @Dict(dicCode = "sex")
dictTable 表字典 动态从业务表获取字典数据的表名 @Dict(dictTable = "sys_user")
dicText 表字典 业务表中作为展示文本的字段名 @Dict(dicText = "realname")
dicCode 表字典 业务表中作为存储值的字段名 @Dict(dicCode = "id")
ds 多数据源场景 指定表字典所在的数据源名称 @Dict(ds = "multi-datasource1")
1.2 两大核心用法
(1)普通字典用法(系统内置字典)

适用于系统通用枚举值,在字典管理界面配置完成后使用,是最常用的场景。

java 复制代码
/**
 * 性别(1:男 2:女)
 * 对应字典编码sex,系统会自动翻译生成 sex_dictText 字段
 */
@Dict(dicCode = "sex")
private Integer sex;
(2)表字典用法(动态业务字典)

适用于需要从业务表动态获取选项的场景,无需在字典管理界面配置,直接关联业务表数据。

java 复制代码
/**
 * 创建人ID,关联用户表,自动翻译为用户真实姓名
 * 格式:dictTable=表名, dicText=展示字段, dicCode=存储字段
 */
@Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id")
private String createBy;
1.3 配套校验注解:@DictVerify

用于入参合法性校验,自动校验前端传入的值是否在字典定义的有效值范围内,避免非法数据入库。

java 复制代码
/**
 * 用户状态,仅允许传入字典user_status中定义的有效值
 */
@DictVerify(dictCode = "user_status", message = "用户状态值无效")
private Integer status;

2. 翻译核心:DictAspect AOP切面

字典自动翻译的底层实现基于Spring AOP环绕通知,核心类为DictAspect(部分版本为DictTransformAspect),在接口响应数据返回给前端前,自动扫描@Dict注解并完成翻译注入。

2.1 核心工作机制
  1. 拦截Controller层返回的响应结果,解析返回数据类型
  2. 通过反射扫描实体类字段上的@Dict注解,收集需要翻译的字段
  3. 批量查询字典数据(普通字典查sys_dict,表字典动态执行SQL查询)
  4. 将字典值翻译为对应的展示文本,注入到返回对象的字段名_dictText属性中
  5. 支持分页对象IPage、列表List、单个实体等多种返回类型
2.2 关键特性
  • 批量查询优化:避免N+1查询问题,一次性加载所有需要翻译的字典数据
  • 缓存优先:优先从缓存中读取字典数据,大幅提升翻译性能
  • 多数据源支持:通过ds参数支持跨数据源的表字典翻译
  • 白名单防护:表字典查询内置SQL注入防护,仅允许查询白名单内的表与字段

3. 缓存机制

针对字典数据读多写少的特性,JEECG Boot 设计了前后端双层缓存架构,保障高性能访问,同时提供完善的缓存一致性方案。

3.1 后端Redis缓存
缓存类型 缓存key 失效策略 适用场景
普通字典缓存 sys:dict:cache 字典新增/编辑/删除时,通过@CacheEvict全量清空主动失效 系统内置的固定字典
表字典缓存 sys:table:dict:cache:* 定时失效,默认缓存5分钟,避免业务表数据变更导致的不一致 动态业务表字典
3.2 前端本地缓存
  • 缓存载体:Pinia/Vuex Store + localStorage(支持AES加密)
  • 加载策略:懒加载,字典组件首次使用时才请求数据,请求后缓存到Store中
  • 刷新机制:支持手动触发全局缓存刷新,字典管理界面修改数据后自动推送刷新事件

4. 核心API接口

平台提供了完善的RESTful API,支持字典的管理、查询、缓存刷新等操作,核心接口如下:

接口地址 请求方式 接口说明 核心参数
/sys/dict/list GET 字典主表分页列表 字典名称、编码、状态
/sys/dict/getDictItems/{dictCode} GET 根据字典编码获取字典项列表 dictCode(字典编码)
/sys/dict/queryTableDictItemsByCode GET 获取表字典数据 table、text、code、filterSql
/sys/dict/refreshCache DELETE 刷新字典全局缓存 -

5. 高级扩展能力

  • 多租户隔离:通过tenant_id字段实现不同租户之间的字典数据完全隔离,互不影响
  • 多数据源支持:表字典支持指定数据源,实现跨库的字典数据查询与翻译
  • Excel导入导出适配:导出时自动将字典值翻译为文本,导入时自动将文本转换为字典存储值,无需手动处理
  • AI智能匹配 :代码生成器AI能力可根据字段名称、注释自动匹配对应的字典编码,自动添加@Dict注解

四、前端核心组件:JDictSelectTag 全解析

JDictSelectTag是JEECG Boot 专为数据字典封装的前端组件,基于Ant Design Vue二次封装,实现了字典数据的一键渲染、双向绑定、自动加载,是前端使用字典的核心载体。

1. 组件核心定位

  • 一行代码实现字典下拉、单选框、按钮式单选的渲染
  • 自动根据dictCode加载字典数据,无需手动调用接口
  • 与平台表单体系深度集成,支持校验、双向绑定、联动等能力
  • 内置缓存机制,同字典编码多次使用仅发起一次接口请求

2. 核心API参数

参数名 类型 必填 默认值 说明
dictCode string - 字典配置核心参数,支持两种格式: 1. 普通字典:字典编码(如sex) 2. 表字典:表名,文本字段,取值字段[,过滤条件]
type string select 组件渲染类型,支持: select:下拉选择框 radio:单选框组 radioButton:按钮式单选框
v-model:value string/number/array - 双向绑定的值,对应字典项的itemValue
placeholder string - 输入框占位提示文本
stringToNumber boolean false 是否将字典value从string自动转为number,解决数值类型回显失败问题
disabled boolean false 是否禁用整个组件
showChooseOption boolean true 是否显示【请选择】默认选项
getPopupContainer function () => document.body 下拉菜单渲染父节点,解决滚动定位问题

3. 基础用法示例

3.1 普通字典用法
vue 复制代码
<template>
  <!-- 性别字典下拉框,对应字典编码sex -->
  <JDictSelectTag 
    v-model:value="queryParam.sex" 
    placeholder="请选择用户性别" 
    dictCode="sex" 
  />
</template>

<script setup>
import { ref } from 'vue';
const queryParam = ref({
  sex: ''
});
</script>
3.2 表字典用法(动态业务表数据)
vue 复制代码
<!-- 从用户表获取数据,展示realname,存储id -->
<JDictSelectTag 
  v-model:value="queryParam.userId" 
  placeholder="请选择用户" 
  dictCode="sys_user,realname,id" 
/>
3.3 带过滤条件的表字典用法
vue 复制代码
<!-- 只查询性别为女的用户,过滤条件sex = '2' -->
<JDictSelectTag 
  v-model:value="queryParam.userId" 
  placeholder="请选择女性用户" 
  dictCode="sys_user,realname,id,sex = '2'" 
/>
3.4 不同渲染类型用法
vue 复制代码
<!-- 按钮式单选框 -->
<JDictSelectTag 
  v-model:value="formData.status" 
  dictCode="order_status" 
  type="radioButton" 
/>

<!-- 普通单选框组 -->
<JDictSelectTag 
  v-model:value="formData.auditType" 
  dictCode="audit_type" 
  type="radio" 
/>

4. 高级用法

4.1 表单校验集成
vue 复制代码
<template>
  <a-form :model="formData" :rules="rules">
    <a-form-item label="用户性别" name="sex">
      <JDictSelectTag 
        v-model:value="formData.sex" 
        dictCode="sex" 
        placeholder="请选择性别"
      />
    </a-form-item>
  </a-form>
</template>

<script setup>
import { reactive, ref } from 'vue';
const formData = reactive({ sex: '' });
const rules = {
  sex: [{ required: true, message: '请选择性别', trigger: 'change' }]
};
</script>
4.2 动态加载与手动获取字典数据

组件配套提供了工具函数,支持手动加载字典数据、自定义翻译场景,核心函数位于@/components/dict/JDictSelectUtil.ts

vue 复制代码
<script setup>
import { initDictOptions, filterDictText } from '@/components/dict/JDictSelectUtil';
import { ref, onMounted } from 'vue';

const sexDictOptions = ref([]);

// 手动加载字典数据
const loadDictData = async () => {
  const res = await initDictOptions('sex');
  if (res.success) {
    sexDictOptions.value = res.result;
  }
};

// 手动翻译字典值
const getSexText = (value) => {
  return filterDictText(sexDictOptions.value, value);
};

onMounted(() => {
  loadDictData();
});
</script>
4.3 表格列自定义渲染
vue 复制代码
<template>
  <a-table :columns="columns" :data-source="tableData" />
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { initDictOptions, filterDictText } from '@/components/dict/JDictSelectUtil';

const sexDictOptions = ref([]);
const tableData = ref([]);

const columns = [
  {
    title: '用户名',
    dataIndex: 'username',
    align: 'center'
  },
  {
    title: '性别',
    dataIndex: 'sex',
    align: 'center',
    customRender: ({ text }) => {
      // 手动翻译字典值为文本
      return filterDictText(sexDictOptions.value, text);
    }
  }
];

onMounted(async () => {
  // 初始化字典数据
  const res = await initDictOptions('sex');
  sexDictOptions.value = res.success ? res.result : [];
});
</script>

五、全链路工作流程

从字典配置到前端渲染的完整闭环流程如下:

  1. 后台配置:管理员在系统管理-字典管理界面,新增字典主表记录,维护对应的字典项,配置完成后保存
  2. 后端实体配置 :在业务实体类的对应字段上,添加@Dict注解,指定字典编码或表字典配置
  3. 接口响应翻译 :前端请求业务接口时,DictAspect切面自动拦截响应数据,扫描@Dict注解,完成字典翻译,注入_dictText字段返回给前端
  4. 前端组件渲染 :前端页面使用JDictSelectTag组件,通过dictCode指定字典编码,组件自动加载字典数据,渲染为下拉/单选组件,实现双向绑定
  5. 缓存更新:当字典数据发生修改时,系统自动清空后端Redis缓存,同时推送事件通知前端刷新本地缓存,保障前后端数据一致性
  6. 数据入库校验 :前端提交表单时,可通过@DictVerify注解自动校验提交的值是否在字典有效值范围内,拦截非法数据

六、最佳实践与规范

1. 字典设计规范

  • 编码规范 :字典编码使用下划线命名法,语义清晰,如user_statusorder_type,禁止使用拼音、无意义缩写
  • 值类型规范:字典项值优先使用数字编码(1/2/3),避免使用中文,特殊场景可使用字符串,保持全系统统一
  • 分类规范:按业务模块对字典进行分类,如系统模块、订单模块、用户模块,避免混乱
  • 禁用规范:字典项废弃时优先禁用,而非直接删除,避免历史数据翻译失败

2. 性能优化最佳实践

  • 高频使用的字典,在系统启动时进行缓存预热,减少首次访问延迟
  • 表字典尽量使用简单过滤条件,避免复杂SQL导致的性能问题
  • 前端页面多个地方使用同一字典时,优先在页面初始化时一次性加载,而非每个组件单独加载
  • 大批量数据翻译时,优先使用后端@Dict注解自动翻译,避免前端循环翻译导致的页面卡顿

3. 安全规范

  • 表字典严格遵守平台白名单机制,禁止在dictCode中拼接复杂SQL、子查询,避免SQL注入风险
  • 敏感业务表禁止作为表字典使用,避免数据泄露
  • 字典管理界面配置严格的权限控制,仅允许管理员进行字典的增删改操作

七、常见问题与解决方案

1. @Dict注解翻译不生效

问题表现 :接口返回数据中没有生成_dictText字段
核心原因与解决方案

  • 原因1:接口返回类型不是IPageResult<IPage>等切面默认支持的类型
    解决方案:扩展DictAspect切面,增加对ListResult<T>等类型的支持
  • 原因2:实体类字段使用了private修饰,且没有对应的getter方法
    解决方案:为字段添加getter/setter方法,或使用lombok的@Data注解
  • 原因3:字典编码配置错误,或字典项被禁用
    解决方案:检查字典管理界面,确认字典编码正确、字典项状态为启用

2. 字典修改后,前端显示旧数据

问题表现 :后台修改字典项后,前端页面仍显示旧的字典数据,刷新页面也不生效
解决方案

  1. 手动点击系统右上角的【刷新缓存】按钮,清空前端本地缓存
  2. 检查后端字典编辑接口是否添加了@CacheEvict注解,确保修改后清空Redis缓存
  3. 表字典数据修改后,等待缓存自动过期(默认5分钟),或手动调用缓存刷新接口

3. JDictSelectTag组件数值回显失败

问题表现 :编辑表单时,数据库中的数值无法回显到组件中
核心原因 :字典itemValue是string类型,而表单绑定的值是number类型,类型不匹配
解决方案 :添加stringToNumber属性,自动将字典value转为number类型

vue 复制代码
<JDictSelectTag 
  v-model:value="formData.sex" 
  dictCode="sex" 
  :stringToNumber="true" 
/>

4. 表字典查询报SQL注入错误

问题表现 :使用表字典时,控制台提示SQL注入拦截,无法查询数据
解决方案

  1. 检查使用的表名、字段名是否在平台的字典表白名单中
  2. 过滤条件仅支持简单的字段=值格式,禁止使用子查询、函数、OR等复杂语法
  3. 避免在表名、字段名中使用关键字、特殊字符
相关推荐
神奇小汤圆2 小时前
Spring Batch实战
后端
卖男孩的小火柴.2 小时前
java内置方法总结及基础算法
java·算法
赫瑞2 小时前
Java中的日期类
java·开发语言
喵个咪2 小时前
传统 CMS 太笨重?试试 Headless 架构的 GoWind,轻量又强大
前端·后端·cms
chenjingming6662 小时前
jmeter导入浏览器上按F12抓的数据包
前端·chrome·jmeter
张元清2 小时前
不用 Server Components 也能做 React 流式 SSR —— 实战指南
前端·javascript·面试
程序员木圭2 小时前
07-数组入门必看!Java数组的内存分析02
java·后端
前端技术2 小时前
ArkTS第三章:声明式UI开发实战
java·前端·人工智能·python·华为·鸿蒙