- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章SpringBoot中实现数据字典的示例代码由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
我们在日常的项目开发中,对于数据字典肯定不模糊,它帮助了我们更加方便快捷地进行开发,下面一起来看看在 SpringBoot 中如何实现数据字典功能的 。
1、简介 。
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 找到唯一的字典值 。
2、数据表设计 。
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 '描述', status tinyint(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 '字典配置表';
它们的关系如图所示:
2、数据字典配置 。
3、开发前戏 。
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 表格的通用实体类,这是在实现数据字典需要用到的,判断响应返回实体类的类型来判断是否需要注入字典 。
4、开发实现 。
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 = “”) 注解,那么我们在获取用户信息的时候,就能获取到对应的字典值了 。
5、测试 。
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,两个属性,也就证明我们的字典功能已经实现成功 。
6、总结 。
1、优点 。
1、在一定程度上,通过系统维护人员即可改变系统的行为(功能),不需要开发人员的介入。使得系统的变化更快,能及时响应客户和市场的需求。 2、提高了系统的灵活性、通用性,减少了主体和属性的耦合度 3、简化了主体类的业务逻辑 4、 能减少对系统程序的改动,使数据库、程序和页面更稳定。特别是数据量大的时候,能大幅减少开发工作量 5、使数据库表结构和程序结构条理上更清楚,更容易理解,在可开发性、可扩展性、可维护性、系统强壮性上都有优势.
2、缺点 。
1、数据字典是通用的设计,在系统效率上会低一些。 2、程序算法相对复杂一些。 3、对于开发人员,需要具备一定抽象思维能力,所以对开发人员的要求较高.
3、优化 。
我们的数据字典数据应该存放在 redis 中,减少与数据库的交互次数,提高响应速度 。
到此这篇关于SpringBoot中实现数据字典的示例代码的文章就介绍到这了,更多相关SpringBoot 数据字典内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/qq_40065776/article/details/107403576 。
最后此篇关于SpringBoot中实现数据字典的示例代码的文章就讲到这里了,如果你想了解更多关于SpringBoot中实现数据字典的示例代码的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Sample data for IPv6? 除了 wireshark 在其网站上提供的内容之外,是否有可以下
我正在寻找可以集成到现有应用程序中并使用多拖放功能的示例或任何现成的解决方案。我在互联网上找到的大多数解决方案在将多个项目从 ListBox 等控件拖放到另一个 ListBox 时效果不佳。谁能指出我
我是 GATE Embedded 的新手,我尝试了简单的示例并得到了 NoClassDefFoundError。首先我会解释我尝试了什么 在 D:\project\gate-7.0 中下载并提取 Ga
是否有像 Eclipse 中的 SWT 示例那样的多合一 JFace 控件示例?搜索(在 stackoverflow.com 上使用谷歌搜索和搜索)对我没有帮助。 如果它是一个独立的应用程序或 ecl
我找不到任何可以清楚地解释如何通过 .net API(特别是 c#)使用谷歌计算引擎的内容。有没有人可以指点我什么? 附言我知道 API 引用 ( https://developers.google.
最近在做公司的一个项目时,客户需要我们定时获取他们矩阵系统的数据。在与客户进行对接时,提到他们的接口使用的目前不常用的BASIC 认证。天呢,它好不安全,容易被不法人监听,咋还在使用呀。但是没办法呀,
最近在做公司的一个项目时,客户需要我们定时获取他们矩阵系统的数据。在与客户进行对接时,提到他们的接口使用的目前不常用的BASIC 认证。天呢,它好不安全,容易被不法人监听,咋还在使用呀。但是没办法呀,
我正在尝试为我的应用程序设计配置文件格式并选择了 YAML。但是,这(显然)意味着我需要能够定义、解析和验证正确的 YAML 语法! 在配置文件中,必须有一个名为 widgets 的集合/序列。 .这
你能给我一个使用 pysmb 库连接到一些 samba 服务器的例子吗?我读过有类 smb.SMBConnection.SMBConnection(用户名、密码、my_name、remote_name
linux服务器默认通过22端口用ssh协议登录,这种不安全。今天想做限制,即允许部分来源ip连接服务器。 案例目标:通过iptables规则限制对linux服务器的登录。 处理方法:编
我一直在寻找任何 PostProjectAnalysisTask 工作代码示例,但没有看。 This页面指出 HipChat plugin使用这个钩子(Hook),但在我看来它仍然使用遗留的 Po
我发现了 GWT 的 CustomScrollPanel 以及如何自定义滚动条,但我找不到任何示例或如何设置它。是否有任何示例显示正在使用的自定义滚动条? 最佳答案 这是自定义 native 滚动条的
我正在尝试开发一个 Backbone Marionette 应用程序,我需要知道如何以最佳方式执行 CRUD(创建、读取、更新和销毁)操作。我找不到任何解释这一点的资源(仅适用于 Backbone)。
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题?通过 editing this post 添加详细信息并澄清问题. 去年关闭。 Improve this
我需要一个提交多个单独请求的 django 表单,如果没有大量定制,我找不到如何做到这一点的示例。即,假设有一个汽车维修店使用的表格。该表格将列出商店能够进行的所有可能的维修,并且用户将选择他们想要进
我有一个 Multi-Tenancy 应用程序。然而,这个相同的应用程序有 liquibase。我需要在我的所有数据源中运行 liquibase,但是我不能使用这个 Bean。 我的应用程序.yml
我了解有关单元测试的一般思想,并已在系统中发生复杂交互的场景中使用它,但我仍然对所有这些原则结合在一起有疑问。 我们被警告不要测试框架或数据库。好的 UI 设计不适合非人工测试。 MVC 框架不包括一
我正在使用 docjure并且它的 select-columns 函数需要一个列映射。我想获取所有列而无需手动指定。 如何将以下内容生成为惰性无限向量序列 [:A :B :C :D :E ... :A
$condition使用说明和 $param在 findByAttributes在 Yii 在大多数情况下,这就是我使用 findByAttributes 的方式 Person::model()->f
我在 Ubuntu 11.10 上安装了 qtcreator sudo apt-get install qtcreator 安装的版本有:QT Creator 2.2.1、QT 4.7.3 当我启动
我是一名优秀的程序员,十分优秀!