电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

SpringBoot中實現數據字典的示例代碼

瀏覽:4日期:2023-04-26 13:58:31

我們在日常的項目開發中,對于數據字典肯定不模糊,它幫助了我們更加方便快捷地進行開發,下面一起來看看在 SpringBoot 中如何實現數據字典功能的

一、簡介

1、定義

數據字典是指對數據的數據項、數據結構、數據流、數據存儲、處理邏輯等進行定義和描述,其目的是對數據流程圖中的各個元素做出詳細的說明,使用數據字典為簡單的建模項目。簡而言之,數據字典是描述數據的信息集合,是對系統中使用的所有數據元素的定義的集合。

數據字典(Data dictionary)是一種用戶可以訪問的記錄數據庫和應用程序元數據的目錄。主動數據字典是指在對數據庫或應用程序結構進行修改時,其內容可以由DBMS自動更新的數據字典。被動數據字典是指修改時必須手工更新其內容的數據字典。

2、理解

數據字典是一種通用的程序設計思想,將主體與分支存于兩張數據表中,他們之間靠著唯一的 code 相互聯系,且 code 是唯一存在的,分支依附主體而存在,每一條分支都有它唯一對應的屬性值

例如:性別(sex),分為(0?保密1?男2?女),那么數據字典的設計就應該是

主表:

{'code': 'sex','name': '性別'}

副表:

[{'dictCode': 'sex','code': '0','text': '保密'},{'dictCode': 'sex','code': '1','text': '男'},{'dictCode': 'sex','code': '2','text': '女'}]

那么我們在使用數據字典的時候,只需要知道 dictCode,再使用 code 找到唯一的字典值

二、數據表設計

1、數據表設計

主表:

drop table if exists sys_dict;/*==============================================================*//* Table: sys_dict *//*==============================================================*/create table sys_dict( id bigint(20) not null auto_increment comment ’主鍵id’, code varchar(32) comment ’編碼’, name varchar(32) comment ’名稱’, descript varchar(64) comment ’描述’, statustinyint(1) default 0 comment ’狀態(0--正常1--凍結)’, create_time datetime comment ’創建時間’, create_user bigint(20) comment ’創建人’, del_flag tinyint(1) default 0 comment ’刪除狀態(0,正常,1已刪除)’, primary key (id))type = InnoDB;alter table sys_dict comment ’字典管理表’;

副表:

drop table if exists sys_dict_detail;/*==============================================================*//* Table: sys_dict_detail *//*==============================================================*/create table sys_dict_detail( id bigint(20) not null comment ’主鍵id’, dict_code varchar(32) comment ’字典編碼’, code varchar(32) comment ’編碼’, name varchar(32) comment ’名稱’, primary key (id))type = InnoDB;alter table sys_dict_detail comment ’字典配置表’;

它們的關系如圖所示:

SpringBoot中實現數據字典的示例代碼

2、數據字典配置

SpringBoot中實現數據字典的示例代碼

三、開發前戲

1、引入 maven 依賴

<!-- web支持 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><!-- thymeleaf模板引擎 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- aop依賴 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency><!-- lombok插件 --><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional></dependency>

我們引入了 aop 切面所需依賴,我們的數據字典也是基于 aop 切面實現的

2、創建實體類

用戶信息表 SysUserInfo.java:

import com.baomidou.mybatisplus.annotation.*;import com.baomidou.mybatisplus.extension.activerecord.Model;import com.zyxx.common.annotation.Dict;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import lombok.EqualsAndHashCode;import lombok.experimental.Accessors;import java.io.Serializable;/** * <p> * 用戶信息表 * </p> * * @author lizhou * @since 2020-07-06 */@Data@EqualsAndHashCode(callSuper = false)@Accessors(chain = true)@TableName('sys_user_info')@ApiModel(value='SysUserInfo對象', description='用戶信息表')public class SysUserInfo extends Model<SysUserInfo> { @ApiModelProperty(value = 'ID') @TableId(value = 'id', type = IdType.AUTO) private Long id; @ApiModelProperty(value = '登錄賬號') @TableField('account') private String account; @ApiModelProperty(value = '登錄密碼') @TableField('password') private String password; @ApiModelProperty(value = '姓名') @TableField('name') private String name; @ApiModelProperty(value = '性別(0--未知1--男2--女)') @TableField('sex') @Dict(dictCode = 'sex') private Integer sex; @ApiModelProperty(value = '狀態(0--正常1--凍結)') @TableField('status') @Dict(dictCode = 'status') private Integer status;}

3、返回結果通用實體類

返回結果通用實體類 LayTableResult.java:

import lombok.Getter;import lombok.Setter;import java.util.List;/** * @param <T> 返回的實體類 * @author lizhou * @描述 后臺返回給LayUI的數據格式 */@Getter@Setterpublic class LayTableResult<T> { /** * 接口狀態 */ private Integer code; /** * 提示信息 */ private String msg; /** * 接口數據長度 */ private Long count; /** * 接口數據 */ private List<T> data; /** * 無參構造函數 */ public LayTableResult() { super(); } /** * 返回數據給表格 */ public LayTableResult(Long count, List<T> data) { super(); this.count = count; this.data = data; this.code = 0; }}

由于我用的是 layui 前端框架,我寫了一個返給 layui 表格的通用實體類,這是在實現數據字典需要用到的,判斷響應返回實體類的類型來判斷是否需要注入字典

四、開發實現

1、創建自定義注解

我們創建一個自定義注解 @Dict 來實現數據字典

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 數據字典注解 * * @author Tellsea * @date 2020/6/23 */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Dict { /** * 字典類型 * * @return */ String dictCode(); /** * 返回屬性名 * * @return */ String dictText() default '';}

2、注解實現

我們使用 aop 切面來實現什么的自定義注解 @Dict

import com.alibaba.fastjson.JSONObject;import com.fasterxml.jackson.annotation.JsonFormat;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.zyxx.common.annotation.Dict;import com.zyxx.common.utils.LayTableResult;import com.zyxx.common.utils.ObjConvertUtils;import com.zyxx.sbm.entity.SysDictDetail;import com.zyxx.sbm.service.SysDictService;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.lang.reflect.Field;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;/** * 數據字典切面 * * @author Tellsea * @date 2020/6/23 */@Aspect@Component@Slf4jpublic class DictAspect {/*** 字典后綴*/ private static String DICT_TEXT_SUFFIX = 'Text'; @Autowired private SysDictService sysDictService;/*** 切點,切入 controller 包下面的所有方法*/ @Pointcut('execution( * com.zyxx.*.controller.*.*(..))') public void dict() { } @Around('dict()') public Object doAround(ProceedingJoinPoint pjp) throws Throwable { long time1 = System.currentTimeMillis(); Object result = pjp.proceed(); long time2 = System.currentTimeMillis(); log.debug('獲取JSON數據 耗時:' + (time2 - time1) + 'ms'); long start = System.currentTimeMillis(); this.parseDictText(result); long end = System.currentTimeMillis(); log.debug('解析注入JSON數據 耗時' + (end - start) + 'ms'); return result; } private void parseDictText(Object result) { if (result instanceof LayTableResult) { List<JSONObject> items = new ArrayList<>(); LayTableResult rr = (LayTableResult) result; if (rr.getCount() > 0) {List<?> list = (List<?>) rr.getData();for (Object record : list) { ObjectMapper mapper = new ObjectMapper(); String json = '{}'; try { // 解決@JsonFormat注解解析不了的問題詳見SysAnnouncement類的@JsonFormat json = mapper.writeValueAsString(record); } catch (JsonProcessingException e) { log.error('Json解析失敗:' + e); } JSONObject item = JSONObject.parseObject(json); // 解決繼承實體字段無法翻譯問題 for (Field field : ObjConvertUtils.getAllFields(record)) { //解決繼承實體字段無法翻譯問題 // 如果該屬性上面有@Dict注解,則進行翻譯 if (field.getAnnotation(Dict.class) != null) { // 拿到注解的dictDataSource屬性的值 String dictType = field.getAnnotation(Dict.class).dictCode(); // 拿到注解的dictText屬性的值 String text = field.getAnnotation(Dict.class).dictText(); //獲取當前帶翻譯的值 String key = String.valueOf(item.get(field.getName())); //翻譯字典值對應的text值 String textValue = translateDictValue(dictType, key); // DICT_TEXT_SUFFIX的值為,是默認值: // public static final String DICT_TEXT_SUFFIX = '_dictText'; log.debug('字典Val: ' + textValue); log.debug('翻譯字典字段:' + field.getName() + DICT_TEXT_SUFFIX + ': ' + textValue); //如果給了文本名 if (!StringUtils.isBlank(text)) {item.put(text, textValue); } else {// 走默認策略item.put(field.getName() + DICT_TEXT_SUFFIX, textValue); } } // date類型默認轉換string格式化日期 if ('java.util.Date'.equals(field.getType().getName())&& field.getAnnotation(JsonFormat.class) == null&& item.get(field.getName()) != null) { SimpleDateFormat aDate = new SimpleDateFormat('yyyy-MM-dd HH:mm:ss'); item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName())))); } } items.add(item);}rr.setData(items); } } } /** * 翻譯字典文本 * * @param dictType * @param key * @return */ private String translateDictValue(String dictType, String key) { if (ObjConvertUtils.isEmpty(key)) { return null; } StringBuffer textValue = new StringBuffer(); String[] keys = key.split(','); for (String k : keys) { if (k.trim().length() == 0) {continue; } /** * 根據 dictCode 和 code 查詢字典值,例如:dictCode:sex,code:1,返回:男 * 應該放在redis,提高響應速度 */ SysDictDetail dictData = sysDictService.getDictDataByTypeAndValue(dictType, key); if (dictData.getName() != null) {if (!''.equals(textValue.toString())) { textValue.append(',');}textValue.append(dictData.getName()); } log.info('數據字典翻譯: 字典類型:{},當前翻譯值:{},翻譯結果:{}', dictType, k.trim(), dictData.getName()); } return textValue.toString(); }}

3、注解使用

我們只需要在實體類的屬性上加入我們實現的自定義注解即可

@ApiModelProperty(value = '性別(0--未知1--男2--女)')@TableField('sex')@Dict(dictCode = 'sex')private Integer sex;@ApiModelProperty(value = '狀態(0--正常1--凍結)')@TableField('status')@Dict(dictCode = 'status')private Integer status;

我們對 sex,status 都加入了 @Dict(dictCode = “”) 注解,那么我們在獲取用戶信息的時候,就能獲取到對應的字典值了

五、測試

1、編寫 API 查詢

我們在 controller 層開放一個 API 實現查詢用戶列表

/** * 分頁查詢 */@PostMapping('list')@ResponseBodypublic LayTableResult list(Integer page, Integer limit, SysUserInfo userInfo) { QueryWrapper<SysUserInfo> queryWrapper = new QueryWrapper<>(); if (StringUtils.isNotBlank(userInfo.getName())) { queryWrapper.like('name', userInfo.getName()); } if (null != userInfo.getSex()) { queryWrapper.eq('sex', userInfo.getSex()); } if (null != userInfo.getStatus()) { queryWrapper.eq('status', userInfo.getStatus()); } queryWrapper.orderByDesc('create_time'); IPage<SysUserInfo> iPage = sysUserInfoService.page(new Page<>(page, limit), queryWrapper); return new LayTableResult<>(iPage.getTotal(), iPage.getRecords());}

注意: 這里我們使用了 LayTableResult 作為相應實體類,與上面我們編寫的返回通用實體類是一致的,必須一直,才能實現數據字典功能

2、調用 API

返回結果如下:

{'code': 0,'msg': null,'count': 3,'data': [{'id': 2,'account': '15286779045','name': '周杰倫','sex': 1,'sexText': '男','status': 0,'statusText': '正常'}, {'id': 1,'name': '超級管理員','account': '15286779044','sex': 1,'sexText': '男','status': 0,'statusText': '正常'}]}

可以看出,返回的數據中,多出了 sexText,statusText,兩個屬性,也就證明我們的字典功能已經實現成功

六、總結

1、優點

1、在一定程度上,通過系統維護人員即可改變系統的行為(功能),不需要開發人員的介入。使得系統的變化更快,能及時響應客戶和市場的需求。2、提高了系統的靈活性、通用性,減少了主體和屬性的耦合度 3、簡化了主體類的業務邏輯 4、能減少對系統程序的改動,使數據庫、程序和頁面更穩定。特別是數據量大的時候,能大幅減少開發工作量5、使數據庫表結構和程序結構條理上更清楚,更容易理解,在可開發性、可擴展性、可維護性、系統強壯性上都有優勢。

2、缺點

1、數據字典是通用的設計,在系統效率上會低一些。2、程序算法相對復雜一些。3、對于開發人員,需要具備一定抽象思維能力,所以對開發人員的要求較高。

3、優化

我們的數據字典數據應該存放在 redis 中,減少與數據庫的交互次數,提高響應速度

到此這篇關于SpringBoot中實現數據字典的示例代碼的文章就介紹到這了,更多相關SpringBoot 數據字典內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
主站蜘蛛池模板: 考勤系统_考勤管理系统_网络考勤软件_政企|集团|工厂复杂考勤工时统计排班管理系统_天时考勤 | 回转支承-转盘轴承-回转驱动生产厂家-洛阳隆达轴承有限公司 | 不干胶标签-不干胶贴纸-不干胶标签定制-不干胶标签印刷厂-弗雷曼纸业(苏州)有限公司 | 不锈钢闸阀_球阀_蝶阀_止回阀_调节阀_截止阀-可拉伐阀门(上海)有限公司 | 苏州防水公司_厂房屋面外墙防水_地下室卫生间防水堵漏-苏州伊诺尔防水工程有限公司 | 一体式钢筋扫描仪-楼板测厚仪-裂缝检测仪-泰仕特(北京) | KBX-220倾斜开关|KBW-220P/L跑偏开关|拉绳开关|DHJY-I隔爆打滑开关|溜槽堵塞开关|欠速开关|声光报警器-山东卓信有限公司 | 土壤检测仪器_行星式球磨仪_土壤团粒分析仪厂家_山东莱恩德智能科技有限公司 | 开平机_纵剪机厂家_开平机生产厂家|诚信互赢-泰安瑞烨精工机械制造有限公司 | 恒温油槽-恒温水槽-低温恒温槽厂家-宁波科麦仪器有限公司 | 流量卡中心-流量卡套餐查询系统_移动电信联通流量卡套餐大全 | 闪电优家-卫生间防水补漏_酒店漏水渗水维修_防水堵漏公司 | 接地电阻测试仪[厂家直销]_电缆故障测试仪[精准定位]_耐压测试仪-武汉南电至诚电力设备 | 成都网站建设制作_高端网站设计公司「做网站送优化推广」 | 车充外壳,车载充电器外壳,车载点烟器外壳,点烟器连接头,旅行充充电器外壳,手机充电器外壳,深圳市华科达塑胶五金有限公司 | 专业广州网站建设,微信小程序开发,一物一码和NFC应用开发、物联网、外贸商城、定制系统和APP开发【致茂网络】 | 步进_伺服_行星减速机,微型直流电机,大功率直流电机-淄博冠意传动机械 | Magnescale探规,Magnescale磁栅尺,Magnescale传感器,Magnescale测厚仪,Mitutoyo光栅尺,笔式位移传感器-苏州连达精密量仪有限公司 | 篮球地板厂家_舞台木地板品牌_体育运动地板厂家_凯洁地板 | 百度网站优化,关键词排名,SEO优化-搜索引擎营销推广 | 手板-手板模型-手板厂-手板加工-生产厂家,[东莞创域模型] | 乙炔气体报警装置|固定式氯化氢检测仪|河南驰诚电气百科 | 寮步纸箱厂_东莞纸箱厂 _东莞纸箱加工厂-东莞市寮步恒辉纸制品厂 | 无味渗透剂,泡沫抑尘剂,烷基糖苷-威海威能化工有限公司 | 众品地板网-地板品牌招商_地板装修设计_地板门户的首选网络媒体。 | 长江船运_国内海运_内贸船运_大件海运|运输_船舶运输价格_钢材船运_内河运输_风电甲板船_游艇运输_航运货代电话_上海交航船运 | 广州中央空调回收,二手中央空调回收,旧空调回收,制冷设备回收,冷气机组回收公司-广州益夫制冷设备回收公司 | 档案密集架,移动密集架,手摇式密集架,吉林档案密集架-厂家直销★价格公道★质量保证 | 学习安徽网| 制丸机,小型中药制丸机,全自动制丸机价格-甘肃恒跃制药设备有限公司 | 走心机厂家,数控走心机-台州博城智能科技有限公司 | 环氧乙烷灭菌器_压力蒸汽灭菌器_低温等离子过氧化氢灭菌器 _低温蒸汽甲醛灭菌器_清洗工作站_医用干燥柜_灭菌耗材-环氧乙烷灭菌器_脉动真空压力蒸汽灭菌器_低温等离子灭菌设备_河南省三强医疗器械有限责任公司 | 危废处理系统,水泥厂DCS集散控制系统,石灰窑设备自动化控制系统-淄博正展工控设备 | 高考志愿规划师_高考规划师_高考培训师_高报师_升学规划师_高考志愿规划师培训认证机构「向阳生涯」 | 石牌坊价格石牌坊雕刻制作_石雕牌坊牌楼石栏杆厂家_山东嘉祥石雕有限公司 | 海南在线 海南一家| 模具ERP_模具管理系统_模具mes_模具进度管理_东莞市精纬软件有限公司 | 青海电动密集架_智能密集架_密集架价格-盛隆柜业青海档案密集架厂家 | 耐热钢-耐磨钢-山东聚金合金钢铸造有限公司 | 粉末冶金-粉末冶金齿轮-粉末冶金零件厂家-东莞市正朗精密金属零件有限公司 | 智能化的检漏仪_气密性测试仪_流量测试仪_流阻阻力测试仪_呼吸管快速检漏仪_连接器防水测试仪_车载镜头测试仪_奥图自动化科技 |