Jeecgboot 字典值自动转化:DictAspect类方法改造,支持IPage、List、Object、Map类自动转化,附有源码
改造的是DictAspect类:
原来使用的 parseDictText(Object result)方法,针对返回对象为Result 的IPage的分页列表数据进行动态字典注入,当单个对象查询,列表查询,或者多个数据放到Map中时,就不会自动转化,在web端进行展示的时候就需要连表查询或者手动查询字典值,不方便使用。
于是我改造了parseDictText()方法,不仅针对返回对象为Result时的分页列表,还支持列表、对象以及Map类型的结果。实在Result对象执行setResult()方式时进行自动注入转换。
原方法
代码:
private Object parseDictText(Object result) {//if (result instanceof Result) {if (true) {if (((Result) result).getResult() instanceof IPage) {List<JSONObject> items = new ArrayList<>();//step.1 筛选出加了 Dict 注解的字段列表List<Field> dictFieldList = new ArrayList<>();// 字典数据列表, key = 字典code,value=数据列表Map<String, List<String>> dataListMap = new HashMap<>(5);//取出结果集List<Object> records=((IPage) ((Result) result).getResult()).getRecords();//update-begin--Author:zyf -- Date:20220606 ----for:【VUEN-1230】 判断是否含有字典注解,没有注解返回-----Boolean hasDict= checkHasDict(records);if(!hasDict){return result;}log.debug(" __ 进入字典翻译切面 DictAspect —— " );//update-end--Author:zyf -- Date:20220606 ----for:【VUEN-1230】 判断是否含有字典注解,没有注解返回-----for (Object record : records) {String json="{}";try {//update-begin--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormatjson = objectMapper.writeValueAsString(record);//update-end--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----} catch (JsonProcessingException e) {log.error("json解析失败"+e.getMessage(),e);}//update-begin--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 -----JSONObject item = JSONObject.parseObject(json, Feature.OrderedField);//update-end--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 -----//update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------//for (Field field : record.getClass().getDeclaredFields()) {// 遍历所有字段,把字典Code取出来,放到 map 里for (Field field : oConvertUtils.getAllFields(record)) {String value = item.getString(field.getName());if (oConvertUtils.isEmpty(value)) {continue;}//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------if (field.getAnnotation(Dict.class) != null) {if (!dictFieldList.contains(field)) {dictFieldList.add(field);}String code = field.getAnnotation(Dict.class).dicCode();String text = field.getAnnotation(Dict.class).dicText();String table = field.getAnnotation(Dict.class).dictTable();//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------String dataSource = field.getAnnotation(Dict.class).ds();//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------List<String> dataList;String dictCode = code;if (!StringUtils.isEmpty(table)) {//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------dictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------}dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));}//date类型默认转换string格式化日期//update-begin--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----//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()))));//}//update-end--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----}items.add(item);}//step.2 调用翻译方法,一次性翻译Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap);//step.3 将翻译结果填充到返回结果里for (JSONObject record : items) {for (Field field : dictFieldList) {String code = field.getAnnotation(Dict.class).dicCode();String text = field.getAnnotation(Dict.class).dicText();String table = field.getAnnotation(Dict.class).dictTable();//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------// 自定义的字典表数据源String dataSource = field.getAnnotation(Dict.class).ds();//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------String fieldDictCode = code;if (!StringUtils.isEmpty(table)) {//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------fieldDictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------}String value = record.getString(field.getName());if (oConvertUtils.isNotEmpty(value)) {List<DictModel> dictModels = translText.get(fieldDictCode);if(dictModels==null || dictModels.size()==0){continue;}String textValue = this.translDictText(dictModels, value);log.debug(" 字典Val : " + textValue);log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue);// TODO-sun 测试输出,待删log.debug(" ---- dictCode: " + fieldDictCode);log.debug(" ---- value: " + value);log.debug(" ----- text: " + textValue);log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels));record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);}}}((IPage) ((Result) result).getResult()).setRecords(items);}}return result;}
改造
判断传递参数的类型,是IPage、List、Map、Object,如果是IPage、List、Map,则把对象中的数据拿出来再挨个转换,改造为新的结果数据返回。
private Object parseDictText(Object result) {if (result instanceof Result) {List<Object> list = new LinkedList<>();if (((Result) result).getResult() instanceof IPage) {//分页list = ((IPage) ((Result) result).getResult()).getRecords();} else if (((Result) result).getResult() instanceof List) {//List集合list = (List<Object>) ((Result) result).getResult();} else if (((Result) result).getResult() instanceof Map) {//mapMap<Object, Object> map = (Map<Object, Object>) ((Result) result).getResult();Map<Object, Object> itemMap = new HashMap<>();for (Map.Entry entry : map.entrySet()) {//System.out.println(entry.getKey() + " " + entry.getValue());Map mapRe = new HashMap();if (entry.getValue() instanceof List) {//列表List<Object> listItems = new ArrayList<>();for (Object record : (List) entry.getValue()) {if (checkIsJsonStr(record)) {//字典翻译record = this.dictEscape(record);}listItems.add(record);}itemMap.put(entry.getKey(), listItems);} else if (entry.getValue() instanceof Object) {//单对象Object record = entry.getValue();//判断能否转换成JSON,因为有些结果集返回的是String类型,导致翻译异常,因此判断是否可以转换jsonif (checkIsJsonStr(record)) {//字典翻译record = this.dictEscape(record);}itemMap.put(entry.getKey(), record);}}((Result) result).setResult(itemMap);} else {//单对象Object record = ((Result) result).getResult();//判断能否转换成JSON,因为有些结果集返回的是String类型,导致翻译异常,因此判断是否可以转换jsonif (checkIsJsonStr(record)) {//字典翻译record = this.dictEscape(record);}((Result) result).setResult(record);}//列表解析if (list != null && list.size() > 0) {List<Object> items = new ArrayList<>();for (Object record : list) {if (checkIsJsonStr(record)) {//字典翻译record = this.dictEscape(record);}items.add(record);}if (((Result) result).getResult() instanceof IPage) {((IPage) ((Result) result).getResult()).setRecords(items);} else if (((Result) result).getResult() instanceof List) {((Result) result).setResult(items);}}}return result;}
字典翻译方法:
/*** 字典翻译** @param record* @return*/private JSONObject dictEscape(Object record) {ObjectMapper mapper = new ObjectMapper();String json = "{}";JSONObject item = null;try {//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormatjson = mapper.writeValueAsString(record);//对象序列化为JSON字符串} catch (JsonProcessingException e) {log.error("json解析失败" + e.getMessage(), e);}try {item = JSONObject.parseObject(json);//update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------for (Field field : oConvertUtils.getAllFields(record)) {//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------if (field.getAnnotation(Dict.class) != null) {String code = field.getAnnotation(Dict.class).dicCode();String text = field.getAnnotation(Dict.class).dicText();String table = field.getAnnotation(Dict.class).dictTable();String key = String.valueOf(item.get(field.getName()));//翻译字典值对应的txtString textValue = key;//非中文时翻译if (!checkCountName(key)) {textValue = translateDictValue(code, text, table, key);}log.debug(" 字典Val : " + textValue);log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue);item.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);}//date类型默认转换string格式化日期if (field.getType().getName().equals("java.util.Date") && 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()))));}}} catch (Exception e) {log.info("字典翻译异常:" + e.getMessage(), e);}return item;}
检测是否是中文:
/*** 检测是否是中文** @param countName* @return*/public static boolean checkCountName(String countName) {Pattern p = Pattern.compile("[\u4e00-\u9fa5]");Matcher m = p.matcher(countName);if (m.find()) {return true;}return false;}
检测是否可转换为JSON字符串
/*** 检测是否可转换为JSON字符串** @param record* @return*/public static boolean checkIsJsonStr(Object record) {boolean jsonFlag = false;try {String json = new ObjectMapper().writeValueAsString(record);if (json.startsWith("{")) {jsonFlag = true;}} catch (JsonProcessingException e) {e.printStackTrace();}return jsonFlag;}
相关文章:
Jeecgboot 字典值自动转化:DictAspect类方法改造,支持IPage、List、Object、Map类自动转化,附有源码
改造的是DictAspect类: 原来使用的 parseDictText(Object result)方法,针对返回对象为Result 的IPage的分页列表数据进行动态字典注入,当单个对象查询,列表查询,或者多个数据放到Map中时,就不会自动转化&am…...

DVWA DOM Based Cross Site Scripting (DOM型 XSS)
DVWA DOM Based Cross Site Scripting (DOM型 XSS) 文章目录 DVWA DOM Based Cross Site Scripting (DOM型 XSS)XSS跨站原理DOM型 LowMediumHighImpossible XSS跨站原理 当应用程序发送给浏览器的页面中包含用户提交的数据,但没有经过适当验证或转义时,就…...

LinkedList集合及迭代器的源码分析
一.介绍: 二.LinkedList集合特有的API: 三.迭代器的源码分析: package com.itheima.a03myarraylist;import java.util.ArrayList; import java.util.Iterator;public class A01_ArrayListDemo1 {public static void main(String[] args) {ArrayList<String> listnew Arr…...

Go调度器
线程数过多,意味着操作系统会不断地切换线程,频繁的上下文切换就成了性能瓶颈.Go提供一种机制 可以在线程中自己实现调度,上下文切换更轻量,从而达到线程数少,而并发数并不少的效果,而线程中调度的就是Goroutine 调度器主要概念: 1.G:即Go协程,每个go关键字都会创建一个协程…...
当node节点kubectl 命令无法连接到 Kubernetes API 服务器
1.问题 当node节点当node节点kubectl 命令无法连接到 Kubernetes API 服务器 [rootnode1 ~]# kubectl get nodes The connection to the server localhost:8080 was refused - did you specify the right host or port?2. 确认 kubeconfig 文件 确保节点上有有效的 kubeco…...

直接通过类CURL方式,与GRPC方法交互的命令行工具
大家好,今天给大家分享的是一个命令行工具grpcurl,它能够直接与 gRPC 服务进行交互。 项目介绍 您可以把grpcurl想象成是 curl 的 gRPC 版本,但是功能更加强大。 由于 gRPC 服务之间的通信使用的是 Protocol Buffers (Protobuf) 格式的二进…...

Hive3:数据的加载与导出
一、加载数据 在创建表之后,表中没有数据,我们不可能insert存入数据。 而是,通过数据加载,将HDFS中的数据关联到Hive表中。 建表 CREATE TABLE myhive.test_load(dt string comment 时间(时分秒), user_…...
React事件绑定的方式有哪些?区别?
React 中事件绑定的方式主要有以下几种: 直接在 JSX 中绑定事件: <button onClick{handleClick}>Click me</button> 这是最常见和推荐的方式。事件名(如 onClick)作为 JSX 的属性,值为一个函数,…...

ibis:极具潜力的Python数据分析新框架
今天要给大家介绍的Python框架叫做ibis,没错,跟著名连锁酒店宜必思同名,其作者是创造了pandas、Arrow等著名框架的Wes McKinney。 ibis的核心理念是用同一套数据框操作API,统一操纵各种主流的数据运算框架,使得用户可以…...

SQL Zoo 8+.NSS Tutorial
以下数据来自SQL Zoo 1.at Edinburgh Napier University,studying (8) Computer Science,Show the the percentage who STRONGLY AGREE.(在爱丁堡纳皮尔大学,学习“计算机科学”,显示STRONGLY AGREE的百分比࿰…...

conda pack迁移环境
文章目录 下载conda pack打包已有环境还原环境 因为有的服务器没有网络,如果想要安装自己的虚拟环境,就需要在有网络的服务器安装好环境后迁移到没有网络的服务器。conda-pack是一个命令行工具,用于打包 conda 环境,pip inatall和…...

UML建模案例分析-活动图商业建模
概述 活动图主要用来描述如何完成工作以及做什么工作。可以用活动图来描述操作、类或 用例,但是它们只能显示工作流。可以用活动图来进行商业建模,在模型中,工作、工 人、组织、对象被显示。 案例 在商业建模时,下列方面是模型要…...
C++标准模板(STL)- 低层内存管理 - 解分配函数 (operator delete, operator delete[])
低层内存管理 new 表达式是创建拥有动态存储期对象或对象数组的仅有方式,即它们拥有不受制于创建所它们在的作用域的生存期。 new 表达式通过调用分配函数获得存储。 delete 表达式销毁最终导出对象或通过 new 表达式创造的数组,然后调用解分配函数。默认…...

LeetCode 热题 HOT 100 (025/100)【宇宙最简单版】
【二叉树】No. 0124 二叉树中的最大路径和 【困难】👉力扣对应题目指路 希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦 欢迎关注、订阅专栏 【力扣详解】谢谢你…...

【mysql 第三篇章】一条 update语句是怎么持久化到磁盘上的?
首先看一下这个 SQL 语句你会不会写? 下面是说明执行这个 SQL 语句,数据库底层做了什么操作。 update users set namexxx where id10;在引擎要执行更新语句的时候,比如更新 id10 这行数据时,他会先查看数据在缓冲池中是否存在,如…...

深入探索大模型:从基础到实践,开启AI之旅
摘要: 在人工智能领域,大模型技术正成为推动创新和进步的关键力量。对于初学者而言,掌握大模型的基本概念、理论和技术是至关重要的。 本文将为你提供一个全面的学习路线,帮助你从基础知识出发,逐步深入到大模型的实践…...
题解:力扣1567 - 返回乘积为正数的最长子数组
问题描述 给定一个整数数组 nums,找出乘积为正数的最长子数组的长度。这里的子数组定义为连续元素的序列,乘积为正数指子数组中正数的个数必须大于负数的个数。 解题思路 为了解决这个问题,我们可以使用两个数组 f 和 g 分别表示以当前位置…...

009 | 上证50ETF基金数据分析及预测
项目背景 中国股市的发展历程坎坷,从最初的茫然到现在的逐步成熟,股市已经成为中国经济发展的重要标志之一。然而,当前中国股市仍存在投机行为过度和定价机制不完善等问题。为更好地理解和预测股市走势,本项目聚焦于上证50ETF基金的历史数据分析和未来走势预测。 项目目标…...

Wakanda: 1靶场复现【附代码】(权限提升)
靶机下载地址: wakanda: 1 ~ VulnHubwakanda: 1, made by xMagass. Download & walkthrough links are available.https://www.vulnhub.com/entry/wakanda-1,251/#download 1. 主机发现端口扫描目录扫描敏感信息获取 1.1. 主机发现 nmap -sn 192.168.7.0/24…...
内核函数调试
要进入 bind 函数的内部进行调试,实际上是不能直接在用户空间代码中进入内核内部的 bind 实现,因为 bind 是一个系统调用,它由内核处理。尽管如此,你可以通过以下几种方法来间接调试 bind 函数并理解它的行为: 1. 使用…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...